Reputation: 910
I have some images arranged in horizontal grid. I want to move my grid from left to right and right to left using key events. When I move through the grid two things happened
The item at second position is selected. For example, I'm at position 0 and want to select the next item at position 1, but my grid select the position 2 item and skips the position 1 item.
on scrolling I get the null pointer exception
if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT)
{
if (mCurrentSelectedPosition + 1 < getItemCount()) {
Log.e("current position1",Integer.toString(mCurrentSelectedPosition));
gridHolder = (GridView_Holder) mRecyclerView.findViewHolderForPosition(mCurrentSelectedPosition);
gridHolder.itemView.setSelected(false);
notifyItemChanged(mCurrentSelectedPosition);
notifyDataSetChanged();
int lastItem = lm.findLastCompletelyVisibleItemPosition();
Log.e("last item",Integer.toString(lastItem));
if ((mCurrentSelectedPosition + 1) > lastItem) {
// Log.e("Is less", "true");
recyclerView.smoothScrollToPosition(mCurrentSelectedPosition + 1);
Log.e("current position2",Integer.toString(mCurrentSelectedPosition));
} else {
gridHolder = (GridView_Holder) mRecyclerView.findViewHolderForPosition(mCurrentSelectedPosition + 1);
gridHolder.itemView.setSelected(true);
Log.e("current position3",Integer.toString(mCurrentSelectedPosition));
}
mCurrentSelectedPosition += 1;
Log.e("current position4",Integer.toString(mCurrentSelectedPosition));
}
return true;
}
scroll listener
gridRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrolled(RecyclerView recyclerView, int x, int y)
{
super.onScrolled(recyclerView, x, y);
try {
GridView_Holder gridHolder;
gridHolder= (GridView_Holder) recyclerView.findViewHolderForPosition(adapter.mCurrentSelectedPosition);
gridHolder.itemView.setSelected(true);
}catch(Exception e){
Log.e("exception",e.getMessage());
}
}
this is my logcat
java.lang.NullPointerException: Attempt to read from field 'android.view.View android.support.v7.widget.RecyclerView$ViewHolder.itemView' on a null object reference
at com.winettv.recylcerviewwithdpad.GridView_Recycler_Adapter$1.onKey(GridView_Recycler_Adapter.java:193)
at android.view.View.dispatchKeyEvent(View.java:9230)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1635)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.widget.ScrollView.dispatchKeyEvent(ScrollView.java:379)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at com.android.internal.policy.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:2395)
at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1727)
at android.app.Activity.dispatchKeyEvent(Activity.java:2725)
at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:543)
at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:53)
at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:315)
Upvotes: 3
Views: 6388
Reputation: 5788
When I developed library with custom translation during scroll I had the same issue. Only in fast scrolling, when i tried to access View element from List, that was null and here is NPE.
So there is pretty simple solution just skip elements, which is empty, and continue with new one. In my case it was like this:
// Other init....
for (int i = 0; i < MainListView.getChildCount; i++) {
if (MainListView.getChildAt(i) == null)
continue;
// Continue base behavior
}
This happens, based on ScrollView (which is parent for RecycleView, ListView, etc.) When we trying to access View which is redrawing now. Anyway just simple Null checking should solve your problem.
UPDATE 1:
Also based on caching View layouts of RecyclerView, you need another option. See below.
gridRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrolled(RecyclerView recyclerView, int x, int y)
{
super.onScrolled(recyclerView, x, y);
GridView_Holder gridHolder;
gridHolder= (GridView_Holder) recyclerView.findViewHolderForPosition(adapter.mCurrentSelectedPosition);
if (gridHolder != null && gridHolder.itemView != null) {
gridHolder.itemView.setSelected(true);
}
}
}
Upvotes: 2
Reputation: 1906
As per the error it is clear that
(GridView_Holder)mRecyclerView.findViewHolderForPosition(mCurrentSelectedPosition);
is null. that is the reason for the crash.
You can refer below links
FindViewHolderForPosition return null when card's not in vision
RecyclerView - findViewHolderForPosition always returns null when onBindViewHolder is not called
Upvotes: 1
Reputation: 1906
In the code gridHolder.itemView.setSelected(true); gridHolder was null.
Change the code like this and try.
if ((mCurrentSelectedPosition + 1) > lastItem) {
// Log.e("Is less", "true");
recyclerView.smoothScrollToPosition(mCurrentSelectedPosition);
Log.e("current position2",Integer.toString(mCurrentSelectedPosition));
} else {
gridHolder = (GridView_Holder) mRecyclerView.findViewHolderForPosition(mCurrentSelectedPosition);
gridHolder.itemView.setSelected(true);
Log.e("current position3",Integer.toString(mCurrentSelectedPosition));
}
Reason for the crash.
Upvotes: 3