RecyclerView 在滚动时崩溃
RecyclerView crashes on scrolling
我有一些图像排列在水平网格中。我想使用关键事件从左到右和从右到左移动我的网格。当我穿过网格时发生了两件事
第二个位置的项目已 selected。例如,我在位置 0 并想 select 位置 1 的下一个项目,但我的网格 select 位置 2 项目并跳过位置 1 项目。
滚动时出现空指针异常
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;
}
滚动监听器
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());
}
}
这是我的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.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)
代码中gridHolder.itemView.setSelected(true);
gridHolder 为空。
像这样更改代码并尝试。
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));
}
崩溃的原因。
根据错误,很明显
(GridView_Holder)mRecyclerView.findViewHolderForPosition(mCurrentSelectedPosition);
为空。这就是崩溃的原因。
您可以参考以下链接
FindViewHolderForPosition return null when card's not in vision
当我在滚动过程中使用自定义翻译开发库时,我遇到了同样的问题。只有在快速滚动时,当我尝试从 List 访问 View 元素时,它才为 null,这里是 NPE。
所以有一个非常简单的解决方案,就是跳过空的元素,然后继续新的元素。在我的例子中是这样的:
// Other init....
for (int i = 0; i < MainListView.getChildCount; i++) {
if (MainListView.getChildAt(i) == null)
continue;
// Continue base behavior
}
当我们尝试访问正在重绘的 View 时,基于 ScrollView(它是 RecycleView、ListView 等的父级)会发生这种情况。无论如何,只需简单的空检查就可以解决您的问题。
更新 1:
同样基于RecyclerView的缓存视图布局,你需要另一个选择。见下文。
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);
}
}
}
我有一些图像排列在水平网格中。我想使用关键事件从左到右和从右到左移动我的网格。当我穿过网格时发生了两件事
第二个位置的项目已 selected。例如,我在位置 0 并想 select 位置 1 的下一个项目,但我的网格 select 位置 2 项目并跳过位置 1 项目。
滚动时出现空指针异常
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; }
滚动监听器
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());
}
}
这是我的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.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)
代码中gridHolder.itemView.setSelected(true); gridHolder 为空。
像这样更改代码并尝试。
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));
}
崩溃的原因。
根据错误,很明显
(GridView_Holder)mRecyclerView.findViewHolderForPosition(mCurrentSelectedPosition);
为空。这就是崩溃的原因。
您可以参考以下链接
FindViewHolderForPosition return null when card's not in vision
当我在滚动过程中使用自定义翻译开发库时,我遇到了同样的问题。只有在快速滚动时,当我尝试从 List 访问 View 元素时,它才为 null,这里是 NPE。
所以有一个非常简单的解决方案,就是跳过空的元素,然后继续新的元素。在我的例子中是这样的:
// Other init....
for (int i = 0; i < MainListView.getChildCount; i++) {
if (MainListView.getChildAt(i) == null)
continue;
// Continue base behavior
}
当我们尝试访问正在重绘的 View 时,基于 ScrollView(它是 RecycleView、ListView 等的父级)会发生这种情况。无论如何,只需简单的空检查就可以解决您的问题。
更新 1:
同样基于RecyclerView的缓存视图布局,你需要另一个选择。见下文。
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);
}
}
}