带有Recyclerview的ViewPager上的NullPointerException

我们的应用程序中有一个ViewPager和一个包含三个片段的FragmentPagerAdapter 。 其中两个片段由每个片段的Recyclerview组成。

第一页(没有ViewPager的片段)正确显示。 但是,当ViewPager尝试预载下一个页面(一个RecyclerView)时,应用程序因为NullPointerException而崩溃,并显示以下日志:

  java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.support.v7.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference at android.support.v7.widget.RecyclerView.findMinMaxChildLayoutPositions(RecyclerView.java:2839) at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2626) at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3011) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1626) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573) at android.widget.FrameLayout.onLayout(FrameLayout.java:508) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557) at android.widget.LinearLayout.onLayout(LinearLayout.java:1466) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.support.design.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1000) at android.support.design.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:710) at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:724) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:907) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573) at android.widget.FrameLayout.onLayout(FrameLayout.java:508) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557) at android.widget.LinearLayout.onLayout(LinearLayout.java:1466) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573) at android.widget.FrameLayout.onLayout(FrameLayout.java:508) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557) at android.widget.LinearLayout.onLayout(LinearLayout.java:1466) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573) at android.widget.FrameLayout.onLayout(FrameLayout.java:508) at android.view.View.layout(View.java:15684) at android.view.ViewGroup.layout(ViewGroup.java:4981) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2186) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1920) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1106) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6018) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:792) at android.view.Choreographer.doCallbacks(Choreographer.java:596) at android.view.Choreographer.doFrame(Choreographer.java:557) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:778) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:155) at android.app.ActivityThread.main(ActivityThread.java:5696) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) 

以下是ViewPager的声明:

 ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager); ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); adapter.addFrag(fragment1, "fragment1"); adapter.addFrag(fragment2, "fragment2"); adapter.addFrag(fragment3, "fragment3"); viewPager.setAdapter(adapter); 

和适配器:

  private class ViewPagerAdapter extends FragmentPagerAdapter { private final List<Fragment> mFragmentList = new ArrayList<>(); private final List<String> mFragmentTitleList = new ArrayList<>(); public ViewPagerAdapter(FragmentManager manager) { super(manager); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } public void addFrag(Fragment fragment, String title) { mFragmentList.add(fragment); mFragmentTitleList.add(title); } @Override public CharSequence getPageTitle(int position) { return mFragmentTitleList.get(position); } } 

由于来自RecyclerView的代码很长且每页都有所不同,所以我不知道哪个部分是相关的,所以我不会给出任何示例。 如果您认为可以帮助解决问题,请毫不犹豫地询问具体的部分。

有一件事我可以告诉你,如果我想让它工作,我必须从setAdapter为每个setAdapter注释。

