[ Android ] 為何呼叫了 notifyDataSetChanged() 卻沒有動靜

notifyDataSetChanged() 是告知 Adapter 刷新 ListView 的方法

但是並非單純在程式碼當中加上去就會有效果




我的 ListView 是透過一個自訂的 Adapter 物件所呈現的

單純的從 SQLite 撈出 Cursor 物件再解析封裝成一個 Note 物件

生成 Note 物件後再丟進 ArrayList <Note> 集結起來

僅撈出資料顯示沒有問題

切換 Activity 新增資料也能夠正常顯示 ( MainActivity <-- 切換 --> EditActivity )


實作刪除選項的功能後進行測試

在 ListView長按後跳出選單,點選刪除 ( 刪除所選擇的選項 )

想要刪除的選項還在 ( 簡而言之就是 ListView 並沒有因為資料的更新而刷新內容 )

僅能在切換 Activity 後才會刷新內容


看了一下相關文章,都指出如果要讓 ListView 自動刷新畫面 ( 因資料的變動 )

必須使用 notifyDataSetChanged() 通知 Adapter重新產生一次畫面

所以當下解決問題的方式是這樣 ( 會這樣講就代表沒成功 )

先指定刪除SQLite的row >>>>使用 notifyDataSetChanged() 刷新 ListView

然而 ListView 仍不動如山 ( 透過 Log 觀察有確實刪除指定的 SQLite Row )


這次換了一組關鍵字 notifyDataSetChanged() not work

看了一下 stackoverflow 上的看到下面兩篇文章


 -----------notifyDataSetChange not working from custom adapter------------

https://stackoverflow.com/questions/15422120/notifydatasetchange-not-working-from-custom-adapter


 -----------Android: notifyDataSetChanged(); not working------------


https://stackoverflow.com/questions/16165728/android-notifydatasetchanged-not-working



思考的同時發現這兩篇都有類似的回應

====== Your adapter loses reference to your list. ======

這句話點亮了我的腦袋,於是我開始查驗整個過程中 ArrayList 的變化



從一開始 SQLite 開始,經過解析封裝成Note,在到 ArrayList 都沒有問題

但是刪除SQLite後,ArrayList仍然沒有變化 ( 啊哈!!! )

再搭上 Your adapter loses reference to your list. 這句話

我再用力研讀這兩篇的內容 ( 英文要用力去看 )

稍微理解一下 notifyDataSetChanged() 的運作方式

當 Adapter 呼叫 notifyDataSetChanged() 方法時

會重新計算資料的長度 ( getCount() ) 再執行 getView () 重新刷新畫面


好了,依照這樣的程序思考下來,我發現我根本沒有把更新過後的資料丟給 Adapter!!




ArrayList 裏頭的資料根本沒更新

就算呼叫 notifyDataSetChanged() 方法到天荒地老 ListView 上的資料就是舊的啊啊!!

馬德法科...

------------------------------------------------------------------------------

 前面廢話這麼多,下列是我在程序上所做的處理


 1. 在 NoteListAdapter ( 我所自訂的Adapter物件 ) 加入 ArrayList 的 Setter

     ( ArrayList 修改為全域變數 )

 2. 在刪除指定的 SQLite Row 後重新跑一次撈資料的流程

     ( ArrayList 在加入新資料前記得要清空 )

 3. 透過 ArrayList 的 Setter 更新資料

 4. 呼叫 Adapter 的 notifyDataSetChanged() 方法

 5. 沒意外的話應該就可以正常的運作了


自動更新 ListView 的方式我想了很多種

1. 透過一個 Thread 定時去更新畫面上的資料
 
現階段沒必要,目前SQLite內容僅限於自己使用,沒必要額外花這些效能。


2. 同時操作 ListView 與 SQLite

意思就是我刪除了指定的 SQLite Row 後,再自行刪除 ListView 上的選項

但這樣有一定的風險會造成資料不同步的問題

且操作上的個人感覺比較繁雜




========================================================

更換為 RecyclerView 後

通知更新的方法為

 notifyItemChanged(int position, Object payload)

notifyDataSetChanged()


可參考下列資料

Android Developer -- RecyclerView.Adapter













1 則留言:

Layout疑難雜症筆記

 這裡記錄一些Layout時View元件比較特殊的狀況與處理方式,內容會陸續增加。