What I want to do: run a background thread which calculates ListView contents and update ListView partially, while results are calculated.
W
I wrote this code and had it run in a 2.1 emulator image for ~12 hours and did not get the IllegalStateException. I'm going to give the android framework the benefit of the doubt on this one and say that it is most likely an error in your code. I hope this helps. Maybe you can adapt it to your list and data.
public class ListViewStressTest extends ListActivity {
ArrayAdapter adapter;
ListView list;
AsyncTask task;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1);
this.list = this.getListView();
this.list.setAdapter(this.adapter);
this.task = new AsyncTask() {
Random r = new Random();
int[] delete;
volatile boolean scroll = false;
@Override
protected void onProgressUpdate(String... values) {
if(scroll) {
scroll = false;
doScroll();
return;
}
if(values == null) {
doDelete();
return;
}
doUpdate(values);
if(ListViewStressTest.this.adapter.getCount() > 5000) {
ListViewStressTest.this.adapter.clear();
}
}
private void doScroll() {
if(ListViewStressTest.this.adapter.getCount() == 0) {
return;
}
int n = r.nextInt(ListViewStressTest.this.adapter.getCount());
ListViewStressTest.this.list.setSelection(n);
}
private void doDelete() {
int[] d;
synchronized(this) {
d = this.delete;
}
if(d == null) {
return;
}
for(int i = 0 ; i < d.length ; i++) {
int index = d[i];
if(index >= 0 && index < ListViewStressTest.this.adapter.getCount()) {
ListViewStressTest.this.adapter.remove(ListViewStressTest.this.adapter.getItem(index));
}
}
}
private void doUpdate(String... values) {
for(int i = 0 ; i < values.length ; i++) {
ListViewStressTest.this.adapter.add(values[i]);
}
}
private void updateList() {
int number = r.nextInt(30) + 1;
String[] strings = new String[number];
for(int i = 0 ; i < number ; i++) {
strings[i] = Long.toString(r.nextLong());
}
this.publishProgress(strings);
}
private void deleteFromList() {
int number = r.nextInt(20) + 1;
int[] toDelete = new int[number];
for(int i = 0 ; i < number ; i++) {
int num = ListViewStressTest.this.adapter.getCount();
if(num < 2) {
break;
}
toDelete[i] = r.nextInt(num);
}
synchronized(this) {
this.delete = toDelete;
}
this.publishProgress(null);
}
private void scrollSomewhere() {
this.scroll = true;
this.publishProgress(null);
}
@Override
protected Void doInBackground(Void... params) {
while(true) {
int what = r.nextInt(3);
switch(what) {
case 0:
updateList();
break;
case 1:
deleteFromList();
break;
case 2:
scrollSomewhere();
break;
}
try {
Thread.sleep(0);
} catch(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
this.task.execute(null);
}
}