编辑 :这是第二页的代码。

 public class MyFragment extends Fragment { RecyclerView recyclerView; GridAdapter gridAdapter; public GridAdapter getGridAdapter() { return gridAdapter; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View v = inflater.inflate(R.layout.our_layout, container, false); recyclerView = (RecyclerView) v.findViewById(R.id.recycler_view); gridLayoutManager.setSmoothScrollbarEnabled(true); recyclerView.setLayoutManager(gridLayoutManager); recyclerView.setHasFixedSize(true); return v; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ArrayList<Model> model = getArguments().getParcelableArrayList("extra"); if (model != null && model.size() != 0) { gridAdapter = new GridAdapter(model); recyclerView.setAdapter(gridAdapter); } } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser && isResumed()){ onResume(); } } @Override public void onResume() { super.onResume(); if (!getUserVisibleHint()) return; } public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration { private int spanCount; private int spacingLeft; private int spacingRight; private int spacingTop; private int spacingBottom; private boolean includeEdge; public GridSpacingItemDecoration(int spanCount, int spacingLeft, int spacingTop, int spacingRight, int spacingBottom, boolean includeEdge) { this.spanCount = spanCount; this.spacingLeft = spacingLeft; this.spacingRight = spacingRight; this.spacingTop = spacingTop; this.spacingBottom = spacingBottom; this.includeEdge = includeEdge; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { int position = parent.getChildAdapterPosition(view); // item position int column = position % spanCount; // item column if (includeEdge) { outRect.left = spacingLeft - column * spacingLeft / spanCount; // spacing - column * ((1f / spanCount) * spacing) outRect.right = (column + 1) * spacingRight / spanCount; // (column + 1) * ((1f / spanCount) * spacing) if (position < spanCount) { // top edge outRect.top = spacingTop; } outRect.bottom = spacingBottom; // item bottom } else { outRect.left = column * spacingLeft / spanCount; // column * ((1f / spanCount) * spacing) outRect.right = spacingRight - (column + 1) * spacingRight / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing) if (position >= spanCount) { outRect.top = spacingTop; // item top } } } } public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder> { private ArrayList<Model> model; public GridAdapter(ArrayList<Model> offer) { super(); model = offer; } @Override public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) { final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item, parent, false); final ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { final Model currentOffer = model.get(position); holder.category.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @SuppressLint("NewApi") @SuppressWarnings("deprecation") @Override public void onGlobalLayout() { int width = holder.category.getWidth(); ViewGroup.LayoutParams params = holder.appIcon.getLayoutParams(); params.width = width; params.height = width; holder.appIcon.setLayoutParams(params); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) holder.itemView.getViewTreeObserver().removeOnGlobalLayoutListener(this); else holder.itemView.getViewTreeObserver().removeGlobalOnLayoutListener(this); } }); Picasso.with(getActivity().getApplicationContext()). load(currentOffer.getApp_logo()).fit().centerCrop().into(holder.appIcon); holder.appName.setText(currentOffer.getApp_name()); holder.category.setText(currentOffer.getApp_category()); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String marketURL = AndroidTools.getPlayStoreURL(currentOffer.getApp_store_id(), true); UITools.launchUrl(getActivity(), marketURL); } }); } @Override public int getItemCount() { return model.size(); } class ViewHolder extends RecyclerView.ViewHolder { private ImageView appIcon; private TextView appName; private TextView category; public ViewHolder(View itemView) { super(itemView); appIcon = (ImageView)itemView.findViewById(R.id.item_icon); appName = (TextView)itemView.findViewById(R.id.item_app_name); category = (TextView)itemView.findViewById(R.id.item_category); } } } } 

任何帮助深表感谢。

Solutions Collecting From Web of "带有Recyclerview的ViewPager上的NullPointerException"

我在开发过程中遇到了这个错误。 你有没有检查你的XML文件中的RecyclerView是否正确包装到另一个布局如FrameLayout?

如果没有,它只会在Viewpager上崩溃,而不会在单个片段视图上崩溃。

当您不小心将视图直接添加到RecyclerView时,会发生这种情况。 在我的情况下,我用View.inflate装饰布局与RecyclerView作为父参数,它自动附加。 RecyclerView迭代所有附加在它上面的子ViewHolders ,并期望它的所有视图子ViewHolders在布局参数中都具有ViewHolders ,并且在子ViewHolders的视图持有者为null时抛出这个NPE。

当你在你的xml布局文件中直接在listView或者RecyclerView添加元素时,会发生这种情况。

 <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.v7.widget.RecyclerView> 

这里我在RecyclerView里面添加了一个TextView,它会抛出onLayout error (由NullPointerException引起)。您不应该直接在RecyclerViewlistView下添加元素。

在回收器视图中添加子项并将attachToRoot inflate()方法的第三个参数attachToRoot设置为false同时将自定义布局膨胀工作。

 @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.online_user, parent, false); return new RecyclerViewHolder(view.findViewById(R.id.onlineUserView)); } 

布局:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/onlineUsersView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> 

更改:

  private final List<Fragment> mFragmentList = new ArrayList<>(); private final List<String> mFragmentTitleList = new ArrayList<>(); 

至:

  // remove final keyword private List<Fragment> mFragmentList = new ArrayList<>(); private List<String> mFragmentTitleList = new ArrayList<>(); 

最终variables不会采取任何值,即使您尝试添加它们。