使用 DiffUtil 更新异构 RecyclerView - Android

spo*_*rch 5 android refresh updates android-recyclerview

更新的问题:

\n\n

我有一个带有异构项目的 RecyclerView (RecyclerView 持有两种视图类型的项目)。我想用从 API 收到的新数据更新此 RecyclerView。

\n\n

所有示例和实现都显示了用于更新包含单一视图类型的项目的 RecyclerView 的 DiffUtil。

\n\n

我是 Android 初学者,尝试了以下代码 -

\n\n
public class TestDiffCallback extends DiffUtil.Callback {\n    private final List<Object> oldList;\n    private final List<Object> newList;\n\n    public TestDiffCallback(List<Object> oldList, List<Object> newList) {\n        this.oldList = oldList;\n        this.newList= newList;\n    }\n\n    @Override\n    public int getOldListSize() {\n        return oldList.size();\n    }\n\n    @Override\n    public int getNewListSize() {\n        return newList.size();\n    }\n\n    @Override\n    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {\n        if (oldList.get(oldItemPosition) instanceof ViewType1) {\n            return (((ViewType1) oldList.get(oldItemPosition)).getUniqueID())\n                    .equals(((ViewType1) newList.get(newItemPosition)).getUniqueID());\n        } else if (oldList.get(oldItemPosition) instanceof ViewType2) {\n            return (((ViewType2) oldList.get(oldItemPosition)).getUniqueID())\n                    .equals(((ViewType2) newList.get(newItemPosition)).getUniqueID());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {\n        if (oldList.get(oldItemPosition) instanceof ViewType1) {\n            final ViewType1 oldViewType1 = (ViewType1) oldList.get(oldItemPosition);\n            final ViewType1 newViewType1 = (ViewType1) oldList.get(newItemPosition);\n\n            return (\n                    oldViewType1.getUniqueID().equals(newViewType1.getUniqueID())\n            );\n        } else if (oldList.get(oldItemPosition) instanceof ViewType2) {\n            final ViewType2 oldViewType2 = (ViewType2) oldList.get(oldItemPosition);\n            final ViewType2 newViewType2 = (ViewType2) oldList.get(newItemPosition);\n\n            return (\n                    oldViewType2.getUniqueID().equals(newViewType2.getUniqueID())\n            );\n\n        }\n        return false;\n    }\n\n    @Nullable\n    @Override\n    public Object getChangePayload(int oldItemPosition, int newItemPosition) {\n        return super.getChangePayload(oldItemPosition, newItemPosition);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在我的异构视图适配器中我有这个 -

\n\n
public void updateHomeItems(List<Object> testItems) {\n    final TestDiffCallback diffCallback =\n            new TestDiffCallback(this.testItems, testItems);\n    final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);\n\n    this.testItems.clear();\n    this.testItems.addAll(testItems);\n    diffResult.dispatchUpdatesTo(this);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

从我的 Fragment 类中,我从 API 获取数据并将其传递给 DiffUtil,如下所示 -

\n\n
programAdapter.updateHomeItems(refreshedTestItemsList);\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我一直遇到的错误 -

\n\n
E/AndroidRuntime: FATAL EXCEPTION: main\n                     Process: com.acadnion, PID: 28315\n                     io.reactivex.exceptions.UndeliverableException: java.lang.ClassCastException: com.acadnion.models.ViewType2 cannot be cast to com.acadnion.models.ViewType1\n                     at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:366)\n                     at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:111)\n                     at android.os.Handler.handleCallback(Handler.java:751)\n                     at android.os.Handler.dispatchMessage(Handler.java:95)\n                     at android.os.Looper.loop(Looper.java:154)\n                     at android.app.ActivityThread.main(ActivityThread.java:6186)\n                     at java.lang.reflect.Method.invoke(Native Method)\n                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)\n                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)\n                     Caused by: java.lang.ClassCastException: com.acadnion.models.ViewType2 cannot be cast to com.acadnion.models.ViewType1\n                     at com.acadnion.utils.TestDiffCallback.areItemsTheSame(TestDiffCallback.java:36)\n                     at android.support.v7.util.DiffUtil.diffPartial(DiffUtil.java:224)\n                     at android.support.v7.util.DiffUtil.calculateDiff(DiffUtil.java:136)\n                     at android.support.v7.util.DiffUtil.calculateDiff(DiffUtil.java:97)\n                     at com.acadnion.adapters.ProgramAdapter.updateHomeItems(ProgramAdapter.java:160)\n                     at com.acadnion.fragments.TestFragment.addFetchedDataToList(TestFragment.java:182)\n                     at com.acadnion.fragments.TestFragment.access$100(TestFragment.java:45)\n                     at com.acadnion.fragments.TestFragment$3.onNext(TestFragment.java:153)\n                     at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:200)\n                     at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)\n                     at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)\n                     at android.os.Handler.handleCallback(Handler.java:751)\xc2\xa0\n                     at android.os.Handler.dispatchMessage(Handler.java:95)\xc2\xa0\n                     at android.os.Looper.loop(Looper.java:154)\xc2\xa0\n                     at android.app.ActivityThread.main(ActivityThread.java:6186)\xc2\xa0\n                     at java.lang.reflect.Method.invoke(Native Method)\xc2\xa0\n                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)\xc2\xa0\n                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)\xc2\xa0\n
Run Code Online (Sandbox Code Playgroud)\n