我在我的应用程序上使用FastAdapter来呈现从远程API读取的项目列表。
在我片段的onCreateView
上,我以这种方式设置了适配器:
FastAdapter<ListModeBaseAdapterItem> fastAdapter = new FastAdapter<>();
itemAdapter = new ItemAdapter<>();
setItemClickListener(fastAdapter);
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
recyclerView.setAdapter(itemAdapter.wrap(fastAdapter));
recyclerView.setItemAnimator(new SlideDownAlphaAnimator());
recyclerView.getItemAnimator().setAddDuration(ADAPTER_ADD_DURATION);
recyclerView.getItemAnimator().setRemoveDuration(ADAPTER_REMOVE_DURATION);
然后,当加载新数据时,使用此行
更新适配器public void listModeImageItemsLoaded(List<ListModeBaseAdapterItem> listModeAdapterItems) {
itemAdapter.add(listModeAdapterItems);
}
以下是ListModeBaseAdapterItem
public abstract class ListModeBaseAdapterItem extends AbstractItem<ListModeBaseAdapterItem, ListModeBaseAdapterItem.ViewHolder> {
private static final ViewHolderFactory<? extends ViewHolder> FACTORY = new ItemFactory();
final ImageLoader imageLoader;
public Deal deal;
Context context;
public ListModeBaseAdapterItem(ImageLoader imageLoader) {
this.imageLoader = imageLoader;
}
public ListModeBaseAdapterItem withDeal(Deal deal) {
this.deal = deal;
return this;
}
@Override
public int getType() {
return R.id.list_mode_image_item_id;
}
@Override
public int getLayoutRes() {
return R.layout.item_list_mode_image;
}
@Override
public void bindView(ListModeBaseAdapterItem.ViewHolder viewHolder, List<Object> payloads) {
super.bindView(viewHolder, payloads);
context = viewHolder.itemView.getContext();
//View binding
}
@Override
public void unbindView(ViewHolder holder) {
super.unbindView(holder);
holder.dealImage.setImageDrawable(null);
holder.dealHeadline.setText(null);
holder.dealDiscount.setText(null);
holder.agreementIcon.setImageDrawable(null);
}
@Override
public ViewHolderFactory<? extends ViewHolder> getFactory() {
return FACTORY;
}
protected static class ItemFactory implements ViewHolderFactory<ViewHolder> {
public ViewHolder create(View v) {
return new ViewHolder(v);
}
}
protected static class ViewHolder extends RecyclerView.ViewHolder {
protected FrameLayout view;
@BindView(R.id.item_list_mode_image)
ImageView dealImage;
@BindView(R.id.item_list_mode_title)
TextView dealTitle;
@BindView(R.id.item_list_mode_headline)
TextView dealHeadline;
@BindView(R.id.item_list_mode_discount)
TextView dealDiscount;
@BindView(R.id.item_list_mode_agreement)
AppCompatImageView agreementIcon;
@BindView(R.id.item_list_mode_hot_badge)
TextView hotBadge;
@BindView(R.id.image_parent)
View imageParent;
public ViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
...
}
}
}
在大多数情况下它工作得很好。但是,我在Crashlytics中检测到,对于某些生产用户,应用程序崩溃时会出现以下堆栈跟踪。似乎适配器期望给定项目计数,但收到的数量少于此。但是,它没有多大意义,因为我只将一个项目列表传递给适配器,我无法看到我的代码的哪一部分是失败。
为了尝试重现该错误,我尝试将null
传递给itemAdapter.add
或带有空值的列表,但这会引发另一个异常。
这次崩溃的原因是什么?
Fatal Exception: java.util.NoSuchElementException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:854)
at java.util.HashMap$ValueIterator.next(HashMap.java:879)
at co.xxx.xxx.ui.listmode.view.ListModeBaseAdapterItem.getLayoutRes(Unknown Source)
at co.xxx.xxx.ui.listmode.view.ListModeBaseAdapterItem.withDeal(Unknown Source)
at co.xxx.xxx.ui.listmode.view.ListModeBaseAdapterItem.withDeal(Unknown Source)
at com.mikepenz.fastadapter.FastAdapter$OnBindViewHolderListenerImpl.onBindViewHolder(Unknown Source)
at com.mikepenz.fastadapter.FastAdapter.withOnClickListener(Unknown Source)
at com.mikepenz.fastadapter.AbstractAdapter.wrap(Unknown Source)
at android.support.v7.widget.RecyclerView$Adapter.onCreateViewHolder(Unknown Source)
at android.support.v7.widget.RecyclerView$Recycler.clear(Unknown Source)
at android.support.v7.widget.RecyclerView$Recycler.clear(Unknown Source)
at android.support.v7.widget.RecyclerView$Recycler.clear(Unknown Source)
at android.support.v7.widget.RecyclerView$Recycler.getScrapList(Unknown Source)
at android.support.v7.widget.LinearLayoutManager$LayoutState.hasMore(Unknown Source)
at android.support.v7.widget.GridLayoutManager.setStackFromEnd(Unknown Source)
at android.support.v7.widget.LinearLayoutManager.generateDefaultLayoutParams(Unknown Source)
at android.support.v7.widget.LinearLayoutManager.onSaveInstanceState(Unknown Source)
at android.support.v7.widget.GridLayoutManager.onLayoutChildren(Unknown Source)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(Unknown Source)
at android.support.v7.widget.RecyclerView.onMeasure(Unknown Source)
at android.view.View.measure(View.java:20084)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6282)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1705)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:797)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:657)
at android.view.View.measure(View.java:20084)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6282)
at android.support.design.widget.CoordinatorLayout.releaseTempRect(Unknown Source)
at android.support.design.widget.CoordinatorLayout.onMeasure(Unknown Source)
at android.view.View.measure(View.java:20084)
at android.support.v4.view.ViewPager.onMeasure(Unknown Source)
at android.view.View.measure(View.java:20084)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6282)
at android.support.design.widget.CoordinatorLayout.releaseTempRect(Unknown Source)
at android.support.design.widget.HeaderScrollingViewBehavior.onMeasureChild(Unknown Source)
at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onRequestChildRectangleOnScreen(Unknown Source)
at android.support.design.widget.CoordinatorLayout.onMeasure(Unknown Source)
at android.view.View.measure(View.java:20084)
at android.support.v4.widget.DrawerLayout.onMeasure(Unknown Source)
at android.view.View.measure(View.java:20084)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6282)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:214)
at android.support.v7.widget.ContentFrameLayout.onMeasure(Unknown Source)
at android.view.View.measure(View.java:20084)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6282)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1705)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:797)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:657)
at android.view.View.measure(View.java:20084)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6282)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:214)
at android.view.View.measure(View.java:20084)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6282)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1705)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:797)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:657)
at android.view.View.measure(View.java:20084)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6282)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:214)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:714)
at android.view.View.measure(View.java:20084)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2627)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1577)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1846)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1462)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6960)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:907)
at android.view.Choreographer.doCallbacks(Choreographer.java:709)
at android.view.Choreographer.doFrame(Choreographer.java:644)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:893)
at android.os.Handler.handleCallback(Handler.java:836)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:208)
at android.app.ActivityThread.main(ActivityThread.java:6267)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)