Android: Refresh ListView in first activity on return from second activity

13,769

Solution 1

well right off the bat, you could easily knock this away with a simple conditional statement that performs the command only if the adapter isn't null:

    if (adapter != null) {
        adapter.notifyDataSetChanged();
    }

But this seems to me like, at a deeper level, your code could be re-factored somewhat to be more efficient, though not necessarily more functional.


do it like this:

private int id = 1;
private ListView listView;
private CustomArrayAdapter arrayAdapter;
private ArrayList<String> list = new ArrayList<String>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
}

@Override
public void onResume() {
    super.onResume();
    populateList();
}

private void populateList() {

    ArrayList<Item> objectList;
    try {
        objectList = new GetAsyncTask(id).execute();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        e.printStackTrace();
    }

    list.clear();
    for (int i = 0; i <objectList.size(); i++) {
        String name = objectList.get(i).getName();
        list.add(name);
    }
    if (arrayAdapter == null) {
        arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item, list);
        listView.setAdapter(arrayAdapter);
    } else {
        arrayAdapter.notifyDataSetChanged();            
    }
}

Solution 2

I catch the list_of_files from device and put it in a list in populateList(). Then I apply adapter. On return that list on device is changed so it again does the same and put it in a list. The problem is in ListView there are still old items and new items are just added at the end. So it's duplicated.

One basic approach is to call list.clear() before adding the new data. This should erase the old data and prevent duplicates. (But it's hard to provide an exact answer without seeing the code in question...)


Addition
You should add this code to your onPostExecute() method inside GetAsyncTask:

int size = objectList.size();
String name;

list.clear(); // or list = new ArrayList<String>();
for (int i = 0; i < size; i++) {
    name = objectList.get(i).getName();
    list.add(name);
}

arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item, list);
listView.setAdapter(arrayAdapter);

Unless GetAsyncTask is nested in your Activity, you will need to move a few variables to GetAsyncTask use this. But this approach is better because it doesn't force the Activity to wait for results (which might cause an "Application Not Responding" error.)

Share:
13,769

Related videos on Youtube

Cristiano
Author by

Cristiano

Updated on May 25, 2022

Comments

  • Cristiano
    Cristiano about 2 years

    I have a problem with list refresh when user closes one activity and returns to previous. I see that problem is very common but I can't solve it.

    I overridden onResume method:

    @Override
    public void onResume() {
        super.onResume();
        populateList();
    }
    

    populateList() is a method where I populate listView with list of Strings:

    arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item,list);
    listView.setAdapter(arrayAdapter);
    

    The problem is that when second activity is closed, new items are just added again in the ListView so I have every item doubled. Like it's not refreshed.

    If I put notifyDataSetChanged() in onResume() it throws me nullPointerException because when activity is started first time there is no adapter initialized when activity is first time started.

    I'm not sure how to handle this.

    public class testActivity extends Activity {
    
    
        private int id=1;
        private ListView listView;
        private CustomArrayAdapter arrayAdapter;
        private ArrayList<String> list = new ArrayList<String>();
        ArrayList<Item> objectList = new ArrayList<Item>();
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test);
    
        }
    
        @Override
        public void onResume() {
            super.onResume();
            populateList();
        }
    
        private void populateList() {
            try {
                objectList = new GetAsyncTask(id).execute();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (TimeoutException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            int size = objectList.size();
            String name;
    
            for (int i = 0; i < size; i++) {
                name = objectList.get(i).getName();
                list.add(name);
            }
    
            arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item,
                    list);
            listView.setAdapter(arrayAdapter);
        }
    }
    
    • Wroclai
      Wroclai over 11 years
      Keep a member variable that controls if the ListView already contain strings. If so, don't call populateList().
    • Sam
      Sam over 11 years
      The problem is with list, how are you populating this?
    • Cristiano
      Cristiano over 11 years
      @Shelly - But I need to call populateList() even if ListView contains strings. I'm trying to refresh it. I'm not sure if I understood you well.
    • Wroclai
      Wroclai over 11 years
      @ZdravkoVajudin: Ah, sorry, I misunderstood. I would clear the adapter, and then add the strings again.
    • Cristiano
      Cristiano over 11 years
      @Sam - I catch the list_of_files from device and put it in a list in populateList(). Then I apply adapter. On return that list on device is changed so it again does the same and put it in a list. The problem is in ListView there are still old items and new items are just added at the end. So it's duplicated.
  • Cristiano
    Cristiano over 11 years
    I put it like that and now it's again working but there is still a problem with duplicated items. I have for example 5 items, change one in second activity and on return there are again those old five on the list, 1 new (one changed in second activity) and 4 old ones again which are duplicated. Like this if the last one is edited: a, b, c, d, e, a, b, c, d, z
  • mango
    mango over 11 years
    you have not put nearly enough code for us to help you sufficiently. but you need to check that whatever code block is initializing the list collection isn't being called again, presumably onResume The fact that you even need what i have suggested has me worried that things aren't all they could be.
  • Cristiano
    Cristiano over 11 years
    It works! Just one correction. In that last else, below arrayAdapter.notifyDataSetChanged(); it also needs to be: arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item, list); listView.setAdapter(arrayAdapter); If it's not, ListView contains only old data.
  • Cristiano
    Cristiano over 11 years
    Thanks for advice for AsyncTask! I gave you one up :)