Android: Refresh ListView in first activity on return from second activity
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.)
Related videos on Youtube
Cristiano
Updated on May 25, 2022Comments
-
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 over 11 yearsKeep a member variable that controls if the
ListView
already contain strings. If so, don't callpopulateList()
. -
Sam over 11 yearsThe problem is with
list
, how are you populating this? -
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 over 11 years@ZdravkoVajudin: Ah, sorry, I misunderstood. I would clear the adapter, and then add the strings again.
-
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 over 11 yearsI 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 over 11 yearsyou 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, presumablyonResume
The fact that you even need what i have suggested has me worried that things aren't all they could be. -
Cristiano over 11 yearsIt works! Just one correction. In that last
else
, belowarrayAdapter.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 over 11 yearsThanks for advice for AsyncTask! I gave you one up :)