Java 为什么我在我的RecyclerView上得到一个空引用
我试图在我的片段中使用RecyclerView。第一个选项卡显示良好,但当我滑动到第二个选项卡,然后返回到第一个选项卡时,我得到以下错误: java.lang.NullPointerException:尝试调用虚拟方法“void” android.support.v7.widget.RecyclerView$LayoutManager.stopSmoothScroller() 关于空对象引用 有人知道我为什么会犯这个错误吗?在我切换片段之前,似乎有一个调用我错过了,但我想不出来 片段的寻呼机适配器:Java 为什么我在我的RecyclerView上得到一个空引用,java,android,android-fragments,Java,Android,Android Fragments,我试图在我的片段中使用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和FragmentII使用我创建的样板类:
public class FragmentOne extends Base {
... code for displaying content in the RecyclerView. Just contains my custom Adapter for the RecyclerView ...
}
基数:
编辑
错误堆栈跟踪:
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)
基本上,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是否为null
我为一个我一直在开发的应用程序向她抛出了一个非常骇人的热修复程序,但我不建议将其用于长期解决方案,因为这是一个很大的预兆。如果你像我一样有一个很紧的截止日期,那么最好捕获空指针异常并忽略它
我的热修复程序只是创建一个扩展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.
*/
}
}
}
然后将所有引用从RecyclerView更改为HotFixRecyclerView。如果你真的使用它,请删除它一旦安卓修补了这个问题,因为这是一个有点黑客
- 如果您使用recylerview inn XML,请不要忘记相应地更改XML文件,以使用
而不是com.your.package.hotfix回收视图
android.support.v7.widget.RecyclerView
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
如果您的布局中有一个RecyclerView,并将其加载到活动中,则必须为其设置一个LayoutManager,否则在尝试销毁它时,它将抛出此异常。我刚刚经历了这个错误,这就是我解决它的方法: 我的活动根据项目的数量在一对文本视图或回收视图中显示元素:如果是项目集合,我使用回收视图;如果只有一个项目,它将显示在文本视图上,我将RecyclerView的可见性设置为
消失
然后,在第一种情况下,我调用了myRecyclerView.setLayoutManager(myLayoutManager),但在另一种情况下,我没有调用,因为我不打算使用它。在这两种情况下,包含RecyclerView的活动都得到了完美的显示。但是当关闭它时,在第二种情况下抛出了异常,因为尽管没有使用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;
}
在我的例子中,我在错误的适配器上安装了
notifyDataSetChanged()
。你能粘贴错误日志吗?请检查我的更新。我认为你的RecyclerView不是空的。它看起来更像是RecyclerView中的其他内容为null。可能是Google代码的错误。如果数据列表为空,请确保您也调用了setAdapter和setLayoutManager。当您删除片段并且FragmentManager试图与适配器内的某个视图交互时,就会发生这种情况。如果您没有调用setAdapter(也使用空列表)或setLayoutManager,您可以使用此代码的例外项,但我最终还是使用了以前使用过的Listview和viewholder模式。我只是想用Recyclerview bc弄脏我的手,它是一个非常好的小部件。不过我会接受你的回答。你知道他们会在什么时候修复它吗?据我所知,它仍然标记为“状态:FutureRelease”,我也有这个问题,但只有我的一个应用程序。为什么?他们什么时候会解决这个问题?顺便说一句,你的热修复程序没有和我一起解决这个问题。你是对的,如果RecycleView膨胀,你必须“如果”分配LayoutManager。当RecycleView在onCreateView()中实例化时,如何在onCreate()中将LayoutManager分配给RecycleView
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.xxx, container, false);
return mRootView;
}