Abbiamo sulla nostra app uno ViewPager con uno FragmentPagerAdapter
che contiene tre frammenti. Due di questi frammenti sono composti con uno Recyclerview per ciascuno.NullPointerException su ViewPager con Recyclerview
La prima pagina (il frammento senza ViewPager) viene visualizzata correttamente. Tuttavia, quando il ViewPager cerca di pre-caricare la pagina successiva (un RecyclerView), l'applicazione si blocca a causa di un NullPointerException
con il seguente 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)
Ecco come il ViewPager è dichiarato:
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);
e l'adattatore:
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);
}
}
come il codice sia del RecyclerView è lungo e diverso per ogni pagina io non so davvero quale parte rilevante così vi frega qualsiasi campione Non esitare a chiedere una parte specifica se pensi che possa essere utile risolvere il problema.
Una cosa che posso dirvi è che se voglio che funzioni, devo commentare la chiamata per ciascuno degli setAdapter
da entrambi i RecylerView.
MODIFICA: ecco il codice per la seconda pagina.
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);
}
}
}
}
Qualsiasi aiuto è molto apprezzato.
c'è qualche recyclerView nel terzo frammento? [EDITED] scusate, è lì. Puoi pubblicare il codice del tuo secondo frammento –
La prima pagina è un frammento senza alcuna RecyclerView. Tuttavia, sì, il secondo e il terzo sono frammenti composti con un RecyclerView per ciascuno. – Neeeko
Puoi pubblicare il tuo metodo 'onBindViewHolder()' dell'adattatore? – Rami