最近在開發中遇到一個問題,Adapter中使用notifyDataSetChanged 與notifyDataSetInvalidated無效,經過思考和網上查找,得出如下原因。
首先看一下notifyDataSetChanged與notifyDataSetInvalidated的區別
我們可應用糧倉來解釋一下,兩者的區別。
notifyDataSetChanged:糧倉中得糧食少了,或者多了,發送通知。
notifyDataSetInvalidated:糧倉變換了,比如原來從A倉取糧食,現在換成了B糧倉。
其次看一下,Java中對象和對象的引用。
java 中使用new 方法創建對象。同時把對象的地址賦值給一個變量。
大家需要明白的是,這個變量,並不是對象,而是存儲對象地址的一個變量。這個有點繞。
還是用糧倉來比喻,new一個對象,就相當於創建了一個糧倉。而這個糧倉的地址就是你聲明的對象變量。
Java中得對象可以說是沒有生命周期這一說法的,因為他只用存在和銷毀兩種狀態。也就是說,對象從創建后,直到被系統回收,是一直存在的。他不會隨着你聲明的變量銷毀而銷毀。
明白了以上兩點,我們再分析一下,為什么Adapter中的兩種方法為什么不起作用。
還是用糧倉來做比喻吧。
設有糧倉A,我們需要把A中得糧食,顯示出來。
然后,某天運輸隊,運來了一批糧食,這批糧食有兩種方式存儲。
1.把糧食放到A中,也就是我們說得List的Add方法。
2.新建一個糧倉B,把糧食放入B糧倉中。就是代碼中,new List --->add.
就這兩種情況分析一下,為什么不起作用。
第一種,如果使用notifyDataSetInvalidated,是不會起作用的,因為數據源沒有變化,就是糧倉還在。這個時候應該使用notifyDataSetChanged。糧倉中得糧食變了。
第二種,這是最復雜的,大部分不起作用都發生在這種情況下。
分析:notifyDataSetChanged不起作用的原因,是因為A糧倉中糧食沒有發生變化。Adapter中仍然保持是對A糧倉的地址引用。
notifyDataSetInvalidated不起作用的原因,是因為,Adapter中得變量仍然是保持對A的引用,沒有改變引用地址。
解決方法:第一種情況,基本不會出問題。
主要是第二種:如果數據對象,是重新new的對象,並且把引用賦值給要顯示的List時,要通知Adapter數據源發生了變化。比如重新setList(),並使用notifyDataSetInvalidated。
其實一切的原因都是Java中對象和引用的理解。有時間再寫例子吧。