2013-07-09 20 views
1

知道在正常情況下,無法在後臺線程中調用ListAdapter.notifyDataSetChanged()來更新列表視圖。所以,我想解決這樣的:在後臺線程中修改適配器

class mythread extends thread { 
    private ListAdapter listAdapter; 
    ... 
    public void run() { 
     listAdpater.setNotifyOnChange(false); 
     listAdapter.addAll(A_LARGE_ARRAY); 
    } 
    ... 
} 

當線程完成後,將消息發送到UI線程運行的處理程序,它會調用listAdapter.notifyDataSetChanged()來更新列表視圖。

這似乎工作,除了當我試圖調試它時,調試器抱怨像「適配器已更改,而listview沒有收到通知。確保您只修改UI線程中的adpater」。

即使我叫setNotifyOnChange(false),android框架是否監視適配器的修改?有什麼方法可以解決嗎?

PS。在我自己的基準測試中,通過將listAdapter.addAll(A_LARGE_ARRAY)移動到後臺線程,它爲我節省了大約126ms的執行時間,這意味着如果我在UI線程中修改適配器,它將被阻塞126ms。

UPDATE
任何人誰遇到這個問題,請參閱本Google I/O Lecture鏈接。這真的很有幫助。

回答

1

您可能不想這樣做,您的應用可能會在某些設備或某個版本的Android上莫名其妙地崩潰,同時完美地處理其他應用。

記住listAdpater每次更新相關UI時都會被訪問,該UI在UI線程上運行。 與此同時,您正在另一個線程中更新相同的listAdpater。這意味着:

  1. 如果UI更新,而你正在修改listAdapter,UI可以顯示甚至拋出異常不正確的項目(取決於競爭條件和)
  2. 什麼東西被更新,以listAdapter在其他線程可能不會更新到主線程,如果操作系統認爲它適合在另一個處理器上運行另一個線程,因爲沒有內存屏障(同步),所以不能保證這兩個線程看到相同的東西

因此,對於您來說最好的行動方案仍然是在UI線程上運行更改,但只能更新一次只吃一小部分A_LARGE_ARRAY給listAdapter。

+0

感謝您的詳細解釋。 – Lion