为什么我让我的RecyclerView空引用 [英] Why am I getting a null reference on my RecyclerView

查看:1658
本文介绍了为什么我让我的RecyclerView空引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用RecyclerView在我的片段。它显示了罚款的第一个选项卡,但是当我刷到第二个选项卡,然后回到第一个我得到以下错误:

  

显示java.lang.NullPointerException:尝试调用虚拟方法无效   android.support.v7.widget.RecyclerView $ LayoutManager.stopSmoothScroller()'   在一个空对象引用

有谁知道为什么我会得到这个错误?它似乎有一个电话,我在我的片段切换很想念,但我不明白。

寻呼机适配器片段:

 公共类PagerAdapter扩展FragmentPagerAdapter {

    私人最终的String []业权= {头0,标题1};

    公共PagerAdapter(FragmentManager FM){
        超(FM);
    }

    @覆盖
    公共CharSequence的getPageTitle(INT位置){
        返回TITLES [位置]
    }

    @覆盖
    公众诠释getCount将(){
        返回TITLES.length;
    }

    @覆盖
    公共片段的getItem(INT位置){
        开关(位置){
            情况下0:
                返回新FragmentOne();
            情况1:
                返回新FragmentTwo();
            默认:
                返回新FragmentOne();
        }
    }
}
 

FragmentOne和放大器; FragmentTwo使用我创建了一个样板类:

 公共类FragmentOne扩展基地{
    ... code在RecyclerView显示内容。只包含我的自定义适配器的RecyclerView ...
}
 

文章:

 公共抽象类中相应扩展片段{

    公众查看MView的;
    公共RecyclerView mDataView;
    公共进度mProgressBar;
    公共语境mContext;
    私人RecyclerView.LayoutManager mLayoutManager;

    公共基地(){}

    @覆盖
    公共查看onCreateView(LayoutInflater _i,ViewGroup中_vg,捆绑savedInstanceBundle){
        MVIEW = _i.inflate(R.layout.f_base,NULL);
        mDataView =(RecyclerView)mView.findViewById(R.id.data);
        mProgressBar =(进度)mView.findViewById(R.id.loading);
        mLayoutManager =新LinearLayoutManager(mContext);
        mDataView.setLayoutManager(mLayoutManager);
        mContext = this.getActivity();
        返回MView的;
    }

    @覆盖
    公共无效的OnStart(){
        super.onStart();
        在里面();
        做工作();
    }

    公共抽象无效的init();

    公共抽象无效的doWork();

}
 

修改

错误堆栈跟踪:

 十二月11日至2号:49:44.171 3708-3708 / com.nitrox.digitune E / AndroidRuntime:致命异常:主要
    工艺:com.nitrox.digitune,PID:3708
    显示java.lang.NullPointerException:尝试调用虚拟方法无效android.support.v7.widget.RecyclerView $ LayoutManager.stopSmoothScroller()'对空对象引用
            在android.support.v7.widget.RecyclerView.stopScrollersInternal(RecyclerView.java:1159)
            在android.support.v7.widget.RecyclerView.stopScroll(RecyclerView.java:1151)
            在android.support.v7.widget.RecyclerView.onDetachedFromWindow(RecyclerView.java:1356)
            在android.view.View.dispatchDetachedFromWindow(View.java:13441)
            在android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2837)
            在android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2834)
            在android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2834)
            在android.view.ViewGroup.removeViewInternal(ViewGroup.java:4163)
            在android.view.ViewGroup.removeViewInternal(ViewGroup.java:4136)
            在android.view.ViewGroup.removeView(ViewGroup.java:4068)
            在android.support.v4.view.ViewPager.removeView(ViewPager.java:1326)
            在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1045)
            在android.support.v4.app.FragmentManagerImpl.detachFragment(FragmentManager.java:1280)
            在android.support.v4.app.BackStackRecord.run(BackStackRecord.java:724)
            在android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1489)
            在android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:486)
            在android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
            在android.support.v4.view.ViewPager.populate(ViewPager.java:1073)
            在android.support.v4.view.ViewPager.populate(ViewPager.java:919)
            在android.support.v4.view.ViewPager $ 3.run(ViewPager.java:249)
            在android.view.Choreographer $ CallbackRecord.run(Choreographer.java:767)
            在android.view.Choreographer.doCallbacks(Choreographer.java:580)
            在android.view.Choreographer.doFrame(Choreographer.java:549)
            在android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:753)
            在android.os.Handler.handleCallback(Handler.java:739)
            在android.os.Handler.dispatchMessage(Handler.java:95)
            在android.os.Looper.loop(Looper.java:135)
            在android.app.ActivityThread.main(ActivityThread.java:5221)
            在java.lang.reflect.Method.invoke(本机方法)
            在java.lang.reflect.Method.invoke(Method.java:372)
            在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:899)
            在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
 

