Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't update android listview in onPostExecute

I have this in my onCreate method:

String[] myStringArray = {"a","b","c","a","b","c","a","b","c","a","b","c","a","b","c","a","b","c"};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_top_jokes);        

    new loadJson().execute();

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
            android.R.layout.simple_list_item_1, myStringArray);

    ListView listView = (ListView) findViewById(R.id.topJokesList);
    listView.setAdapter(adapter);

    listView.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            // When clicked, show a toast with the TextView text
            Toast.makeText(getApplicationContext(),
            ((TextView) view).getText(), Toast.LENGTH_SHORT).show();
        }
    });

}

The above code populates a listView with the content of myStringArray, for now everything is ok. The problem comes when I call new loadJson().execute(); it executes fine and here is the method's code:

public class loadJson extends AsyncTask<Void, Integer, String>{

@Override
protected String doInBackground(Void... params) {
    URL u;
    StringBuffer buffer = new StringBuffer();
    try {
    u = new URL("https://website.com/content/showContent.php");
    URLConnection conn = u.openConnection();
    BufferedReader in = new BufferedReader(
                            new InputStreamReader(
                                conn.getInputStream()));

    String inputLine;
    while ((inputLine = in.readLine()) != null) 
        buffer.append(inputLine);
    in.close();

    }catch(Exception e){
        e.printStackTrace();
    }
    return buffer.toString();
}

protected void onPostExecute(String buffer) {
    JSONArray jsonArray = new JSONArray();
    try {
        jsonArray = new JSONArray(buffer);
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println("JSONarray: " + jsonArray);
    String[] newArray = null;
    for (int i = 0; i < jsonArray.length(); i++) {
        try {

        newArray[i] = jsonArray.getJSONObject(i).toString();
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    myStringArray = newArray;
 }

}

As you can see I'm updating the hardcoded content of myStringArray with the new values fetched into newArray. Now I'm unable to see the new content. I know it's there, but how can I tell to the current activity: "Hey, I updated your array, please show it!" ?

I know that I'm missing something really small, but as a beginner, I'm not able to spot it.

like image 620
chility Avatar asked Dec 25 '22 13:12

chility


1 Answers

I found the answer to this question because I was searching for the answer myself. There are a few close answers here, but they leave out pieces which will never get you to the answer.

First of all add two member variables to your AsyncTask class:

private ListView listView;
private Activity activity;

Next, add a constructor to you AsyncTask class which takes an Activity:

  public loadJson(Activity activity) {
        this.activity = activity;
    }

Now, when you new up your AsyncTask class and call execute() you will add the reference to the Activity which called it (the this value passed in when you construct your AsyncTask class).

new loadJson(this).execute(param);

Finally, back in your AsyncTask you will write the code for your postExecute() which looks like the following:

protected void onPostExecute(String output) {
        listView = (ListView) activity.findViewById(R.id.targetListView);
        ArrayAdapter<String> adapter = (ArrayAdapter<String>)listView.getAdapter();
        adapter.add(output);
        adapter.notifyDataSetChanged();
    }

You have to have a reference to your Activity so you can call the findViewById. Note that the targetListView is the id of your ListView which is on your original Activity.

We've sent that Activity into the AsyncTask's constructor so it is available. Now you can get the Adapter and add your value to you and call notifyDataSetChanged() so it will update on your UI.

I'm using this code in my solution and it works great.

like image 148
raddevus Avatar answered Jan 06 '23 18:01

raddevus