Android, ListView IllegalStateException: “The content of the adapter has changed but ListView did not receive a notification”

后端 未结 25 2150
执念已碎
执念已碎 2020-11-22 16:59

What I want to do: run a background thread which calculates ListView contents and update ListView partially, while results are calculated.

W

25条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-22 17:32

    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);
        }
    }
    

提交回复
热议问题