idanatz / OneAdapter

A Viewholderless Adapter for RecyclerView, who supports builtin diffing, states (paging, empty...), events (clicking, swiping...), and more.
MIT License
470 stars 45 forks source link

Random crash in onCreate #34

Closed vellrya closed 3 years ago

vellrya commented 3 years ago

Hello!

Sometimes (<1%) there is an exceptiom in onCreate with this stacktrace:

2020-12-05 18:23:07.758 14685-14685/com.sample.app E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.sample.app, PID: 14685
    kotlin.TypeCastException: null cannot be cast to non-null type V
        at com.idanatz.oneadapter.internal.holders.ViewBinder.findViewById(ViewBinder.kt:31)
        at com.sample.app.DialogsActivity$DialogModule$2.invoke(DialogsActivity.kt:50)
        at com.sample.app.DialogsActivity$DialogModule$2.invoke(DialogsActivity.kt:37)
        at com.idanatz.oneadapter.internal.InternalAdapter$register$1$create$1.onBind(InternalAdapter.kt:233)
        at com.idanatz.oneadapter.internal.holders.OneViewHolder.onBindViewHolder(OneViewHolder.kt:51)
        at com.idanatz.oneadapter.internal.InternalAdapter.onBindViewHolder(InternalAdapter.kt:118)
        at com.idanatz.oneadapter.internal.InternalAdapter.onBindViewHolder(InternalAdapter.kt:39)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:530)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:759)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
2020-12-05 18:23:07.759 14685-14685/com.sample.app E/AndroidRuntime:     at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2515)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2224)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1410)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6834)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
        at android.view.Choreographer.doCallbacks(Choreographer.java:778)
        at android.view.Choreographer.doFrame(Choreographer.java:713)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6809)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
2020-12-05 18:23:07.761 14685-14685/com.sample.app E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.sample.app, PID: 14685
    kotlin.TypeCastException: null cannot be cast to non-null type V
        at com.idanatz.oneadapter.internal.holders.ViewBinder.findViewById(ViewBinder.kt:31)
        at com.sample.app.DialogsActivity$DialogModule$2.invoke(DialogsActivity.kt:50)
        at com.sample.app.DialogsActivity$DialogModule$2.invoke(DialogsActivity.kt:37)
        at com.idanatz.oneadapter.internal.InternalAdapter$register$1$create$1.onBind(InternalAdapter.kt:233)
        at com.idanatz.oneadapter.internal.holders.OneViewHolder.onBindViewHolder(OneViewHolder.kt:51)
        at com.idanatz.oneadapter.internal.InternalAdapter.onBindViewHolder(InternalAdapter.kt:118)
        at com.idanatz.oneadapter.internal.InternalAdapter.onBindViewHolder(InternalAdapter.kt:39)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:530)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:759)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
2020-12-05 18:23:07.761 14685-14685/com.sample.app E/AndroidRuntime:     at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2515)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2224)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1410)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6834)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
        at android.view.Choreographer.doCallbacks(Choreographer.java:778)
        at android.view.Choreographer.doFrame(Choreographer.java:713)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6809)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
2020-12-05 18:23:07.761 14685-14685/com.sample.app D/AppTracker: App Event: crash

Code DialogsActivity.kt, line 50:

onBind { model, viewBinder, metadata ->
    viewBinder.findViewById<TextView>(R.id.titleTv).text = model.name
   ...
}

DialogsActivity has DataBinding and ViewBinding, probably. there is some conflict between internal oneAdapter binding?

idanatz commented 3 years ago

Hi Haven't got this exception in any of my apps or tests.

The fact that the activity is using DataBinding and ViewBinding should not make a difference since you supply the layout the view holder should use and it is inflated inside the library.

Does the adapter hold multiple types of data or a single type?

By the way, if you wish to use DataBinding in view holder layout as well, there is support for that, check the sample project.

vellrya commented 3 years ago

DialogsActivity code:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityDialogsBinding.inflate(layoutInflater)
        setContentView(binding.root)
        ... (1)
        val oneAdapter = OneAdapter(binding.dialogsRV)
            .attachItemModule(DialogModule())
        ... (2)
        val layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        binding.dialogsRV.layoutManager = layoutManager
        ...
        dialogViewModel.allDialogs.observe(this) { dialogs ->
            oneAdapter.setItems(dialogs)
       }
}

I will try to swap (1) and (2) code fragment, probably this is the reason of crash)

idanatz commented 3 years ago

the layout manager should be attached to the RecyclerView before the adapter creation. tell me if it is still happening after the change