question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Getting a crash when reusing layouts for different EpoxyModel

See original GitHub issue

I have two EpoxyModelWithHolders that I’d like to have use the same layout file. However, I am getting ClassCastException at random times; usually when the controller is refreshed again. If I switch the layout file and change nothing else, it works. Is this expected behavior?

A simple example follows.

First model

@EpoxyModelClass(layout = R.layout.test_epoxy_layout)
abstract class TestEpoxyView1 : EpoxyModelWithHolder<TestEpoxyView1.ViewHolder>() {
    class ViewHolder : KotlinEpoxyHolder()
}

Second model

If I change this to point at another layout resource (even an exact duplicate of test_epoxy_layout) it will no longer crash

@EpoxyModelClass(layout = R.layout.test_epoxy_layout)
abstract class TestEpoxyView2 : EpoxyModelWithHolder<TestEpoxyView2.ViewHolder>() {
  class ViewHolder : KotlinEpoxyHolder()
}

Layout file test_epoxy_layout

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="1dp"
  android:background="#FFFFFF" />

Inside Controller.buildModels()

    testEpoxyView1 { id(UUID.randomUUID().toString()) }
    testEpoxyView2 { id(UUID.randomUUID().toString()) }

The following exception is thrown the second time the controller is updated.

 java.lang.ClassCastException: xxxx.TestEpoxyView2$ViewHolder cannot be cast to xxxx.TestEpoxyView1$ViewHolder
        at xxxx.TestEpoxyView1_.handlePreBind(TestEpoxyView1_.java:22)
        at com.airbnb.epoxy.EpoxyViewHolder.bind(EpoxyViewHolder.java:53)
        at com.airbnb.epoxy.BaseEpoxyAdapter.onBindViewHolder(BaseEpoxyAdapter.java:98)
        at com.airbnb.epoxy.BaseEpoxyAdapter.onBindViewHolder(BaseEpoxyAdapter.java:15)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3641)
        at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1888)
        at androidx.recyclerview.widget.RecyclerView$1.run(RecyclerView.java:407)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
        at android.view.Choreographer.doCallbacks(Choreographer.java:723)
        at android.view.Choreographer.doFrame(Choreographer.java:655)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
        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:6541)
        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)

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:3
  • Comments:11 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
baoticommented, Oct 31, 2019

You can share the Holder Class or use a layout resource alias in ViewModel2.

1reaction
markherschercommented, Oct 30, 2019

Is it documented somewhere that two or more view holders cannot use the same layout resource?

I won’t go into the boring details but basically we wanted to reuse a layout file but didn’t need to reuse the view holder. We certainly can, but we were surprised by the crash.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Epoxy updating the epoxy attributes in the models once they ...
Problem. I'm not the Epoxy expert, but Epoxy models are required to be not modified after they were added to the controller.
Read more >
Crash when switching between layouts in AutoCAD
When switching between layouts within AutoCAD, the program crashes, with or without an error message.
Read more >
Displaying API data with Epoxy | Android 2022 | Kotlin
This episode covers everything you need to know about handling network requests, mapping API data to domain data, and displaying the data in ......
Read more >
Move Fast & *Don't* Break Things. A retrospective ... - Medium
The paradigm change between the current Android layout style and Jetpack Compose is huge, but we're excited about the direction that the platform...
Read more >
Epoxy for Android - Airbnb Engineering & Data Science
You should subclass EpoxyModel to specify what layout your model uses and how to bind data ... This is a bit different from...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found