I am trying to implement a list selector for my RecyclerView
grid on a touch free device. My implementation works fine but it requires notifyItemChanged()
method which is not efficient performance wise. I have a grid with 100s of items so if i am scrolling fast (scrolling with a keyboard hence the onKey) the grid becomes distorted as lots of items are being updated. Is there a way to avoid this?
Activity
mRecyclerView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager();
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case Constants.KEYCODE_UP:
return moveSelection(lm, -1, true);
case Constants.KEYCODE_DOWN:
return moveSelection(lm, 1, true);
}
}
return false;
}
});
public boolean moveSelection(RecyclerView.LayoutManager lm, int direction, boolean verticalMovement) {
...
//just calculate the position to move to and pass it to selectedPosition
return mAdapter.tryMoveSelection(lm, selectedPosition);
}
Adapter
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
mViewHolder = holder;
holder.itemView.setSelected(mFocusedItem == position);
...
}
public boolean tryMoveSelection(RecyclerView.LayoutManager lm, int selectedPosition) {
notifyItemChanged(mFocusedItem);
mFocusedItem = selectedPosition;
notifyItemChanged(mFocusedItem);
lm.scrollToPosition(mFocusedItem);
return true;
}
There are couple of optimisations you could add to your code:
Don't call notifyItemChanged()
when RecyclerView
is scrolling. There are couple of handy methods for that:
getScrollState()
- when the result is different than SCROLL_STATE_IDLE
then RecyclerView
is scrolling.
hasPendingAdapterUpdates()
- that means, that RecyclerView.RecyclerAdapter
has items to layout.
When the getScrollState()
is SCROLL_STATE_IDLE
then call notifyItemChanged()
.
Adapter also has a couple of handy method to override:
void onViewAttachedToWindow (VH holder)
- is called when view is about to be shown to the user.
void onViewDetachedFromWindow (VH holder)
- the row is detached from view - free heavy resources here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With