场景:
RecyclerView
和RecyclerView.Adapter
。因为会显示时间敏感信息,所以每10ms就会调用一次notifyDataSetChanged()
方法,因此ViewHolders(类正在扩展RecyclerView.ViewHolder
)会经常更新。View.OnTouchListener
并将所有触摸事件和listItem-position(由getAdapterPosition()
查询)通过接口传递给Activity。问题:
当调用notifyDataSetChanged()
之后不久触摸ListItem时,接收到的值为:
[1 getAdapterPosition()
:-1
[2 motionEvent.getAction()
:ACTION_DOWN
直接后跟ACTION_CANCEL
请注意,如果您调用了notifyDataSetChanged(),则直到下一个布局传递,此方法的返回值为NO_POSITION。
所以我猜想,在notifyDatasetChanges()
刷新viewHolders时,每次触摸listItem都会发生错误:getAdapterPosition()
根据文档返回-1。并且,可能是因为刷新了viewHolder中的元素,所以onTouchEvent抛出ACTION_CANCEL
。
我尝试过的事情:
ACTION_DOWN
上RecyclerView的刷新,但是由于ACTION_CANCEL
事件,我没有收到任何ACTION_UP
事件,并且无法重新开始刷新数据。RecyclerView.OnItemTouchListener()
,以便在将其传递给listItem及其onTouchListener并在其中停止刷新recyclerview之前,在onInterceptTouchEvent()
中接收TouchEvent。但是,因为我仍然需要有关单击了哪个项目的信息,所以我仍然需要onTouchListener项,该项仍返回-1和ACTION_CANCEL
。问题:
在经常更新其数据的RecyclerView中处理onTouch事件的最佳做法是什么?
活动类别
public class Activity extends AppCompatActivity implements DataStoreDataAdapter.OnListItemTouchListener { Handler dataUpdateHandler = new Handler(); Runnable timerRunnable = new Runnable() { @Override public void run() { dataStoreDataAdapter.notifyDataSetChanged(); dataUpdateHandler.postDelayed(this, 10); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity); dataStoreDataAdapter = new DataStoreDataAdapter(getApplicationContext(),this); recyclerView = findViewById(R.id.list_view); layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(dataStoreDataAdapter); recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() { @Override public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) { Log.i(TAG, "onInterceptTouchEvent: " + " touched by type " + e); int action = e.getAction(); if (action == MotionEvent.ACTION_DOWN) { dataUpdateHandler.removeCallbacks(timerRunnable); } else if (action == MotionEvent.ACTION_UP) { dataUpdateHandler.post(timerRunnable); } return false; } @Override public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) { Log.i(TAG, "onTouchEvent: " + " touched by type " + e); } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } }); //set update Handler dataUpdateHandler.post(timerRunnable); } @Override public void onListItemTouch(int position, MotionEvent motionEvent) { Log.i(TAG, "onListItemTouch: ListItem position " + position + " motionEvent: " + motionEvent); } }
适配器类
public class DataStoreDataAdapter extends RecyclerView.Adapter<DataStoreDataAdapter.ViewHolder> {
private OnListItemTouchListener onListItemTouchListener;
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnTouchListener{
View view;
TextView Name;
// ...
ViewHolder(@NonNull View itemView, OnListItemTouchListener onListItemTouchListener) {
super(itemView);
this.Name = itemView.findViewById(R.id.NameListItem);
// ...
this.onListItemTouchListener = onListItemTouchListener;
itemView.setOnTouchListener(this);
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
onListItemTouchListener.onListItemTouch(getAdapterPosition(), motionEvent);
return true;
}
}
public interface OnListItemTouchListener{
void onListItemTouch(int position, MotionEvent motionEvent);
}
public DataStoreDataAdapter(Context context, OnListItemTouchListener onListItemTouchListener) {
super();
this.onListItemTouchListener = onListItemTouchListener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.list_item,parent,false);
return new ViewHolder(view, onListItemTouchListener);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// get the stored data for this position
// ...get stuff from native library
// put data into view elements...
}
@Override
public int getItemCount() {
return // ... itemCount from native library;
}
}
场景:带有RecyclerView.Adapter的RecyclerView。因为会显示时间敏感信息,所以每10毫秒调用一次notifyDataSetChanged()方法,因此ViewHolders(类正在扩展...