Skip to content

Commit

Permalink
Add an experimental rememberGlidePainter API
Browse files Browse the repository at this point in the history
  • Loading branch information
sjudd committed Jul 13, 2023
1 parent fd96de2 commit 8420af5
Show file tree
Hide file tree
Showing 19 changed files with 794 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.app.Application;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RawRes;
import androidx.benchmark.BenchmarkState;
Expand Down Expand Up @@ -111,17 +112,17 @@ private void loadImageWithExpectedDataSource(
public boolean onLoadFailed(
@Nullable GlideException e,
Object model,
Target<Bitmap> target,
@NonNull Target<Bitmap> target,
boolean isFirstResource) {
return false;
}

@Override
public boolean onResourceReady(
Bitmap resource,
Object model,
@NonNull Bitmap resource,
@NonNull Object model,
Target<Bitmap> target,
DataSource dataSource,
@NonNull DataSource dataSource,
boolean isFirstResource) {
dataSourceRef.set(dataSource);
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ public void thumbnail_onResourceReady_forPrimary_isComplete_whenRequestListenerI
public boolean onLoadFailed(
@Nullable GlideException e,
Object model,
Target<Drawable> target,
@NonNull Target<Drawable> target,
boolean isFirstResource) {
return false;
}

@Override
public boolean onResourceReady(
Drawable resource,
Object model,
@NonNull Drawable resource,
@NonNull Object model,
Target<Drawable> target,
DataSource dataSource,
@NonNull DataSource dataSource,
boolean isFirstResource) {
isPrimaryRequestComplete.set(target.getRequest().isComplete());
countDownLatch.countDown();
Expand Down Expand Up @@ -115,7 +115,7 @@ public void thumbnail_onLoadFailed_forPrimary_isNotRunningOrComplete_whenRequest
public boolean onLoadFailed(
@Nullable GlideException e,
Object model,
Target<Drawable> target,
@NonNull Target<Drawable> target,
boolean isFirstResource) {
Request request = target.getRequest();
isNeitherRunningNorComplete.set(!request.isComplete() && !request.isRunning());
Expand All @@ -125,10 +125,10 @@ public boolean onLoadFailed(

@Override
public boolean onResourceReady(
Drawable resource,
Object model,
@NonNull Drawable resource,
@NonNull Object model,
Target<Drawable> target,
DataSource dataSource,
@NonNull DataSource dataSource,
boolean isFirstResource) {
return false;
}
Expand Down
58 changes: 58 additions & 0 deletions integration/compose/api/compose.api
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
public final class com/bumptech/glide/integration/compose/AnimationState : java/lang/Enum {
public static final field Animate Lcom/bumptech/glide/integration/compose/AnimationState;
public static final field Failed Lcom/bumptech/glide/integration/compose/AnimationState;
public static final field Loading Lcom/bumptech/glide/integration/compose/AnimationState;
public static final field Success Lcom/bumptech/glide/integration/compose/AnimationState;
public static fun valueOf (Ljava/lang/String;)Lcom/bumptech/glide/integration/compose/AnimationState;
public static fun values ()[Lcom/bumptech/glide/integration/compose/AnimationState;
}

public final class com/bumptech/glide/integration/compose/AsyncLayoutSize {
public static final field $stable I
public fun <init> (Lcom/bumptech/glide/integration/ktx/AsyncGlideSize;)V
public final fun copy (Lcom/bumptech/glide/integration/ktx/AsyncGlideSize;)Lcom/bumptech/glide/integration/compose/AsyncLayoutSize;
public static synthetic fun copy$default (Lcom/bumptech/glide/integration/compose/AsyncLayoutSize;Lcom/bumptech/glide/integration/ktx/AsyncGlideSize;ILjava/lang/Object;)Lcom/bumptech/glide/integration/compose/AsyncLayoutSize;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public abstract interface annotation class com/bumptech/glide/integration/compose/ExperimentalGlideComposeApi : java/lang/annotation/Annotation {
}

Expand All @@ -8,6 +27,45 @@ public final class com/bumptech/glide/integration/compose/GlideImageKt {
public static final fun placeholder (Lkotlin/jvm/functions/Function2;)Lcom/bumptech/glide/integration/compose/Placeholder;
}

public abstract class com/bumptech/glide/integration/compose/GlidePainter : androidx/compose/ui/graphics/painter/Painter {
public static final field $stable I
public fun <init> ()V
public abstract fun getState ()Lcom/bumptech/glide/integration/compose/GlidePainter$State;
}

public abstract class com/bumptech/glide/integration/compose/GlidePainter$State {
public static final field $stable I
}

public final class com/bumptech/glide/integration/compose/GlidePainter$State$Failure : com/bumptech/glide/integration/compose/GlidePainter$State {
public static final field $stable I
public static final field INSTANCE Lcom/bumptech/glide/integration/compose/GlidePainter$State$Failure;
}

public final class com/bumptech/glide/integration/compose/GlidePainter$State$Loading : com/bumptech/glide/integration/compose/GlidePainter$State {
public static final field $stable I
public static final field INSTANCE Lcom/bumptech/glide/integration/compose/GlidePainter$State$Loading;
}

public final class com/bumptech/glide/integration/compose/GlidePainter$State$Success : com/bumptech/glide/integration/compose/GlidePainter$State {
public static final field $stable I
public fun <init> (Lcom/bumptech/glide/load/DataSource;)V
public final fun component1 ()Lcom/bumptech/glide/load/DataSource;
public final fun copy (Lcom/bumptech/glide/load/DataSource;)Lcom/bumptech/glide/integration/compose/GlidePainter$State$Success;
public static synthetic fun copy$default (Lcom/bumptech/glide/integration/compose/GlidePainter$State$Success;Lcom/bumptech/glide/load/DataSource;ILjava/lang/Object;)Lcom/bumptech/glide/integration/compose/GlidePainter$State$Success;
public fun equals (Ljava/lang/Object;)Z
public final fun getDataSource ()Lcom/bumptech/glide/load/DataSource;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/bumptech/glide/integration/compose/GlidePainterKt {
public static final fun animate (Lcom/bumptech/glide/integration/compose/GlidePainter$State;)Lcom/bumptech/glide/integration/compose/AnimationState;
public static final fun rememberGlidePainter (Ljava/lang/Object;Lcom/bumptech/glide/integration/compose/AsyncLayoutSize;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)Lcom/bumptech/glide/integration/compose/GlidePainter;
public static final fun rememberGlidePainter (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)Lcom/bumptech/glide/integration/compose/GlidePainter;
public static final fun rememberSizeAndModifier (Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Lkotlin/Pair;
}

public abstract interface class com/bumptech/glide/integration/compose/GlidePreloadingData {
public abstract fun get (ILandroidx/compose/runtime/Composer;I)Lkotlin/Pair;
public abstract fun getSize ()I
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,17 +295,17 @@ class GlideImageTest {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
target: Target<Drawable>,
isFirstResource: Boolean,
): Boolean {
throw UnsupportedOperationException()
}

override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
resource: Drawable,
model: Any,
target: Target<Drawable>,
dataSource: DataSource,
isFirstResource: Boolean,
): Boolean {
onResourceReadyCounter.incrementAndGet()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
@file:OptIn(ExperimentalGlideComposeApi::class)

package com.bumptech.glide.integration.compose

import android.content.Context
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.test.core.app.ApplicationProvider
import com.bumptech.glide.Glide
import com.bumptech.glide.integration.compose.test.GlideComposeRule
import com.bumptech.glide.load.DataSource
import com.google.common.truth.ComparableSubject
import com.google.common.truth.Truth.assertThat
import org.junit.Assert.assertThrows
import org.junit.Rule
import org.junit.Test

class GlidePainterTest {
val context: Context = ApplicationProvider.getApplicationContext()

@get:Rule
val glideComposeRule = GlideComposeRule()

@Test
fun rememberGlidePainter_withoutSize_startsWithStateLoading() {
var painter: GlidePainter? = null
glideComposeRule.setContent {
painter = rememberGlidePainter(model = android.R.drawable.star_big_on)
}
assertThat(painter!!.state).isEqualTo(GlidePainter.State.Loading)
}

@Test
fun rememberGlidePainter_withOverrideSize_loadsImage() {
var painter: GlidePainter? = null
glideComposeRule.setContent {
painter = rememberGlidePainter(model = android.R.drawable.star_big_on) {
it.override(50)
}
}
glideComposeRule.waitForIdle()
assertThat(painter!!.state).isInstanceOf(GlidePainter.State.Success::class.java)
}

@Test
fun rememberGlidePainter_whenDrawnWithSize_loadsImage() {
var painter: GlidePainter? = null
glideComposeRule.setContent {
painter = rememberGlidePainter(model = android.R.drawable.star_big_on)
Image(
painter = painter!!,
contentDescription = "",
)
}
glideComposeRule.waitForIdle()
assertThat(painter!!.state).isInstanceOf(GlidePainter.State.Success::class.java)
}

@Test
fun rememberGlidePainter_withProvidedSize_andOverrideSize_throws() {
assertThrows(IllegalArgumentException::class.java) {
glideComposeRule.setContent {
val (size, _) = rememberSizeAndModifier(Modifier.size(10.dp))
rememberGlidePainter(model = android.R.drawable.star_big_on, size) {
it.override(50)
}
}
}
}

@Test
fun rememberGlidePainter_withLayoutSize_startsWithStateLoading() {
var painter: GlidePainter? = null
glideComposeRule.setContent {
val (size, _) = rememberSizeAndModifier(Modifier.size(10.dp))
painter = rememberGlidePainter(model = android.R.drawable.star_big_on, size)
}
assertThat(painter!!.state).isEqualTo(GlidePainter.State.Loading)
}

@Test
fun rememberGlidePainter_withLayoutSize_appliedToBox_loadsImage() {
var painter: GlidePainter? = null
glideComposeRule.setContent {
val (size, modifier) = rememberSizeAndModifier(Modifier.size(10.dp))
painter = rememberGlidePainter(model = android.R.drawable.star_big_on, size)
Box(modifier)
}
glideComposeRule.waitForIdle()
assertThat(painter!!.state).isInstanceOf(GlidePainter.State.Success::class.java)
}

@Test
fun rememberGlidePainter_withOverrideSize_andInvalidImage_setsStateToFailed() {
var painter: GlidePainter? = null
glideComposeRule.setContent {
painter = rememberGlidePainter(model = 1234) {
it.override(50)
}
}
glideComposeRule.waitForIdle()
assertThat(painter!!.state).isEqualTo(GlidePainter.State.Failure)
}

@Test
fun rememberGlidePainter_withLayoutSize_andInvalidImage_setsStateToFailed() {
var painter: GlidePainter? = null
glideComposeRule.setContent {
val (size, modifier) = rememberSizeAndModifier(Modifier.size(10.dp))
painter = rememberGlidePainter(model = 1234, size)
Box(modifier)
}
glideComposeRule.waitForIdle()
assertThat(painter!!.state).isEqualTo(GlidePainter.State.Failure)
}

@Test
fun rememberGlidePainter_onLoadFromSource_setsDataSourceToSource() {
var painter: GlidePainter? = null
glideComposeRule.setContent {
painter = rememberGlidePainter(model = android.R.drawable.star_big_on) {
it.override(50)
}
}
glideComposeRule.waitForIdle()
assertThatDataSource(painter).isEqualTo(DataSource.LOCAL)
}

@Test
fun rememberGlidePainter_onLoadFromMemory_setsDataSourceToMemory() {
var painter: GlidePainter? = null
val resourceId = android.R.drawable.star_big_on
val overrideSize = 50
// TODO: Compose always uses the generic paths to load models, so it skips options that are
// set by default by Glide's various class specific .load() method overrides.
val future = Glide.with(context).load(resourceId as Any).override(overrideSize).submit()
glideComposeRule.waitForIdle()
future.get()
glideComposeRule.setContent {
painter = rememberGlidePainter(model = resourceId) {
it.override(overrideSize)
}
}

glideComposeRule.waitForIdle()
assertThatDataSource(painter).isEqualTo(DataSource.MEMORY_CACHE)
}

private fun assertThatDataSource(painter: GlidePainter?): ComparableSubject<DataSource> =
assertThat((painter!!.state as GlidePainter.State.Success).dataSource)
}

Loading

0 comments on commit 8420af5

Please sign in to comment.