-1

In my CountryInfoActivity.java I have an Async Class which retrieves a JSON from this website: https://pt.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=Portugal. It then parses the extract node into a String so I can set it in my TextView. The problem is, whenever I set the text in the text view, my app crashes. The JSON parse is correct as it is retrieving all the information I want...

These are the classes I use to retrieve the data and, in the last one I try to set the data textoSobrePais into my TextView... By the way, in my onCreate method I called the class this way new DownloadTask().execute(url);

public class DownloadTask extends AsyncTask<String,Integer,Void>{
@Override
protected Void doInBackground(String... params) {
    String url = params[0];
    getJSONFromURL(url);
    return null;
}
}



public String getJSONFromURL(String url){
    String json_string = null;
    try{
        URL obj = new URL(url);
        HttpURLConnection http = (HttpURLConnection) obj.openConnection();
        http.setRequestMethod("GET");
        int response = http.getResponseCode();
        Log.i("response",Integer.toString(response));
        BufferedReader reader  = new BufferedReader(new InputStreamReader(http.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine())!= null){
            sb.append(line+"\n");
        }
        reader.close();

        json_string = sb.toString();
        Log.i("json_string",json_string);
    } catch (UnsupportedEncodingException e){
        e.printStackTrace();
    } catch (ClientProtocolException e){
        e.printStackTrace();
    } catch (IOException e){
        e.printStackTrace();
    }
    ParseJson(json_string);
    return null;


}


public void ParseJson (String json){

JSONObject obj = null;
try {
    obj = new JSONObject(json);
} catch (JSONException e) {
    e.printStackTrace();
}
try {
    JSONArray pageIdObj = obj.getJSONObject("query").getJSONObject("pages").names();
    String page =  String.valueOf(pageIdObj.get(0));
    Log.i("ASdasd",page);
    textoSobrePais = obj.getJSONObject("query").getJSONObject("pages").getJSONObject(page).getString("extract");
    page = "";
    Log.i("texte",textoSobrePais);
    txtInfoPais = findViewById(R.id.txtInfoPais);
    txtInfoPais.setText(textoSobrePais);
} catch (JSONException e) {
    e.printStackTrace();
}

}

This is the error that is giving me when it crashes: https://pastebin.com/PJh5r36u

Can somebody help, please?

André Silva
  • 121
  • 11
  • 1
    Every answer which gives you idea about to move your code-snippet to run on UI thread is horrible. Try to learn about other callback methods of AsynTask and then do it yourself. – Pankaj Kumar Jul 04 '18 at 09:14
  • @PankajKumar Why is it horrible? Can you be more specific? – André Silva Jul 04 '18 at 09:18

2 Answers2

3

We can't update UI from Background Thread. You have to set text on main thread

Run on main thread like this

runOnUiThread(new Runnable() {
            @Override
            public void run() {
                txtInfo.setText(textoPais);
            }
 });
PinkeshGjr
  • 8,460
  • 5
  • 41
  • 56
Arti Patel
  • 671
  • 4
  • 15
  • I've tried that and it doesn't crash, I set them after I call the class... The problem is, it runs even when the AsyncTask is running (because it is in doInBackground) so, I need it to run just when the AsyncTask has run completely... – André Silva Jul 04 '18 at 09:17
1

You cannot update UI components from non-UI Thread. Run the update of TextView on UI thread as follows:

 runOnUiThread(new Runnable() {
            @Override
            public void run() {
                txtInfoPais.setText(textoSobrePais);
            }
 });
Sagar
  • 23,903
  • 4
  • 62
  • 62