airbnb / epoxy

Epoxy is an Android library for building complex screens in a RecyclerView
https://goo.gl/eIK82p
Apache License 2.0
8.49k stars 733 forks source link

Epoxy version 4.5.0 does not work with paging-runtime-ktx 3.0.0 #1203

Closed tuancoltech closed 2 years ago

tuancoltech commented 3 years ago

Hello,

So in our app we're using com.airbnb.android:epoxy-paging:4.5.0, which internally depends on androidx.paging:paging-runtime:2.0.0.

From another library module that we implements, androidx.paging:paging-runtime-ktx:3.0.0 is used. As Gradle's version resolution strategy, when the same library module is being used inside the app, the newer one will be selected. (https://docs.gradle.org/current/userguide/dependency_resolution.html)

Hence, we'll finally have the source code of com.airbnb.android:epoxy-paging:4.5.0 with androidx.paging:paging-runtime-ktx:3.0.0 inside the APK.

This leads to a crash with below stack trace:

Thread: main, Exception: java.lang.IllegalStateException: Failed to hijack update handler in AsyncPagedListDiffer.You can only build models on the main thread at com.airbnb.epoxy.paging.PagedListModelCache$asyncDiffer$1.(PagedListModelCache.kt:169) at com.airbnb.epoxy.paging.PagedListModelCache.(PagedListModelCache.kt:149) at com.airbnb.epoxy.paging.PagedListModelCache.(PagedListModelCache.kt:55) at com.airbnb.epoxy.paging.PagedListEpoxyController.(PagedListEpoxyController.kt:62) at com.airbnb.epoxy.paging.PagedListEpoxyController.(PagedListEpoxyController.kt:59) at im.vector.app.features.home.room.list.RoomSummaryPagedController.(RoomSummaryPagedController.kt:27) at im.vector.app.features.home.room.list.RoomSummaryPagedControllerFactory.createRoomSummaryPagedController(RoomSummaryPagedControllerFactory.kt:26) at im.vector.app.features.home.room.list.RoomListFragment.setupRecyclerView(RoomListFragment.kt:250) at im.vector.app.features.home.room.list.RoomListFragment.onViewCreated(RoomListFragment.kt:107) at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987) at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002) at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7660) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) Caused by: java.lang.NoSuchFieldException: No field mMainThreadExecutor in class Landroidx/paging/AsyncPagedListDiffer; (declaration of 'androidx.paging.AsyncPagedListDiffer' appears in /data/app/~~DH_CG1GATPrzhWIhETVmRQ==/im.vector.app.debug-TwcZ317FHCs1gBBbiJLzOA==/base.apk) at java.lang.Class.getDeclaredField(Native Method) at com.airbnb.epoxy.paging.PagedListModelCache$asyncDiffer$1.(PagedListModelCache.kt:157) at com.airbnb.epoxy.paging.PagedListModelCache.(PagedListModelCache.kt:149)  at com.airbnb.epoxy.paging.PagedListModelCache.(PagedListModelCache.kt:55)  at com.airbnb.epoxy.paging.PagedListEpoxyController.(PagedListEpoxyController.kt:62)  at com.airbnb.epoxy.paging.PagedListEpoxyController.(PagedListEpoxyController.kt:59)  at im.vector.app.features.home.room.list.RoomSummaryPagedController.(RoomSummaryPagedController.kt:27)  at im.vector.app.features.home.room.list.RoomSummaryPagedControllerFactory.createRoomSummaryPagedController(RoomSummaryPagedControllerFactory.kt:26)  at im.vector.app.features.home.room.list.RoomListFragment.setupRecyclerView(RoomListFragment.kt:250)  at im.vector.app.features.home.room.list.RoomListFragment.onViewCreated(RoomListFragment.kt:107)  at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987)  at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)  at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)  at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)  at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)  at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)  at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524)  at android.os.Handler.handleCallback(Handler.java:938)  at android.os.Handler.dispatchMessage(Handler.java:99)  at android.os.Looper.loop(Looper.java:223)  at android.app.ActivityThread.main(ActivityThread.java:7660)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

The reason is: Class PagedListModelCache inside paging-runtime's implementation relies on this field: mMainThreadExecutor, which is gotten from AsyncPagedListDiffer, via reflection.

Screen Shot 2021-06-23 at 00 07 20

However, from androidx.paging:paging-runtime-ktx:3.0.0, the field was renamed to mainThreadExecutor, which then breaks this logic of PagedListModelCache.

Screen Shot 2021-06-23 at 00 07 50

So my question is: Are you planing to update your epoxy-paging module to make it work with newer version of paging-runtime from Google?

If you are not doing it in a very near future, what would you suggest us doing to solve this issue?

Thanks.

elihart commented 3 years ago

Have you tried using epoxy's paging3 support? It's a different module from paging2 https://github.com/airbnb/epoxy/tree/master/epoxy-paging3

tuancoltech commented 3 years ago

Have you tried using epoxy's paging3 support? It's a different module from paging2 https://github.com/airbnb/epoxy/tree/master/epoxy-paging3

@elihart Yes, and it still does not work since the implementation is still the same.

Screen Shot 2021-06-23 at 13 31 21

FYI: I only changed from epoxy-paging to epoxy-paging3 without modifying any other code.

elihart commented 3 years ago

I see, yes it seems like what you're saying is right. Also in general AsyncPagedListDiffer and PagedList in the paging3 module are now deprecated and need to be replaced so the whole module needs an update.

I won't be able to do that work myself (paging is all community contributed) so if anyone wants this fixed please contribute the change with tests.

tuancoltech commented 3 years ago

I see, yes it seems like what you're saying is right. Also in general AsyncPagedListDiffer and PagedList in the paging3 module are now deprecated and need to be replaced so the whole module needs an update.

I won't be able to do that work myself (paging is all community contributed) so if anyone wants this fixed please contribute the change with tests.

Thank you for the response anyway.

alpinebuster commented 3 years ago

Same error here, anyone help ?

yqritc commented 2 years ago

@elihart

I see, yes it seems like what you're saying is right. Also in general AsyncPagedListDiffer and PagedList in the paging3 module are now deprecated and need to be replaced so the whole module needs an update.

PagedDataEpoxyController and PagedDataModelCache already exist in epoxy-paging3 module. I believe PagedListEpoxyController and PagedListModelCache are here for large application developers when they migrate from paging2 to paging3 because they don't have to change everything at once. I've just started migration and found this issue, so I've sent #1263.