Почему-то не отображаются актуальные данные из JSON файла которые тяну с сайта RBC. Создал класс в MainActivity:
private class GetRbcExchangeRates extends AsyncTask<String, String, String> {
public ArrayList<CurrencyRateModel> listOfCurrency = new ArrayList<>();
private final String httpAddress = "https://www.cbr-xml-daily.ru/daily_json.js";
@Override
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader bufferedReader = null;
StringBuilder jSonResult = new StringBuilder();
//listOfCurrency = new ArrayList<>();
try {
URL url = new URL(httpAddress);
connection = (HttpURLConnection)url.openConnection();
connection.connect();
bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = "";
while((line = bufferedReader.readLine()) != null) {
jSonResult.append(line);
}
}
catch(Exception e) {
e.printStackTrace();
publishProgress("MESSAGE", "Отсутствует подключение к интернет!");
}
finally {
if(connection != null)
connection.disconnect();
try {
if(bufferedReader !=null)
bufferedReader.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
try {
JSONObject rbcGETRates = new JSONObject(jSonResult.toString());
JSONObject jSonValute = rbcGETRates.getJSONObject("Valute");
Iterator<String> arrayKey = jSonValute.keys();
while(arrayKey.hasNext()) {
String key = arrayKey.next();
JSONObject jSonItem = jSonValute.getJSONObject(key);
CurrencyRateModel currencyitems = new CurrencyRateModel();
currencyitems.id = jSonItem.getString("ID");
currencyitems.nameCode = jSonItem.getString("NumCode");
currencyitems.charCode = jSonItem.getString("CharCode");
currencyitems.nominal = jSonItem.getInt("Nominal");
currencyitems.name = jSonItem.getString("Name");
currencyitems.value = jSonItem.getDouble("Value");
currencyitems.previous = jSonItem.getDouble("Previous");
listOfCurrency.add(currencyitems);
}
}
catch (JSONException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
ListView lsView = (ListView)findViewById(R.id.currencyView);
MyAdapter myAdapter = new MyAdapter(MainActivity.this, listOfCurrency);
lsView.setAdapter(myAdapter);
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if(values[0].equals("MESSAGE")) {
Toast.makeText(MainActivity.this, values[1], Toast.LENGTH_LONG).show();
}
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
Класс - Модель с полями:
public class CurrencyRateModel {
public String id;
public String nameCode;
public String charCode;
public int nominal;
public String name;
double value;
double previous;
}
И адаптер:
public class MyAdapter extends BaseAdapter {
private Context ctx;
private ArrayList<CurrencyRateModel> arrayList;
private LayoutInflater inflater;
public MyAdapter(Context ctx, ArrayList<CurrencyRateModel> arrayList) {
this.ctx = ctx;
this.arrayList = arrayList;
inflater = ((Activity)ctx).getLayoutInflater();
}
@Override
public int getCount() {
return arrayList.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh;
if(convertView == null) {
vh = new ViewHolder();
convertView = inflater.inflate(R.layout.itemcurrency, null);
vh.tvTitle = (TextView)convertView.findViewById(R.id.title);
vh.tvDescription = (TextView)convertView.findViewById(R.id.description);
convertView.setTag(vh);
}
else {
vh = (ViewHolder) convertView.getTag();
vh.tvTitle.setText("1");
vh.tvDescription.setText("2");
}
return convertView;
}
static class ViewHolder {
TextView tvTitle, tvDescription;
}
}
В методе onCreate делаю так:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// async TASK Run
GetRbcExchangeRates async = new GetRbcExchangeRates();
async.execute();
}
Так же создан отдельный ресурс файл c 2 TextView:
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22sp"/>
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="#555"/>
Отладку произвожу на планшете с Lollipop 5.1. При запуске пустота, если свернешь приложение, а после снова разворачиваешь, в ListView записываются цифры 1 и 2 (что в адаптере в блоке else); При отладке видно, что в структуру данных записываются валидные распарсенные данные из сайта, какая то проблема в отображении данных. Я вывел в лог:
Что я делаю не так. Буду благодарен за любую помощь, так как всего пару недель щупаю эту платформу.
Код по обработке данных (вывод на экран), полученных в асинхронном потоке, должен выполнятся в методе onPostExecute()
- выполнить после завршения потока, то есть, когда данные сформированы.
В адаптере вместо
vh.tvTitle.setText("1");
логично предположить, что нужно выводить данные для этой позиции, а не хардкорный текст - 1.
vh.tvTitle.setText(arrayList.get(position).name);
целиком метод getView()
(не знаю, что нужно выводить в description, пусть будет значение value
) + комментарии, что именно там происходит и исправленное условие (закрывающая скобка не в том месте была):
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh;
if(convertView == null) {
// создаем объект-холдер для кэширования ссылок на виджеты
vh = new ViewHolder();
// получаем объект айтема списка, который парсим из xml-разметки
convertView = inflater.inflate(R.layout.itemcurrency, null);
// получаем ссылки на виджеты в айтеме
vh.tvTitle = (TextView)convertView.findViewById(R.id.title);
vh.tvDescription = (TextView)convertView.findViewById(R.id.description);
// сохраняем холдер для переиспользования
convertView.setTag(vh);
}
else {
// получаем холдер с кэшированными ссылками на виджеты
vh = (ViewHolder) convertView.getTag();
}
// в виджеты айтема выводим данные согласно текущей позиции в списке
vh.tvTitle.setText(arrayList.get(position).name);
vh.tvDescription.setText(Double.toString(arrayList.get(position).value));
return convertView;
}
Числовой тип должен быть преобразован в String
перед передачей в метод setText()
.
Подробнее о устройстве адаптера с холдером
Метод getItem()
не должен возвращать null, он должен возвращать содержимое айтема (данные для него):
@Override
public CurrencyRateModel getItem(int position) {
return arrayList.get(position);
}
Так же в модели данных стоит подумать о геттерах/сеттерах, в Java это считается хорошим тоном.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Странный вопрос, но в голову больше ничего не лезетЧто ещё можно сделать если id меньше 0 или имя фамилия пустые?
Привет всем! Как можно перебрать все элементы Deque и Queue как в массиве?
ЭкспериментируюЗапустил Активити, а через него перехожу на второе активити, в нем запускаю AsyncTask
Вопрос такойЯ Android разработчик, пишу на котлине