解决方案

基本上,你的LayoutManager是被布置在你的回收站已经完成它的。

从Android源:

  @覆盖
保护无效onDetachedFromWindow(){
    super.onDetachedFromWindow();
    如果(mItemAnimator!​​= NULL){
        mItemAnimator.endAnimations();
    }
    mFirstLayoutComplete = FALSE;
    stopScroll();
    mIsAttached = FALSE;
    如果(mLayout!= NULL){
        mLayout.onDetachedFromWindow(这一点,mRecycler);
    }
    removeCallbacks(mItemAnimatorRunner);
}
 

问题是stopScroll试图调用mLayout.stopSmoothScroller();任何检查mLayout为空。我扔togeather一个非常哈克热修复程序的应用程序,我一直在工作,但不应该被用来作为一个长期的解决方案,因为它是非常一个黑客,但我有一个时间紧迫,所以我不得不赶上空指针异常。我剪了我的处理程序,因为它是应用特定的。

我烫只是创造延长RecyclerView的自定义视图:

 进口android.content.Context;
进口android.support.v7.widget.RecyclerView;
进口android.util.AttributeSet;

公共类HotFixRecyclerView扩展RecyclerView
{
    公共HotFixRecyclerView(上下文的背景下)
    {
        超(上下文);
    }

    公共HotFixRecyclerView(上下文的背景下,ATTRS的AttributeSet)
    {
        超(背景下,ATTRS);
    }

    公共HotFixRecyclerView(上下文的背景下,ATTRS的AttributeSet,INT defStyle)
    {
        超(背景下,ATTRS,defStyle);
    }

    @覆盖
    公共无效stopScroll()
    {
        尝试
        {
            super.stopScroll();
        }
        赶上(NullPointerException异常除外)
        {
            / **
             *本mLayout已前的处置
             * RecyclerView这停止应用程序
             *崩溃。
             * /
        }
    }
}
 

然后切换到我自己的看法到RecyclerView所有引用。如果你使用它,请删除它,一旦机器人已经修补了这个问题,因为它是一个黑客攻击的一位。

I am trying to use the RecyclerView in my fragments. It shows up fine for the first tab, but when I swipe to the second tab and then back to the first one I get the following error:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView$LayoutManager.stopSmoothScroller()' on a null object reference

Does anyone know why I would be getting this error? It seems that there is a call that I'm missing before I the fragments switch, but I can't figure it out.

Pager Adapter for Fragments:

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 use a boilerplate class I created:

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

Base:

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();

}

EDIT

Error Stack Trace:

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)

解决方案

Basically, your LayoutManager is being disposed of before your recycler has finished with it.

From the Android source :

@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);
}

The problem is stopScroll tries to call mLayout.stopSmoothScroller(); without checking if mLayout is null. I threw togeather a very hacky hot fix for an app I've been working on but should NOT be used as a long term solution as it's very much a hack, but I had a tight deadline so I just had to catch the null pointer exception. I cut out my handler because it was application specific.

My hot fix was just to create a custom View extending the RecyclerView :

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.
             */
        }
    }
}

Then change all references to the RecyclerView to my own View. If you do use it please remove it once Android have patched this issue as it's a bit of a hack.

这篇关于为什么我让我的RecyclerView空引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