Coroutine issue / IllegalStateException: View ID [...] for 'view' not found
See original GitHub issueDisclaimer: Hi, I’ve been using Groupie for the past year, but it is kind of abandoned and EVERYBODY always says good things about epoxy, so I’m here trying to use it and breaking my head. One advice, your examples are really poor, there is 1 for java, 1 for kotlin, and 1 for paging. FastAdapter has like dozens of samples, Groupie itself has a very very complete sample. Wiki is really vague on a few things, like when to use withModels/epoxyController and which kind of ViewHolder is more efficient - there is a comment on KotlinModel saying it is not efficient, and another one on EpoxyModelWithHolder saying it is good. Makes a lot of confusion.
Anyway: I have this code (simplified) in Groupie:
class RowItem(val app: App) : Item(), CoroutineScope {
private var job: Job = Job()
override val coroutineContext: CoroutineContext = Dispatchers.Main + job
override fun unbind(holder: ViewHolder) {
job.cancel()
holder.icon.setImageDrawable(null)
holder.bottom_view.background = null
super.unbind(holder)
}
private val bottomShape = createShape(app.backgroundColor.darken, true)
private var drawable: Bitmap? = null
override fun getLayout() = R.layout.row_navigation_item
override fun bind(viewHolder: ViewHolder, position: Int) {
viewHolder.label.setTextAsync(app.title)
viewHolder.bottom_view.background = bottomShape
job = Job()
launch {
cacheDrawable() // PAY ATTENTION TO THIS
viewHolder.icon?.setImageBitmap(drawable)
}
}
private suspend inline fun cacheDrawable() {
if (drawable == null) {
drawable = withContext(Dispatchers.IO) {
AppManager.getIconFromId(app.packageName)?.toBitmap()
}
}
}
}
So I went ahead and converted it to Epoxy, following your samples:
internal class PhotoController : TypedEpoxyController<List<App>>() {
override fun buildModels(data: List<App>) {
data.forEach {
ItemDataClass(it)
.id("data class \${app.packageName}")
.addTo(this)
}
}
}
abstract class KotlinModel(
@LayoutRes private val layoutRes: Int
) : EpoxyModel<View>(), CoroutineScope {
private var job: Job = Job()
override val coroutineContext: CoroutineContext = Dispatchers.Main + job
override fun bind(view: View) {
job = Job()
this.view = view
bind()
}
override fun unbind(view: View) {
job.cancel()
this.view = null
}
// everything else is same as the sample
}
data class ItemDataClass(
val app: App, val sdkVersion: Int, val lastUpdateTime: String, val cornerRadius: Float
) : KotlinModel(R.layout.row_navigation_item) {
val icon by bind<ImageView>(R.id.icon)
val label by bind<AppCompatTextView>(R.id.label)
val bottom_view by bind<View>(R.id.bottom_view)
private val bottomShape = createShape(app.backgroundColor.darken, true)
private var drawable: Bitmap? = null
override fun bind() {
label.setTextAsync(app.title)
bottom_view.background = bottomShape
launch {
updateDrawable() // PAY ATTENTION TO THIS
icon.setImageBitmap(drawable)
}
}
private suspend inline fun updateDrawable() {
if (drawable == null) {
drawable = withContext(Dispatchers.IO) {
AppManager.getIconFromId(app.packageName)?.toBitmap()
}
}
}
}
Did you see the issue already? If I scroll very fast, by using the coroutines (since I don’t want to retrieve a drawable in main thread), when it is done, I believe icon might be null and it explodes with a IllegalStateException because getValue returns null for the view id.
It works perfectly with Groupie and the default RecyclerView. So, my question is, what should I do? Should I just go with viewBinding and forget this?
I am using 3.0.0-rc01.
Edit:
I just converted to DataBinding and… worked fine but first run got REALLY slow (like, from 1~2seconds to 6) since it is not parsing the images async - I don’t need to load them all, if it fetches them as the user scrolls is ok. Is there any strategies to fix this?
Edit 2: (again, almost no samples, which is bad) how are you using glide with it? 🤔
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (7 by maintainers)
You could link those two sections, I think would help a lot of people. I wouldn’t know if you haven’t linked it, thanks!
Well well, at the end of the day and with a lot of effort, everything is working perfectly! Thanks for all the help!!