For some reason, the actual data from the JSON file that I pull from the RBC site is not displayed. Created a class in 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); } } 

Class - Model with fields:

 public class CurrencyRateModel { public String id; public String nameCode; public String charCode; public int nominal; public String name; double value; double previous; 

}

And adapter:

 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; } 

}

In the onCreate method, I do this:

  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // async TASK Run GetRbcExchangeRates async = new GetRbcExchangeRates(); async.execute(); } 

Also created a separate resource file 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"/> 

I make debugging on a tablet with Lollipop 5.1. When you start the void, if you turn the application, and then deploy it again, the numbers 1 and 2 are written in the ListView (which is in the adapter in the else block); When debugging, you can see that valid parsed data from the site is written to the data structure, which is a problem in displaying the data. I brought to the log:

enter image description here

What am I doing wrong. I would be grateful for any help, as I have been feeling this platform for only a couple of weeks.

  • Transfer the code from onPreExecute to onPostExecute and add the fourth line: myAdapter.notifyDataSetChanged() . - post_zeew
  • I did as you said, now such a problem, when you start the application, the data in the ListView is output from the else block of the @Override method Public View getView (int position, View convertView, ViewGroup parent). If you remove the check and comment out the else block, then an empty ListView is displayed. - JDo
  • what do you expect should appear, except for 1 and 2, if you yourself have explicitly indicated to output these numbers? - pavlofff
  • Why obviously? This is for me to check, in theory, if the View (the one that convertView) is empty, then I pull from Json, otherwise the numbers 1.2 are just for debugging, see what's in ListView. So, I already wrote that I remove the else block and leave only: 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); 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); - JDo
  • In the list there appears what you set as a setter for widgets (using the setText() method), nothing happens in the first block except caching, no data is output there and not even present, why do you think something is pulling from JSON? - pavlofff

1 answer 1

The data processing code (output to the screen) received in the asynchronous stream should be executed in the onPostExecute() method β€” execute after the end of the stream, that is, when the data is generated.

In the adapter instead

 vh.tvTitle.setText("1"); 

It is logical to assume that you need to display data for this position, and not hardcore text - 1.

  vh.tvTitle.setText(arrayList.get(position).name); 

the whole getView() method (I don’t know what to display in the description, let it be the value value ) + comments, what exactly is happening and the corrected condition (the closing bracket was in the wrong place):

 @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; } 

The numeric type must be converted to a String before being passed to the setText() method.

More information about the device adapter with holder

The getItem() method should not return null, it should return the contents of the item (data for it):

 @Override public CurrencyRateModel getItem(int position) { return arrayList.get(position); } 

Also in the data model you should think about getters / setters, in Java this is considered a good form.

  • Thank you for the property you correctly noted. I’m just a long Codil on C # and there are very convenient getters and setters. In Java, I haven’t dealt with them yet and quickly applied fields to the model - I will correct it as soon as I see the data in the ListView. Left only the context transfer in View - `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); `And empty .... - JDo
  • you still have one brace there not in the condition - pavlofff
  • one
    That the data appeared in the list - they need to be placed there (explicitly indicate which data exactly which widget needs to be output) you do not do anything for this and why do you think that they themselves will fit where they are, but in android There is no binding, as in C #. - pavlofff
  • Thank! It all worked. I will now refactor! - JDo