Recyclerview或Listview實時重新整理,item點選事件失效的解決方法
問題場景:
本人最近在做一個關於藍芽開發的Demo,在掃描藍芽裝置的時候會產生回撥,並會返回BluetoothDevice和rssi,這個rssi就是掃描到的這個裝置的訊號。
注意,這個回撥不是搜尋到1個裝置後就只回調一次這個裝置,而是隻要掃描到了就會回撥,如下圖,掃描到了很多重複的裝置。
所以,這樣的話,我們就可以實時的拿到rssi,進行訊號的實時重新整理。
然後我把每一個裝置都當做一個item放在了Recyclerview裡,因為要實時重新整理rssi(訊號),所以就要一直呼叫
mAdapter.notifyDataSetChanged()來實現。
具體問題:
那麼問題來了,在掃描中的時候,訊號會實時重新整理,然後設定了OnItemClickLitener,但是點選會失效。在我停止了掃描,也就是沒有回撥的時候,自然不會呼叫mAdapter.notifyDataSetChanged()來進行實時重新整理了,這時點選不會失效。
解決問題:
我先對item設定了一個OnItemTouchListener(),具體程式碼
mAdapter.setOnItemTouchListener(new MyAdapter.OnItemTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "Item: ACTION_DOWN" );
break;
case MotionEvent.ACTION_MOVE:
Log.i(TAG, "Item: ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "Item: ACTION_UP");
break ;
case MotionEvent.ACTION_CANCEL:
Log.i(TAG, "Item: ACTION_CANCEL");
break;
}
return false;
}
});
重新執行一遍,在掃描中的時候,點選item,檢視日誌。
發現item的事件走到了DOWN後就直接到了CANCEL,並沒有走到UP,那就不可能到Click了。
那我停止掃描裝置,也就是不實時重新整理了,點選item,檢視日誌。
發現item的事件正常的經過了DOWN和UP,然後到了Click,經過這個測試,我們可以猜測或大致的先認為點選item失效,是由notifyDataSetChanged()引起的,我們看看能不能解決。
需要注意的時,通過日誌我們可以發現,雖然Click失效了,但是onTouch並沒有失效,點選的時候每次都會走到ACTION_DOWN裡,這裡我們就有了一個解決方法,就是定義一個標記isClick,然後把mAdapter.notifyDataSetChanged()放在if(!isClick){}裡去執行,在MotionEvent.ACTION_DOWN的時候,isClick=true,在case MotionEvent.ACTION_UP的時候,isClick=false,具體程式碼:
if (!isClick) {
mAdapter.notifyDataSetChanged(); //重新整理資料
}
mAdapter.setOnItemTouchListener(new MyAdapter.OnItemTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isClick = true;
Log.i(TAG, "Item: ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i(TAG, "Item: ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
isClick = false;
Log.i(TAG, "Item: ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.i(TAG, "Item: ACTION_CANCEL");
break;
}
return false;
}
});
執行測試,實時重新整理的時候點選,檢視日誌
可以發現點選生效了,但還能發現,最後一下點選沒有生效,還是走到了DOWN直接到了CANCEL,並沒有走到UP,而且更為致命的是,訊號不重新整理了,因為我們再DOWN裡isClick = true裡,但是沒有走到UP裡,所以isClick就一直為true了,就不會呼叫notifyDataSetChanged()了, 解決辦法是我們在CANCEL裡也加上isClick = false。
總結:
通過這個方法可以解決在實時重新整理的時候點選失效的問題,但是,還是會有點選失效的問題,不過在實際操作過程中沒有明顯的感覺。具體的更好的解決辦法目前還沒有發現。