为什么我在RecyclerView上获得空引用

我试图在我的片段中使用RecyclerView。 它显示第一个选项卡正常,但当我滑到第二个选项卡,然后回到第一个选项卡时,我收到以下错误:

java.lang.NullPointerException:尝试在空对象引用上调用虚方法’void android.support.v7.widget.RecyclerView $ LayoutManager.stopSmoothScroller()’

有谁知道为什么我会收到这个错误? 在片段切换之前似乎有一个我失踪的电话,但我无法弄明白。

用于片段的寻呼机适配器:

public class PagerAdapter extends FragmentPagerAdapter { private final String[] TITLES = {"Header 0", "Header 1" }; public PagerAdapter(FragmentManager fm){ super(fm); } @Override public CharSequence getPageTitle(int position){ return TITLES[position]; } @Override public int getCount() { return TITLES.length; } @Override public Fragment getItem(int position){ switch(position){ case 0: return new FragmentOne(); case 1: return new FragmentTwo(); default: return new FragmentOne(); } } } 

FragmentOne&FragmentTwo使用我创建的样板类:

 public class FragmentOne extends Base { ... code for displaying content in the RecyclerView. Just contains my custom Adapter for the RecyclerView ... } 

基础:

 public abstract class Base extends Fragment { public View mView; public RecyclerView mDataView; public ProgressBar mProgressBar; public Context mContext; private RecyclerView.LayoutManager mLayoutManager; public Base() { } @Override public View onCreateView(LayoutInflater _i, ViewGroup _vg, Bundle savedInstanceBundle){ mView = _i.inflate(R.layout.f_base, null); mDataView = (RecyclerView) mView.findViewById(R.id.data); mProgressBar = (ProgressBar)mView.findViewById(R.id.loading); mLayoutManager = new LinearLayoutManager(mContext); mDataView.setLayoutManager(mLayoutManager); mContext = this.getActivity(); return mView; } @Override public void onStart() { super.onStart(); init(); doWork(); } public abstract void init(); public abstract void doWork(); } 

编辑

错误堆栈跟踪:

 11-02 12:49:44.171 3708-3708/com.nitrox.digitune E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.nitrox.digitune, PID: 3708 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView$LayoutManager.stopSmoothScroller()' on a null object reference at android.support.v7.widget.RecyclerView.stopScrollersInternal(RecyclerView.java:1159) at android.support.v7.widget.RecyclerView.stopScroll(RecyclerView.java:1151) at android.support.v7.widget.RecyclerView.onDetachedFromWindow(RecyclerView.java:1356) at android.view.View.dispatchDetachedFromWindow(View.java:13441) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2837) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2834) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2834) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:4163) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:4136) at android.view.ViewGroup.removeView(ViewGroup.java:4068) at android.support.v4.view.ViewPager.removeView(ViewPager.java:1326) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1045) at android.support.v4.app.FragmentManagerImpl.detachFragment(FragmentManager.java:1280) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:724) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1489) at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:486) at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141) at android.support.v4.view.ViewPager.populate(ViewPager.java:1073) at android.support.v4.view.ViewPager.populate(ViewPager.java:919) at android.support.v4.view.ViewPager$3.run(ViewPager.java:249) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) at android.view.Choreographer.doCallbacks(Choreographer.java:580) at android.view.Choreographer.doFrame(Choreographer.java:549) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

  • MediaStore.EXTRA_OUTPUT呈现数据为空,其他方式保存照片?
  • 无法解析com.google.android.gms play-services-auth:11.4.0
  • 如何在Android中安全地存储加密密钥?
  • 如果当前版本市场版本,则提示Android App用户更新应用程序
  • Android Manifest - 具有Activity / Runnable类的“没有默认构造函数”
  • 你如何在android中获得用户定义的“设备名称”?
  • 在android中将字符串转换为日期格式
  • 将YouTube Data API添加到Android Studio
  • 基本上,您的LayoutManager将在回收商完成之前进行处理。

    来自Android来源:

     @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mItemAnimator != null) { mItemAnimator.endAnimations(); } mFirstLayoutComplete = false; stopScroll(); mIsAttached = false; if (mLayout != null) { mLayout.onDetachedFromWindow(this, mRecycler); } removeCallbacks(mItemAnimatorRunner); } 

    问题是stopScroll尝试调用mLayout.stopSmoothScroller(); 不检查mLayout是否为空。 我为一个我一直在努力的应用程序扔了一个非常hacky热修复,但不应该用作长期解决方案,因为它非常黑客,但我有一个紧迫的截止日期所以我只需要捕获空指针exception。 我删除了我的处理程序,因为它是特定于应用程序

    我的热门修复只是创建一个扩展RecyclerView的自定义View:

     import android.content.Context; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; public class HotFixRecyclerView extends RecyclerView { public HotFixRecyclerView( Context context ) { super( context ); } public HotFixRecyclerView( Context context, AttributeSet attrs ) { super( context, attrs ); } public HotFixRecyclerView( Context context, AttributeSet attrs, int defStyle ) { super( context, attrs, defStyle ); } @Override public void stopScroll() { try { super.stopScroll(); } catch( NullPointerException exception ) { /** * The mLayout has been disposed of before the * RecyclerView and this stops the application * from crashing. */ } } } 

    然后将对RecyclerView的所有引用更改为我自己的视图。 如果您确实使用它,请在Android修补此问题后将其删除,因为这有点像黑客攻击。

    • 如果您在XML上使用recylerview,请不要忘记将XML文件相应地更改为com.your.package.HotFixRecyclerView而不是android.support.v7.widget.RecyclerView

    似乎如果你的布局中有一个RecyclerView并且你在Activity中加载它,那么必须为它设置一个LayoutManager,否则它会在试图销毁它时抛出这个exception。 我刚遇到这个错误,这就是我解决它的方式:

    我的活动显示了一对TextViews或RecyclerView中的元素,具体取决于项目数量:如果它是一个项目集合,我使用了RecyclerView; 如果只有一个项目,它会显示在TextViews上,并将RecyclerView的可见性设置为GONE

    然后,在第一种情况下,我调用myRecyclerView.setLayoutManager(myLayoutManager) ,但在另一种情况下我没有,因为我不打算使用它。 在这两种情况下,包含RecyclerView的Activity都完美显示。 但是当关闭它时,Exception被抛入第二种情况,因为RecyclerView虽然没有使用,但是当它试图处理它时,它似乎不可能。 所以我在两种情况下都分配了LayoutManager,虽然我没有使用它,这解决了这个问题。

    这是我的活动中的代码:

     ItemsAdapter adapter; RecyclerView myRecyclerView = findViewById(R.id.my_recycler_view); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); if (items.size() > 1){ adapter = new ItemsAdapter(this, R.layout.item_layout, items); myRecyclerView.setLayoutManager(layoutManager); myRecyclerView.setAdapter(adapter); } else { tv_field1.setText(items.get(0).getField1()); tv_field2.setText(items,get(0).getField2()); myRecyclerView.setVisibility(View.GONE); //This is what I had to add myRecyclerView.setLayoutManager(layoutManager); } 

    因为它已经夸大了pref.xml。 你应该删除这个:

      @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mRootView = inflater.inflate(R.layout.xxx, container, false); return mRootView; } 

    阅读Isaak发布的错误,最好的解决方案似乎是在视图膨胀后立即分配布局管理器。

    在我的情况下,我只需要在onCreate上分配它来解决问题:

     mLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager);