@@ -7,7 +7,8 @@ import androidx.annotation.DrawableRes
77import androidx.compose.foundation.Image
88import androidx.compose.foundation.layout.Box
99import androidx.compose.runtime.Composable
10- import androidx.compose.runtime.collectAsState
10+ import androidx.compose.runtime.MutableState
11+ import androidx.compose.runtime.mutableStateOf
1112import androidx.compose.runtime.remember
1213import androidx.compose.ui.Alignment
1314import androidx.compose.ui.Modifier
@@ -20,21 +21,12 @@ import androidx.compose.ui.graphics.painter.ColorPainter
2021import androidx.compose.ui.graphics.painter.Painter
2122import androidx.compose.ui.layout.ContentScale
2223import androidx.compose.ui.layout.Layout
23- import androidx.compose.ui.layout.layout
2424import androidx.compose.ui.platform.LocalContext
2525import androidx.compose.ui.platform.LocalInspectionMode
2626import com.bumptech.glide.Glide
2727import com.bumptech.glide.RequestBuilder
2828import com.bumptech.glide.RequestManager
29- import com.bumptech.glide.integration.ktx.AsyncGlideSize
30- import com.bumptech.glide.integration.ktx.ExperimentGlideFlows
31- import com.bumptech.glide.integration.ktx.GlideFlowInstant
32- import com.bumptech.glide.integration.ktx.ImmediateGlideSize
3329import com.bumptech.glide.integration.ktx.InternalGlideApi
34- import com.bumptech.glide.integration.ktx.ResolvableGlideSize
35- import com.bumptech.glide.integration.ktx.Resource
36- import com.bumptech.glide.integration.ktx.Status
37- import com.bumptech.glide.integration.ktx.flowResolvable
3830import com.bumptech.glide.load.DataSource
3931import com.google.accompanist.drawablepainter.DrawablePainter
4032import com.google.accompanist.drawablepainter.rememberDrawablePainter
@@ -90,7 +82,6 @@ public typealias RequestBuilderTransform<T> = (RequestBuilder<T>) -> RequestBuil
9082// to RequestBuilder (though thumbnail() may make that a challenge).
9183// TODO(judds): Consider how to deal with transitions.
9284@ExperimentalGlideComposeApi
93- @OptIn(InternalGlideApi ::class )
9485@Composable
9586public fun GlideImage (
9687 model : Any? ,
@@ -144,16 +135,16 @@ public fun GlideImage(
144135 }
145136 }
146137 } else {
147- val size : ImmediateGlideSize ? = requestBuilder.overrideSize()?. let { ImmediateGlideSize (it) }
148- ModifierGlideImage (
149- requestBuilder,
150- size ,
151- contentDescription,
152- modifier ,
153- alignment ,
154- contentScale ,
155- alpha ,
156- colorFilter,
138+ SimpleLayout (
139+ modifier
140+ .glideNode(
141+ requestBuilder ,
142+ contentDescription,
143+ alignment ,
144+ contentScale ,
145+ alpha ,
146+ colorFilter ,
147+ )
157148 )
158149 }
159150}
@@ -173,34 +164,14 @@ public interface GlideSubcompositionScope {
173164 public val painter: Painter
174165}
175166
176- @OptIn(ExperimentGlideFlows ::class )
177167@ExperimentalGlideComposeApi
178168internal class GlideSubcompositionScopeImpl (
179- private val value : GlideFlowInstant <Drawable >? ,
169+ private val drawable : Drawable ? ,
170+ override val state : RequestState
180171) : GlideSubcompositionScope {
181172
182173 override val painter: Painter
183- get() = value?.drawable()?.toPainter() ? : ColorPainter (Color .Transparent )
184-
185- override val state: RequestState
186- get() = when (val current = value) {
187- is com.bumptech.glide.integration.ktx.Placeholder -> {
188- when (current.status) {
189- Status .CLEARED -> RequestState .Loading
190- Status .RUNNING -> RequestState .Loading
191- Status .FAILED -> RequestState .Failure
192- Status .SUCCEEDED -> throw IllegalStateException ()
193- }
194- }
195-
196- is Resource -> RequestState .Success (current.dataSource)
197- null -> RequestState .Loading
198- }
199-
200- private fun GlideFlowInstant<Drawable>.drawable (): Drawable ? = when (this ) {
201- is com.bumptech.glide.integration.ktx.Placeholder -> placeholder
202- is Resource -> resource
203- }
174+ get() = drawable?.toPainter() ? : ColorPainter (Color .Transparent )
204175
205176 private fun Drawable.toPainter (): Painter =
206177 when (this ) {
@@ -210,19 +181,6 @@ internal class GlideSubcompositionScopeImpl(
210181 }
211182}
212183
213- @OptIn(InternalGlideApi ::class )
214- private fun Modifier.sizeObservingModifier (size : ResolvableGlideSize ): Modifier =
215- this .layout { measurable, constraints ->
216- if (size is AsyncGlideSize ) {
217- val inferredSize = constraints.inferredGlideSize()
218- if (inferredSize != null ) {
219- size.setSize(inferredSize)
220- }
221- }
222- val placeable = measurable.measure(constraints)
223- layout(placeable.width, placeable.height) { placeable.place(0 , 0 ) }
224- }
225-
226184/* *
227185 * The current state of a request associated with a Glide painter.
228186 *
@@ -295,7 +253,7 @@ public sealed class RequestState {
295253 * load never starting, or in an unreasonably large amount of memory being used. Loading overly
296254 * large images in memory can also impact scrolling performance.
297255 */
298- @OptIn(InternalGlideApi ::class , ExperimentGlideFlows :: class )
256+ @OptIn(InternalGlideApi ::class )
299257@ExperimentalGlideComposeApi
300258@Composable
301259public fun GlideSubcomposition (
@@ -310,27 +268,45 @@ public fun GlideSubcomposition(
310268 requestBuilderTransform(requestManager.load(model))
311269 }
312270
313- val overrideSize = requestBuilder.overrideSize()
314- val size = remember(overrideSize) {
315- if (overrideSize != null ) {
316- ImmediateGlideSize (overrideSize)
317- } else {
318- AsyncGlideSize ()
271+ val requestState: MutableState <RequestState > =
272+ remember(model, requestManager, requestBuilderTransform) {
273+ mutableStateOf(RequestState .Loading )
319274 }
275+ val drawable: MutableState <Drawable ?> = remember(model, requestManager, requestBuilderTransform) {
276+ mutableStateOf(null )
320277 }
321278
322- val result = remember(requestBuilder, size) {
323- requestBuilder.flowResolvable(size)
324- }.collectAsState(initial = null )
279+ val requestListener: StateTrackingListener =
280+ remember(model, requestManager, requestBuilderTransform) {
281+ StateTrackingListener (
282+ requestState,
283+ drawable
284+ )
285+ }
325286
326- val scope = GlideSubcompositionScopeImpl (result .value)
287+ val scope = GlideSubcompositionScopeImpl (drawable.value, requestState .value)
327288
328- if (overrideSize != null ) {
289+ Box (
290+ modifier
291+ .glideNode(
292+ requestBuilder,
293+ draw = false ,
294+ requestListener = requestListener,
295+ )
296+ ) {
329297 scope.content()
330- } else {
331- Box (modifier = modifier.sizeObservingModifier(size)) {
332- scope.content()
333- }
298+ }
299+ }
300+
301+ @ExperimentalGlideComposeApi
302+ private class StateTrackingListener (
303+ val state : MutableState <RequestState >,
304+ val drawable : MutableState <Drawable ?>
305+ ) : RequestListener {
306+
307+ override fun onStateChanged (model : Any? , drawable : Drawable ? , requestState : RequestState ) {
308+ state.value = requestState
309+ this .drawable.value = drawable
334310 }
335311}
336312
@@ -472,31 +448,14 @@ private fun RequestBuilder<Drawable>.contentScaleTransform(
472448 // TODO(judds): Think about how to handle the various fills
473449}
474450
475- @OptIn( InternalGlideApi :: class , ExperimentalGlideComposeApi :: class )
451+
476452@Composable
477- private fun ModifierGlideImage (
478- requestBuilder : RequestBuilder <Drawable >,
479- size : ImmediateGlideSize ? ,
480- contentDescription : String? ,
453+ private fun SimpleLayout (
481454 modifier : Modifier ,
482- alignment : Alignment ,
483- contentScale : ContentScale ,
484- alpha : Float ,
485- colorFilter : ColorFilter ?
486455) {
487456 Layout (
488- {},
489457 modifier
490- .glideNode(
491- requestBuilder,
492- size,
493- contentDescription,
494- alignment,
495- contentScale,
496- alpha,
497- colorFilter,
498- )
499- ) { _, constraints ->
458+ ) { _, constraints ->
500459 layout(constraints.minWidth, constraints.minHeight) {}
501460 }
502461}
0 commit comments