NullPointerException en ViewPager con Recyclerview

Tenemos en nuestra aplicación un ViewPager con un FragmentPagerAdapter que contiene tres fragmentos. Dos de estos fragmentos se componen con una Recyclerview para cada uno.

La primera página (el fragmento sin ViewPager) se muestra correctamente. Sin embargo, cuando ViewPager intenta pre-cargar la página siguiente (un RecyclerView), la aplicación se bloquea debido a una NullPointerException con el siguiente registro:

  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) 

A continuación se muestra cómo se declara 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); 

Y el adaptador:

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

Como el código de ambos RecyclerView es largo y diferente para cada página realmente no sé qué parte es relevante por lo que no daré ninguna muestra. No dude en pedir una parte específica si cree que puede ser útil para solucionar el problema.

Una cosa que puedo decir es que si quiero que funcione, tengo que comentar la llamada para cada uno de los setAdapter de ambos de RecylerView.

EDIT : Aquí está el código para la segunda página.

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

Cualquier ayuda es muy apreciada.

Tengo este error durante uno de mis desarrollos. ¿Ha comprobado que su RecyclerView en sus archivos XML está correctamente envuelto en otro diseño como un FrameLayout?

Si no, se bloqueará sólo en un Viewpager y no en la vista de fragmento único.

Esto sucede cuando agrega vistas accidentalmente al RecyclerView . En mi caso, utilicé View.inflate para un diseño de decorador con el RecyclerView como parámetro principal, que automáticamente lo adjunta. RecyclerView itera sobre cualquier niño conectado a él y espera que todos sus niños de la visión tengan ViewHolders en los params de la disposición, y lanzará este NPE cuando el sostenedor de la opinión de un niño es nulo.

Esto sucede cuando agrega elementos directamente en listView o RecyclerView en su archivo de diseño xml .

 <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> 

Aquí he añadido un TextView dentro de RecyclerView que me lanzará onLayout error (causado por NullPointerException ). No debe agregar elementos directamente en RecyclerView o listView .

No añadir a los niños en la vista del reciclador y establecer attachToRoot , el tercer parámetro del método attachToRoot inflate() a false mientras inflar el diseño personalizado funcionó para mí.

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

Diseño:

 <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> 

Cambio:

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

a:

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

La variable final no tomará valores, aunque intente agregarlos.

  • Descripción de RecyclerView.ViewHolder
  • Incrustación de anuncios en Recyclerview
  • Eliminar los efectos de desplazamiento de RecyclerView
  • El uso del ejemplo de RecyclerView no compila
  • Cómo importar RecyclerView para Android L-preview
  • RecyclerView Adapter da error "La jerarquía del tipo RecycleAdapter es inconsistente"
  • ¿Cómo se puede agregar una línea de divisor en un Android RecyclerView?
  • RecyclerView no llama aCreateViewHolder o onBindView
  • Reciclador vista de la lista de desplazamiento vertical con fila horizontal desplazable
  • ¿Cómo crear RecyclerView con múltiples tipos de vista?
  • RecyclerView y SwipeRefreshLayout
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.