ianrumac
10/27/2019, 12:07 PMContainer{
val state = +model{ NetworkImagemodel(bitmap: null); } // this is a @Model annotated data class
glideBitmapReady(src,context) {
state.bitmap = it //this is callback from Glide's onResourceReady
}
onCommit(state) {
println("Loaded)"
}
}
I get a IllegalStateException: Not in a frame
pointing to the change of state model (state.bitmap = it //this is callback from Glide's onResourceReady
)Andrey Kulikov
10/27/2019, 12:11 PMianrumac
10/27/2019, 12:13 PMGlide.with( context).asBitmap().load(src)
.addListener(object :
RequestListener<Bitmap> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Bitmap>?,
isFirstResource: Boolean
): Boolean {
e!!.printStackTrace()
return false
}
override fun onResourceReady(
resource: Bitmap?,
_model: Any?,
target: Target<Bitmap>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
callback(resource)
return true
}
}).preload()
Leland Richardson [G]
10/27/2019, 2:57 PMglideBitmapReady
function, as you noticed, will run too oftenonCommit
effect is a way to run code when compose actually applies the changes to the UI, and only when some number of inputs have changed (like memo)fun glideBitmapReady(src: String) = effectOf<Bitmap?> {
val result = +state<Bitmap> { null }
val context = +ambient(AmbientContext)
+onPreCommit(src) {
val listener = object : RequestListener<Bitmap> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Bitmap>?,
isFirstResource: Boolean
): Boolean {
e!!.printStackTrace()
return false
}
override fun onResourceReady(
resource: Bitmap?,
_model: Any?,
target: Target<Bitmap>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
result.value = resource
return true
}
}
val glide = Glide
.with(context)
.asBitmap()
.load(src)
.addListener(listener)
.preload()
onDispose {
glide.removeListener(listener)
}
}
result.value
}
= effectOf<Bitmap?>
would just turn into : Bitmap?
and all of the pluses would go awayonPreCommit
when the src
string changes. this means that things will properly update if you change the src stringremoveListener
was an API that exists, but let me know if it doesntonDispose
here with the removeListener
call, which ensures that as the src string changes, I clean up any old requests that had been set up from earlier versionsvar bitmap = +glideBitmapReady(src)
IllegalStateException: Not in a frame
was because you were mutating the model in a different thread. This is totally allowed, but you have to do a little bit of extra work. In this case, you need to open up a model transaction and commit it.
I’m not in a place to look up the exact API, but I believe if you look in androidx.compose.frames
it will be something like
open {
myModel.property = newValue
commit()
}
ianrumac
10/27/2019, 3:14 PMLeland Richardson [G]
10/27/2019, 3:16 PMianrumac
10/27/2019, 3:18 PMopen
tip, I assumed that I was out of the UI scope/thread when getting the exception, and started going through `Frames’ to figure out what was going on but couldn’t really wrap my head around it, now it’s more obvious.Leland Richardson [G]
10/27/2019, 3:19 PMianrumac
10/27/2019, 3:22 PMLeland Richardson [G]
10/27/2019, 3:22 PMeffectOf
for nowframe
doesn’t actually correspond to the UI’s sense of frame
hereianrumac
10/27/2019, 3:23 PMLeland Richardson [G]
10/27/2019, 3:23 PMianrumac
10/27/2019, 3:28 PMModel
, transaction does fit betterLeland Richardson [G]
10/27/2019, 3:32 PMianrumac
10/27/2019, 3:49 PM