2014-09-30 202 views
2

我的一些用戶的更新適配器(也許50)是越來越崩潰,並顯示以下錯誤:從後臺線程

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread.

如果我理解正確的話,它造成的一個的AsyncTask的doInBackground()調用adapter.clear();adapter.addAll(list);方法,我需要將它移動到onPostExecute()

問題是我不能再現該錯誤,所以我不能確定它是否修復。 StackOverflow上的一些類似問題似乎表明,僅僅將更新適配器更改爲onPostExecute()方法並不能解決問題。

有誰知道我可以如何使每次在我的設備上發生此錯誤,以確保修復工作?我不明白它爲什麼在大多數情況下都能正常工作,但有時只會導致崩潰。

+0

你在某一個點做在你的列表中的任何插入?如果你是可以模擬的,看看會發生什麼 – AndroidEnthusiast 2014-09-30 15:56:52

+0

當'mItemCount'不是零並且'mItemCount!= mAdapter.getCount()':[ListView時,拋出'layoutChildren()'中'ListView'的異常。的java(http://grepcode.com/file_/repo1.maven.org/maven2/org.robolectric/android-all/4.1.2_r1-robolectric-0/android/widget/ListView.java/?v=source) – 2014-09-30 16:01:20

+0

我在'doInBackground()'中用適配器做的唯一事情就是'adapter.clear();'和'adapter.addAll(list)'。到目前爲止,我在所有設備上運行了數百次,而不是一次崩潰。 – TimSim 2014-09-30 16:02:31

回答

1

簡單的答案:你忘記打電話adapter.notifyDatasetChanged()

Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.

獲取後臺數據和onPostExecute()更新您的適配器,因爲你永遠不應該改變從後臺線程適配器的內容。在UI線程上執行onPreExecute()onPostExecute()

+0

我在'onPostExecute()'中調用了該函數,該函數恰好在之後發生。但我更感興趣的是重現這個錯誤。出於某種原因,它從來沒有發生過我,所以它吱吱作響。 – TimSim 2014-09-30 16:00:05

0

要重現此問題,請在doInBackground()中更改適配器後嘗試休眠。

例如:

@Override 
    protected Void doInBackground(Void... params) { 
    adapter.clear(); 
    try 
    { 
     Thread.sleep(5000); 
    } 
    catch(InterruptedException e){} 
    return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
    super.onPostExecute(result); 
    adapter.notifyDatasetChanged(); 
    } 
+0

仍然不會崩潰應用程序。 – TimSim 2014-09-30 17:59:30

+0

@TimSim是否會引發異常? – nyx 2014-09-30 18:01:57

0

你不應該調用任何UI事情doInBackground(..)方法。 只是調用它們在onPostExecute(..)以及onPreExecute(..)

例如

@Override 
    protected void onPostExecute(Void result) { 
    super.onPostExecute(result); 
    adapter.clear(); 
    } 

按照AsyncTask文檔,在 「4個步驟」 的段落。

onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.

0

試試這個..

runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        adapter.notifyDatasetChanged(); 
       } 
      });