diff --git a/build.gradle b/build.gradle
index b4f5b8e20e..26b81f9175 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ buildscript {
'targetSdk': 31,
'sourceCompatibility': JavaVersion.VERSION_1_8,
'targetCompatibility': JavaVersion.VERSION_1_8,
- 'kotlin': '1.5.21',
+ 'kotlin': '1.6.10',
'okhttp': '4.9.3',
'okio': '3.0.0',
]
@@ -28,6 +28,9 @@ buildscript {
truth: 'com.google.truth:truth:1.1.3',
robolectric: 'org.robolectric:robolectric:4.6.1',
mockito: 'org.mockito:mockito-core:3.0.0',
+ drawablePainter: 'com.google.accompanist:accompanist-drawablepainter:0.23.1',
+ composeUi: 'androidx.compose.ui:ui:1.1.1',
+ foundation: 'androidx.compose.foundation:foundation:1.1.1'
]
ext.isCi = "true" == System.getenv('CI')
diff --git a/picasso-compose/README.md b/picasso-compose/README.md
new file mode 100644
index 0000000000..9fa845eb43
--- /dev/null
+++ b/picasso-compose/README.md
@@ -0,0 +1,16 @@
+Picasso Compose Ui
+====================================
+
+A [Painter] which wraps a [RequestCreator]
+
+Usage
+-----
+
+Create a `Painter` using the rememberPainter extension on a Picasso instance.
+
+```kotlin
+val picasso = Picasso.Builder(context).build()
+val painter = picasso.rememberPainter(key = url) {
+ it.load(url).placeholder(placeholderDrawable).error(errorDrawable)
+}
+```
\ No newline at end of file
diff --git a/picasso-compose/api/picasso-compose.api b/picasso-compose/api/picasso-compose.api
new file mode 100644
index 0000000000..73c88ddd88
--- /dev/null
+++ b/picasso-compose/api/picasso-compose.api
@@ -0,0 +1,4 @@
+public final class com/squareup/picasso3/compose/PicassoPainterKt {
+ public static final fun rememberPainter (Lcom/squareup/picasso3/Picasso;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)Landroidx/compose/ui/graphics/painter/Painter;
+}
+
diff --git a/picasso-compose/build.gradle b/picasso-compose/build.gradle
new file mode 100644
index 0000000000..09b0dd0a6e
--- /dev/null
+++ b/picasso-compose/build.gradle
@@ -0,0 +1,40 @@
+apply plugin: 'com.android.library'
+apply plugin: 'org.jetbrains.kotlin.android'
+apply plugin: 'com.vanniktech.maven.publish'
+
+android {
+ compileSdkVersion versions.compileSdk
+
+ defaultConfig {
+ minSdkVersion versions.minSdk
+ }
+
+ buildFeatures {
+ compose true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion "1.1.1"
+ }
+
+ compileOptions {
+ sourceCompatibility versions.sourceCompatibility
+ targetCompatibility versions.targetCompatibility
+ }
+
+ lintOptions {
+ textOutput 'stdout'
+ textReport true
+ lintConfig rootProject.file('lint.xml')
+ }
+}
+
+dependencies {
+ api project(':picasso')
+
+ implementation deps.drawablePainter
+ implementation deps.composeUi
+ implementation deps.foundation
+
+ compileOnly deps.androidxAnnotations
+}
diff --git a/picasso-compose/gradle.properties b/picasso-compose/gradle.properties
new file mode 100644
index 0000000000..eef2b86bcc
--- /dev/null
+++ b/picasso-compose/gradle.properties
@@ -0,0 +1,4 @@
+POM_ARTIFACT_ID=picasso-compose
+POM_NAME=Picasso Compose
+POM_DESCRIPTION=Compose UI support for Picasso.
+POM_PACKAGING=aar
diff --git a/picasso-compose/src/main/AndroidManifest.xml b/picasso-compose/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..f62947b282
--- /dev/null
+++ b/picasso-compose/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
diff --git a/picasso-compose/src/main/java/com/squareup/picasso3/compose/PicassoPainter.kt b/picasso-compose/src/main/java/com/squareup/picasso3/compose/PicassoPainter.kt
new file mode 100644
index 0000000000..82502200ae
--- /dev/null
+++ b/picasso-compose/src/main/java/com/squareup/picasso3/compose/PicassoPainter.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2022 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.picasso3.compose
+
+import android.graphics.drawable.Drawable
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.RememberObserver
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.graphics.DefaultAlpha
+import androidx.compose.ui.graphics.drawscope.DrawScope
+import androidx.compose.ui.graphics.painter.Painter
+import com.google.accompanist.drawablepainter.DrawablePainter
+import com.squareup.picasso3.DrawableTarget
+import com.squareup.picasso3.Picasso
+import com.squareup.picasso3.Picasso.LoadedFrom
+import com.squareup.picasso3.RequestCreator
+
+@Composable
+fun Picasso.rememberPainter(
+ key: Any? = null,
+ onError: ((Exception) -> Unit)? = null,
+ request: (Picasso) -> RequestCreator,
+): Painter {
+ return remember(key) { PicassoPainter(this, request, onError) }
+}
+
+internal class PicassoPainter(
+ private val picasso: Picasso,
+ private val request: (Picasso) -> RequestCreator,
+ private val onError: ((Exception) -> Unit)? = null
+) : Painter(), RememberObserver, DrawableTarget {
+
+ private var painter: Painter by mutableStateOf(EmptyPainter)
+ private var alpha: Float by mutableStateOf(DefaultAlpha)
+ private var colorFilter: ColorFilter? by mutableStateOf(null)
+
+ override val intrinsicSize: Size
+ get() = painter.intrinsicSize
+
+ override fun applyAlpha(alpha: Float): Boolean {
+ this.alpha = alpha
+ return true
+ }
+
+ override fun applyColorFilter(colorFilter: ColorFilter?): Boolean {
+ this.colorFilter = colorFilter
+ return true
+ }
+
+ override fun DrawScope.onDraw() {
+ with(painter) {
+ draw(size, alpha, colorFilter)
+ }
+ }
+
+ override fun onRemembered() {
+ request.invoke(picasso).into(this)
+ }
+
+ override fun onAbandoned() {
+ (painter as? RememberObserver)?.onAbandoned()
+ painter = EmptyPainter
+ picasso.cancelRequest(this)
+ }
+
+ override fun onForgotten() {
+ (painter as? RememberObserver)?.onForgotten()
+ painter = EmptyPainter
+ picasso.cancelRequest(this)
+ }
+
+ override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
+ placeHolderDrawable?.let(::setPainter)
+ }
+
+ override fun onDrawableLoaded(drawable: Drawable, from: LoadedFrom) {
+ setPainter(drawable)
+ }
+
+ override fun onDrawableFailed(e: Exception, errorDrawable: Drawable?) {
+ onError?.invoke(e)
+ errorDrawable?.let(::setPainter)
+ }
+
+ private fun setPainter(drawable: Drawable) {
+ (painter as? RememberObserver)?.onForgotten()
+ painter = DrawablePainter(drawable).apply(DrawablePainter::onRemembered)
+ }
+}
+
+private object EmptyPainter : Painter() {
+ override val intrinsicSize = Size.Zero
+ override fun DrawScope.onDraw() = Unit
+}
diff --git a/picasso-sample/build.gradle b/picasso-sample/build.gradle
index a0841be563..422ff7fe4f 100644
--- a/picasso-sample/build.gradle
+++ b/picasso-sample/build.gradle
@@ -10,6 +10,14 @@ android {
applicationId 'com.example.picasso'
}
+ buildFeatures {
+ compose true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion "1.1.1"
+ }
+
compileOptions {
sourceCompatibility versions.sourceCompatibility
targetCompatibility versions.targetCompatibility
@@ -32,6 +40,11 @@ dependencies {
implementation deps.androidxFragment
implementation deps.androidxStartup
+ implementation deps.drawablePainter
+ implementation deps.composeUi
+ implementation deps.foundation
+
implementation project(':picasso')
implementation project(':picasso-stats')
+ implementation project(':picasso-compose')
}
diff --git a/picasso-sample/src/main/AndroidManifest.xml b/picasso-sample/src/main/AndroidManifest.xml
index 300e3350b2..63f3944b53 100644
--- a/picasso-sample/src/main/AndroidManifest.xml
+++ b/picasso-sample/src/main/AndroidManifest.xml
@@ -34,6 +34,7 @@
+
diff --git a/picasso-sample/src/main/java/com/example/picasso/PicassoSampleAdapter.kt b/picasso-sample/src/main/java/com/example/picasso/PicassoSampleAdapter.kt
index c65c20bb70..cd4fca9c8d 100644
--- a/picasso-sample/src/main/java/com/example/picasso/PicassoSampleAdapter.kt
+++ b/picasso-sample/src/main/java/com/example/picasso/PicassoSampleAdapter.kt
@@ -38,6 +38,7 @@ internal class PicassoSampleAdapter(context: Context?) : BaseAdapter() {
private val activityClass: Class?
) {
GRID_VIEW("Image Grid View", SampleGridViewActivity::class.java),
+ COMPOSE_UI("Compose UI", SampleComposeActivity::class.java),
GALLERY("Load from Gallery", SampleGalleryActivity::class.java),
CONTACTS("Contact Photos", SampleContactsActivity::class.java),
LIST_DETAIL("List / Detail View", SampleListDetailActivity::class.java),
diff --git a/picasso-sample/src/main/java/com/example/picasso/SampleComposeActivity.kt b/picasso-sample/src/main/java/com/example/picasso/SampleComposeActivity.kt
new file mode 100644
index 0000000000..a8b18ef5f6
--- /dev/null
+++ b/picasso-sample/src/main/java/com/example/picasso/SampleComposeActivity.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.picasso
+
+import android.os.Bundle
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.lazy.GridCells.Adaptive
+import androidx.compose.foundation.lazy.LazyVerticalGrid
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.ContentScale.Companion.Crop
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.unit.dp
+import com.squareup.picasso3.Picasso
+import com.squareup.picasso3.compose.rememberPainter
+
+class SampleComposeActivity : PicassoSampleActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val composeView = ComposeView(this)
+
+ val urls = Data.URLS.toMutableList().shuffled() +
+ Data.URLS.toMutableList().shuffled() +
+ Data.URLS.toMutableList().shuffled()
+
+ composeView.setContent {
+ ImageGrid(urls = urls)
+ }
+
+ setContentView(composeView)
+ }
+}
+
+@OptIn(ExperimentalFoundationApi::class)
+@Composable
+fun ImageGrid(
+ modifier: Modifier = Modifier,
+ urls: List,
+ picasso: Picasso = PicassoInitializer.get()
+) {
+ LazyVerticalGrid(
+ cells = Adaptive(150.dp),
+ modifier = modifier,
+ ) {
+ items(urls.size) {
+ val url = urls[it]
+ Image(
+ painter = picasso.rememberPainter(key = url) {
+ it.load(url).placeholder(R.drawable.placeholder).error(R.drawable.error)
+ },
+ contentDescription = null,
+ contentScale = Crop,
+ modifier = Modifier
+ .fillMaxWidth()
+ .aspectRatio(1f)
+ )
+ }
+ }
+}
diff --git a/picasso/api/picasso.api b/picasso/api/picasso.api
index 3af2ac5bf9..a38eee1ba6 100644
--- a/picasso/api/picasso.api
+++ b/picasso/api/picasso.api
@@ -15,6 +15,12 @@ public class com/squareup/picasso3/Callback$EmptyCallback : com/squareup/picasso
public fun onSuccess ()V
}
+public abstract interface class com/squareup/picasso3/DrawableTarget {
+ public abstract fun onDrawableFailed (Ljava/lang/Exception;Landroid/graphics/drawable/Drawable;)V
+ public abstract fun onDrawableLoaded (Landroid/graphics/drawable/Drawable;Lcom/squareup/picasso3/Picasso$LoadedFrom;)V
+ public abstract fun onPrepareLoad (Landroid/graphics/drawable/Drawable;)V
+}
+
public abstract interface class com/squareup/picasso3/EventListener : java/io/Closeable {
public abstract fun bitmapDecoded (Landroid/graphics/Bitmap;)V
public abstract fun bitmapTransformed (Landroid/graphics/Bitmap;)V
@@ -72,6 +78,7 @@ public final class com/squareup/picasso3/Picasso : androidx/lifecycle/LifecycleO
public final fun cancelRequest (Landroid/widget/ImageView;)V
public final fun cancelRequest (Landroid/widget/RemoteViews;I)V
public final fun cancelRequest (Lcom/squareup/picasso3/BitmapTarget;)V
+ public final fun cancelRequest (Lcom/squareup/picasso3/DrawableTarget;)V
public final fun cancelTag (Ljava/lang/Object;)V
public final fun evictAll ()V
public final fun getIndicatorsEnabled ()Z
@@ -272,6 +279,7 @@ public final class com/squareup/picasso3/RequestCreator {
public final fun into (Landroid/widget/RemoteViews;I[I)V
public final fun into (Landroid/widget/RemoteViews;I[ILcom/squareup/picasso3/Callback;)V
public final fun into (Lcom/squareup/picasso3/BitmapTarget;)V
+ public final fun into (Lcom/squareup/picasso3/DrawableTarget;)V
public static synthetic fun into$default (Lcom/squareup/picasso3/RequestCreator;Landroid/widget/ImageView;Lcom/squareup/picasso3/Callback;ILjava/lang/Object;)V
public static synthetic fun into$default (Lcom/squareup/picasso3/RequestCreator;Landroid/widget/RemoteViews;IILandroid/app/Notification;Ljava/lang/String;Lcom/squareup/picasso3/Callback;ILjava/lang/Object;)V
public static synthetic fun into$default (Lcom/squareup/picasso3/RequestCreator;Landroid/widget/RemoteViews;IILcom/squareup/picasso3/Callback;ILjava/lang/Object;)V
diff --git a/picasso/src/main/java/com/squareup/picasso3/DrawableTarget.kt b/picasso/src/main/java/com/squareup/picasso3/DrawableTarget.kt
new file mode 100644
index 0000000000..78c774f409
--- /dev/null
+++ b/picasso/src/main/java/com/squareup/picasso3/DrawableTarget.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.picasso3
+
+import android.graphics.drawable.Drawable
+import com.squareup.picasso3.Picasso.LoadedFrom
+
+/**
+ * Represents an arbitrary listener for image loading.
+ *
+ * Objects implementing this class **must** have a working implementation of
+ * [Object.equals] and [Object.hashCode] for proper storage internally.
+ * Instances of this interface will also be compared to determine if view recycling is occurring.
+ * It is recommended that you add this interface directly on to a custom view type when using in an
+ * adapter to ensure correct recycling behavior.
+ */
+interface DrawableTarget {
+ /**
+ * Callback when an image has been successfully loaded.
+ *
+ */
+ fun onDrawableLoaded(
+ drawable: Drawable,
+ from: LoadedFrom
+ )
+
+ /**
+ * Callback indicating the image could not be successfully loaded.
+ *
+ * **Note:** The passed [Drawable] may be `null` if none has been
+ * specified via [RequestCreator.error].
+ */
+ fun onDrawableFailed(
+ e: Exception,
+ errorDrawable: Drawable?
+ )
+
+ /**
+ * Callback invoked right before your request is submitted.
+ *
+ *
+ * **Note:** The passed [Drawable] may be `null` if none has been
+ * specified via [RequestCreator.placeholder].
+ */
+ fun onPrepareLoad(placeHolderDrawable: Drawable?)
+}
diff --git a/picasso/src/main/java/com/squareup/picasso3/DrawableTargetAction.kt b/picasso/src/main/java/com/squareup/picasso3/DrawableTargetAction.kt
new file mode 100644
index 0000000000..b9dea2cca6
--- /dev/null
+++ b/picasso/src/main/java/com/squareup/picasso3/DrawableTargetAction.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.picasso3
+
+import android.graphics.drawable.Drawable
+import androidx.annotation.DrawableRes
+import androidx.core.content.ContextCompat
+import com.squareup.picasso3.RequestHandler.Result
+import com.squareup.picasso3.RequestHandler.Result.Bitmap
+
+internal class DrawableTargetAction(
+ picasso: Picasso,
+ private val target: DrawableTarget,
+ data: Request,
+ private val noFade: Boolean,
+ private val placeholderDrawable: Drawable?,
+ private val errorDrawable: Drawable?,
+ @DrawableRes val errorResId: Int
+) : Action(picasso, data) {
+ override fun complete(result: Result) {
+ if (result is Bitmap) {
+ val bitmap = result.bitmap
+ target.onDrawableLoaded(
+ PicassoDrawable(
+ context = picasso.context,
+ bitmap = bitmap,
+ placeholder = placeholderDrawable,
+ loadedFrom = result.loadedFrom,
+ noFade = noFade,
+ debugging = picasso.indicatorsEnabled
+ ),
+ result.loadedFrom
+ )
+ check(!bitmap.isRecycled) { "Target callback must not recycle bitmap!" }
+ }
+ }
+
+ override fun error(e: Exception) {
+ val drawable = if (errorResId != 0) {
+ ContextCompat.getDrawable(picasso.context, errorResId)
+ } else {
+ errorDrawable
+ }
+
+ target.onDrawableFailed(e, drawable)
+ }
+
+ override fun getTarget(): Any {
+ return target
+ }
+}
diff --git a/picasso/src/main/java/com/squareup/picasso3/Picasso.kt b/picasso/src/main/java/com/squareup/picasso3/Picasso.kt
index b9a5abca68..a86a58e6a4 100644
--- a/picasso/src/main/java/com/squareup/picasso3/Picasso.kt
+++ b/picasso/src/main/java/com/squareup/picasso3/Picasso.kt
@@ -149,6 +149,12 @@ class Picasso internal constructor(
cancelExistingRequest(target)
}
+ /** Cancel any existing requests for the specified [DrawableTarget] instance. */
+ fun cancelRequest(target: DrawableTarget) {
+ // checkMain() is called from cancelExistingRequest()
+ cancelExistingRequest(target)
+ }
+
/**
* Cancel any existing requests for the specified [RemoteViews] target with the given [viewId].
*/
diff --git a/picasso/src/main/java/com/squareup/picasso3/RequestCreator.kt b/picasso/src/main/java/com/squareup/picasso3/RequestCreator.kt
index 12adef8a23..1ba703e2a7 100644
--- a/picasso/src/main/java/com/squareup/picasso3/RequestCreator.kt
+++ b/picasso/src/main/java/com/squareup/picasso3/RequestCreator.kt
@@ -448,6 +448,48 @@ class RequestCreator internal constructor(
picasso.enqueueAndSubmit(action)
}
+ /**
+ * Asynchronously fulfills the request into the specified [DrawableTarget]. In most cases, you
+ * should use this when you are dealing with a custom [View][android.view.View] or view
+ * holder which should implement the [DrawableTarget] interface.
+ */
+ fun into(target: DrawableTarget) {
+ val started = System.nanoTime()
+ checkMain()
+ check(!deferred) { "Fit cannot be used with a Target." }
+
+ val placeHolderDrawable = if (setPlaceholder) getPlaceholderDrawable() else null
+ if (!data.hasImage()) {
+ picasso.cancelRequest(target)
+ target.onPrepareLoad(placeHolderDrawable)
+ return
+ }
+
+ val request = createRequest(started)
+ if (shouldReadFromMemoryCache(request.memoryPolicy)) {
+ val bitmap = picasso.quickMemoryCacheCheck(request.key)
+ if (bitmap != null) {
+ picasso.cancelRequest(target)
+ target.onDrawableLoaded(
+ PicassoDrawable(
+ context = picasso.context,
+ bitmap = bitmap,
+ placeholder = null,
+ loadedFrom = LoadedFrom.MEMORY,
+ noFade = noFade,
+ debugging = picasso.indicatorsEnabled
+ ),
+ LoadedFrom.MEMORY
+ )
+ return
+ }
+ }
+
+ target.onPrepareLoad(placeHolderDrawable)
+ val action = DrawableTargetAction(picasso, target, request, noFade, placeHolderDrawable, errorDrawable, errorResId)
+ picasso.enqueueAndSubmit(action)
+ }
+
/**
* Asynchronously fulfills the request into the specified [RemoteViews] object with the
* given [viewId]. This is used for loading bitmaps into a [Notification].
diff --git a/picasso/src/test/java/com/squareup/picasso3/BitmapTargetActionTest.kt b/picasso/src/test/java/com/squareup/picasso3/BitmapTargetActionTest.kt
index c463ca3127..f1c59968d0 100644
--- a/picasso/src/test/java/com/squareup/picasso3/BitmapTargetActionTest.kt
+++ b/picasso/src/test/java/com/squareup/picasso3/BitmapTargetActionTest.kt
@@ -27,8 +27,8 @@ import com.squareup.picasso3.TestUtils.RESOURCE_ID_1
import com.squareup.picasso3.TestUtils.SIMPLE_REQUEST
import com.squareup.picasso3.TestUtils.UNUSED_CALL_FACTORY
import com.squareup.picasso3.TestUtils.makeBitmap
+import com.squareup.picasso3.TestUtils.mockBitmapTarget
import com.squareup.picasso3.TestUtils.mockPicasso
-import com.squareup.picasso3.TestUtils.mockTarget
import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
@@ -43,7 +43,7 @@ class BitmapTargetActionTest {
@Test fun invokesSuccessIfTargetIsNotNull() {
val bitmap = makeBitmap()
- val target = mockTarget()
+ val target = mockBitmapTarget()
val request = BitmapTargetAction(
picasso = mockPicasso(RuntimeEnvironment.application),
target = target,
@@ -57,7 +57,7 @@ class BitmapTargetActionTest {
@Test fun invokesOnBitmapFailedIfTargetIsNotNullWithErrorDrawable() {
val errorDrawable = mock(Drawable::class.java)
- val target = mockTarget()
+ val target = mockBitmapTarget()
val request = BitmapTargetAction(
picasso = mockPicasso(RuntimeEnvironment.application),
target = target,
@@ -74,7 +74,7 @@ class BitmapTargetActionTest {
@Test fun invokesOnBitmapFailedIfTargetIsNotNullWithErrorResourceId() {
val errorDrawable = mock(Drawable::class.java)
- val target = mockTarget()
+ val target = mockBitmapTarget()
val context = mock(Context::class.java)
val dispatcher = mock(Dispatcher::class.java)
val cache = PlatformLruCache(0)
diff --git a/picasso/src/test/java/com/squareup/picasso3/DispatcherTest.kt b/picasso/src/test/java/com/squareup/picasso3/DispatcherTest.kt
index df5b7e4fa1..6c9bcdf907 100644
--- a/picasso/src/test/java/com/squareup/picasso3/DispatcherTest.kt
+++ b/picasso/src/test/java/com/squareup/picasso3/DispatcherTest.kt
@@ -40,11 +40,11 @@ import com.squareup.picasso3.TestUtils.URI_KEY_1
import com.squareup.picasso3.TestUtils.URI_KEY_2
import com.squareup.picasso3.TestUtils.makeBitmap
import com.squareup.picasso3.TestUtils.mockAction
+import com.squareup.picasso3.TestUtils.mockBitmapTarget
import com.squareup.picasso3.TestUtils.mockCallback
import com.squareup.picasso3.TestUtils.mockHunter
import com.squareup.picasso3.TestUtils.mockNetworkInfo
import com.squareup.picasso3.TestUtils.mockPicasso
-import com.squareup.picasso3.TestUtils.mockTarget
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -156,7 +156,7 @@ class DispatcherTest {
}
@Test fun performCancelDetachesRequestAndCleansUp() {
- val target = mockTarget()
+ val target = mockBitmapTarget()
val action = mockAction(picasso, URI_KEY_1, URI_1, target)
val hunter = mockHunter(picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action)
hunter.future = FutureTask(mock(Runnable::class.java), mock(Any::class.java))
@@ -181,7 +181,7 @@ class DispatcherTest {
}
@Test fun performCancelUnqueuesAndDetachesPausedRequest() {
- val action = mockAction(picasso, URI_KEY_1, URI_1, mockTarget(), tag = "tag")
+ val action = mockAction(picasso, URI_KEY_1, URI_1, mockBitmapTarget(), tag = "tag")
val hunter = mockHunter(picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action)
dispatcher.hunterMap[URI_KEY_1 + Request.KEY_SEPARATOR] = hunter
dispatcher.pausedTags.add("tag")
@@ -248,7 +248,7 @@ class DispatcherTest {
}
@Test fun performErrorCleansUpAndPostsToMain() {
- val action = mockAction(picasso, URI_KEY_1, URI_1, mockTarget(), tag = "tag")
+ val action = mockAction(picasso, URI_KEY_1, URI_1, mockBitmapTarget(), tag = "tag")
val hunter = mockHunter(picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action)
dispatcher.hunterMap[hunter.key] = hunter
dispatcher.performError(hunter)
@@ -257,7 +257,7 @@ class DispatcherTest {
}
@Test fun performErrorCleansUpAndDoesNotPostToMainIfCancelled() {
- val action = mockAction(picasso, URI_KEY_1, URI_1, mockTarget(), tag = "tag")
+ val action = mockAction(picasso, URI_KEY_1, URI_1, mockBitmapTarget(), tag = "tag")
val hunter = mockHunter(picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action)
hunter.future = FutureTask(mock(Runnable::class.java), mock(Any::class.java))
hunter.future!!.cancel(false)
@@ -268,7 +268,7 @@ class DispatcherTest {
}
@Test fun performRetrySkipsIfHunterIsCancelled() {
- val action = mockAction(picasso, URI_KEY_1, URI_1, mockTarget(), tag = "tag")
+ val action = mockAction(picasso, URI_KEY_1, URI_1, mockBitmapTarget(), tag = "tag")
val hunter = mockHunter(picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action)
hunter.future = FutureTask(mock(Runnable::class.java), mock(Any::class.java))
hunter.future!!.cancel(false)
@@ -319,7 +319,7 @@ class DispatcherTest {
@Test fun performRetryMarksForReplayIfSupportedScansNetworkChangesAndShouldNotRetry() {
val networkInfo = mockNetworkInfo(true)
- val action = mockAction(picasso, URI_KEY_1, URI_1, mockTarget())
+ val action = mockAction(picasso, URI_KEY_1, URI_1, mockBitmapTarget())
val hunter = mockHunter(
picasso,
RequestHandler.Result.Bitmap(bitmap1, MEMORY),
@@ -348,7 +348,7 @@ class DispatcherTest {
}
@Test fun performRetryMarksForReplayIfSupportsReplayAndShouldNotRetry() {
- val action = mockAction(picasso, URI_KEY_1, URI_1, mockTarget())
+ val action = mockAction(picasso, URI_KEY_1, URI_1, mockBitmapTarget())
val hunter = mockHunter(
picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action,
e = null, shouldRetry = false, supportsReplay = true
@@ -360,7 +360,7 @@ class DispatcherTest {
}
@Test fun performRetryRetriesIfShouldRetry() {
- val action = mockAction(picasso, URI_KEY_1, URI_1, mockTarget())
+ val action = mockAction(picasso, URI_KEY_1, URI_1, mockBitmapTarget())
val hunter = mockHunter(
picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action,
e = null, shouldRetry = true
@@ -372,7 +372,7 @@ class DispatcherTest {
}
@Test fun performRetrySkipIfServiceShutdown() {
- val action = mockAction(picasso, URI_KEY_1, URI_1, mockTarget())
+ val action = mockAction(picasso, URI_KEY_1, URI_1, mockBitmapTarget())
val hunter = mockHunter(picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action)
service.shutdown()
dispatcher.performRetry(hunter)
@@ -418,7 +418,7 @@ class DispatcherTest {
}
@Test fun performPauseTagIsIdempotent() {
- val action = mockAction(picasso, URI_KEY_1, URI_1, mockTarget(), tag = "tag")
+ val action = mockAction(picasso, URI_KEY_1, URI_1, mockBitmapTarget(), tag = "tag")
val hunter = mockHunter(picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action)
dispatcher.hunterMap[URI_KEY_1] = hunter
assertThat(dispatcher.pausedActions).isEmpty()
@@ -468,10 +468,10 @@ class DispatcherTest {
@Test fun performPauseOnlyDetachesPausedRequest() {
val action1 = mockAction(
- picasso = picasso, key = URI_KEY_1, uri = URI_1, target = mockTarget(), tag = "tag1"
+ picasso = picasso, key = URI_KEY_1, uri = URI_1, target = mockBitmapTarget(), tag = "tag1"
)
val action2 = mockAction(
- picasso = picasso, key = URI_KEY_1, uri = URI_1, target = mockTarget(), tag = "tag2"
+ picasso = picasso, key = URI_KEY_1, uri = URI_1, target = mockBitmapTarget(), tag = "tag2"
)
val hunter = mockHunter(picasso, RequestHandler.Result.Bitmap(bitmap1, MEMORY), action1)
hunter.attach(action2)
diff --git a/picasso/src/test/java/com/squareup/picasso3/DrawableTargetActionTest.kt b/picasso/src/test/java/com/squareup/picasso3/DrawableTargetActionTest.kt
new file mode 100644
index 0000000000..6191054fd8
--- /dev/null
+++ b/picasso/src/test/java/com/squareup/picasso3/DrawableTargetActionTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2022 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.picasso3
+
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.Bitmap.Config.ARGB_8888
+import android.graphics.drawable.Drawable
+import com.google.common.truth.Truth.assertThat
+import com.squareup.picasso3.Picasso.LoadedFrom.MEMORY
+import com.squareup.picasso3.Picasso.LoadedFrom.NETWORK
+import com.squareup.picasso3.TestUtils.argumentCaptor
+import com.squareup.picasso3.TestUtils.eq
+import com.squareup.picasso3.TestUtils.makeBitmap
+import com.squareup.picasso3.TestUtils.mockDrawableTarget
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+import org.mockito.Mockito.mock
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.RuntimeEnvironment
+
+@RunWith(RobolectricTestRunner::class)
+class DrawableTargetActionTest {
+
+ @Test fun invokesSuccessIfTargetIsNotNull() {
+ val bitmap = makeBitmap()
+ val target = mockDrawableTarget()
+ val drawableCaptor = argumentCaptor()
+ val placeholder = mock(Drawable::class.java)
+ val action = DrawableTargetAction(
+ picasso = TestUtils.mockPicasso(RuntimeEnvironment.application),
+ target = target,
+ data = TestUtils.SIMPLE_REQUEST,
+ noFade = false,
+ placeholderDrawable = placeholder,
+ errorDrawable = null,
+ errorResId = 0
+ )
+
+ action.complete(RequestHandler.Result.Bitmap(bitmap, NETWORK))
+
+ Mockito.verify(target).onDrawableLoaded(drawableCaptor.capture(), eq(NETWORK))
+ with(drawableCaptor.value) {
+ assertThat(this.bitmap).isEqualTo(bitmap)
+ assertThat(this.placeholder).isEqualTo(placeholder)
+ assertThat(this.animating).isTrue()
+ }
+ }
+
+ @Test fun invokesOnBitmapFailedIfTargetIsNotNullWithErrorDrawable() {
+ val errorDrawable = mock(Drawable::class.java)
+ val target = mockDrawableTarget()
+ val action = DrawableTargetAction(
+ picasso = TestUtils.mockPicasso(RuntimeEnvironment.application),
+ target = target,
+ data = TestUtils.SIMPLE_REQUEST,
+ noFade = true,
+ placeholderDrawable = null,
+ errorDrawable = errorDrawable,
+ errorResId = 0
+ )
+ val e = RuntimeException()
+
+ action.error(e)
+
+ Mockito.verify(target).onDrawableFailed(e, errorDrawable)
+ }
+
+ @Test fun invokesOnBitmapFailedIfTargetIsNotNullWithErrorResourceId() {
+ val errorDrawable = mock(Drawable::class.java)
+ val context = mock(Context::class.java)
+ val dispatcher = mock(Dispatcher::class.java)
+ val cache = PlatformLruCache(0)
+ val picasso = Picasso(
+ context, dispatcher,
+ TestUtils.UNUSED_CALL_FACTORY, null, cache, null,
+ TestUtils.NO_TRANSFORMERS,
+ TestUtils.NO_HANDLERS,
+ TestUtils.NO_EVENT_LISTENERS, ARGB_8888, false, false
+ )
+ val res = mock(Resources::class.java)
+
+ val target = mockDrawableTarget()
+ val action = DrawableTargetAction(
+ picasso = picasso,
+ target = target,
+ data = TestUtils.SIMPLE_REQUEST,
+ noFade = true,
+ placeholderDrawable = null,
+ errorDrawable = null,
+ errorResId = TestUtils.RESOURCE_ID_1
+ )
+
+ Mockito.`when`(context.getDrawable(TestUtils.RESOURCE_ID_1)).thenReturn(errorDrawable)
+ val e = RuntimeException()
+
+ action.error(e)
+
+ Mockito.verify(target).onDrawableFailed(e, errorDrawable)
+ }
+
+ @Test fun recyclingInSuccessThrowsException() {
+ val picasso = TestUtils.mockPicasso(RuntimeEnvironment.application)
+ val bitmap = makeBitmap()
+ val action = DrawableTargetAction(
+ picasso = picasso,
+ target = object : DrawableTarget {
+ override fun onDrawableLoaded(drawable: Drawable, from: Picasso.LoadedFrom) = (drawable as PicassoDrawable).bitmap.recycle()
+ override fun onDrawableFailed(e: Exception, errorDrawable: Drawable?) = throw AssertionError()
+ override fun onPrepareLoad(placeHolderDrawable: Drawable?) = throw AssertionError()
+ },
+ data = TestUtils.SIMPLE_REQUEST,
+ noFade = true,
+ placeholderDrawable = null,
+ errorDrawable = null,
+ errorResId = 0
+ )
+
+ try {
+ action.complete(RequestHandler.Result.Bitmap(bitmap, MEMORY))
+ Assert.fail()
+ } catch (ignored: IllegalStateException) {
+ }
+ }
+}
diff --git a/picasso/src/test/java/com/squareup/picasso3/PicassoTest.kt b/picasso/src/test/java/com/squareup/picasso3/PicassoTest.kt
index 7cecea2674..7c13db3e99 100644
--- a/picasso/src/test/java/com/squareup/picasso3/PicassoTest.kt
+++ b/picasso/src/test/java/com/squareup/picasso3/PicassoTest.kt
@@ -37,12 +37,13 @@ import com.squareup.picasso3.TestUtils.URI_KEY_1
import com.squareup.picasso3.TestUtils.defaultPicasso
import com.squareup.picasso3.TestUtils.makeBitmap
import com.squareup.picasso3.TestUtils.mockAction
+import com.squareup.picasso3.TestUtils.mockBitmapTarget
import com.squareup.picasso3.TestUtils.mockDeferredRequestCreator
+import com.squareup.picasso3.TestUtils.mockDrawableTarget
import com.squareup.picasso3.TestUtils.mockHunter
import com.squareup.picasso3.TestUtils.mockImageViewTarget
import com.squareup.picasso3.TestUtils.mockPicasso
import com.squareup.picasso3.TestUtils.mockRequestCreator
-import com.squareup.picasso3.TestUtils.mockTarget
import org.junit.Assert.fail
import org.junit.Before
import org.junit.Rule
@@ -291,8 +292,20 @@ class PicassoTest {
assertThat(picasso.targetToDeferredRequestCreator).containsKey(target)
}
- @Test fun cancelExistingRequestWithTarget() {
- val target = mockTarget()
+ @Test fun cancelExistingRequestWithBitmapTarget() {
+ val target = mockBitmapTarget()
+ val action = mockAction(picasso, URI_KEY_1, URI_1, target)
+ picasso.enqueueAndSubmit(action)
+ assertThat(picasso.targetToAction).hasSize(1)
+ assertThat(action.cancelled).isFalse()
+ picasso.cancelRequest(target)
+ assertThat(picasso.targetToAction).isEmpty()
+ assertThat(action.cancelled).isTrue()
+ verify(dispatcher).dispatchCancel(action)
+ }
+
+ @Test fun cancelExistingRequestWithDrawableTarget() {
+ val target = mockDrawableTarget()
val action = mockAction(picasso, URI_KEY_1, URI_1, target)
picasso.enqueueAndSubmit(action)
assertThat(picasso.targetToAction).hasSize(1)
diff --git a/picasso/src/test/java/com/squareup/picasso3/RequestCreatorTest.kt b/picasso/src/test/java/com/squareup/picasso3/RequestCreatorTest.kt
index f925e4c608..2099d8ac22 100644
--- a/picasso/src/test/java/com/squareup/picasso3/RequestCreatorTest.kt
+++ b/picasso/src/test/java/com/squareup/picasso3/RequestCreatorTest.kt
@@ -41,14 +41,15 @@ import com.squareup.picasso3.TestUtils.any
import com.squareup.picasso3.TestUtils.argumentCaptor
import com.squareup.picasso3.TestUtils.eq
import com.squareup.picasso3.TestUtils.makeBitmap
+import com.squareup.picasso3.TestUtils.mockBitmapTarget
import com.squareup.picasso3.TestUtils.mockCallback
+import com.squareup.picasso3.TestUtils.mockDrawableTarget
import com.squareup.picasso3.TestUtils.mockFitImageViewTarget
import com.squareup.picasso3.TestUtils.mockImageViewTarget
import com.squareup.picasso3.TestUtils.mockNotification
import com.squareup.picasso3.TestUtils.mockPicasso
import com.squareup.picasso3.TestUtils.mockRemoteViews
import com.squareup.picasso3.TestUtils.mockRequestCreator
-import com.squareup.picasso3.TestUtils.mockTarget
import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
@@ -151,20 +152,20 @@ class RequestCreatorTest {
@Test fun intoTargetWithFitThrows() {
try {
- RequestCreator(picasso, URI_1, 0).fit().into(mockTarget())
+ RequestCreator(picasso, URI_1, 0).fit().into(mockBitmapTarget())
fail("Calling into() target with fit() should throw exception")
} catch (ignored: IllegalStateException) {
}
}
@Test fun intoTargetNoPlaceholderCallsWithNull() {
- val target = mockTarget()
+ val target = mockBitmapTarget()
RequestCreator(picasso, URI_1, 0).noPlaceholder().into(target)
verify(target).onPrepareLoad(null)
}
@Test fun intoTargetWithNullUriAndResourceIdSkipsAndCancels() {
- val target = mockTarget()
+ val target = mockBitmapTarget()
val placeHolderDrawable = mock(Drawable::class.java)
RequestCreator(picasso, null, 0).placeholder(placeHolderDrawable).into(target)
verify(picasso).defaultBitmapConfig
@@ -176,7 +177,7 @@ class RequestCreatorTest {
@Test fun intoTargetWithQuickMemoryCacheCheckDoesNotSubmit() {
`when`(picasso.quickMemoryCacheCheck(URI_KEY_1)).thenReturn(bitmap)
- val target = mockTarget()
+ val target = mockBitmapTarget()
RequestCreator(picasso, URI_1, 0).into(target)
verify(target).onBitmapLoaded(bitmap, MEMORY)
verify(picasso).cancelRequest(target)
@@ -184,13 +185,13 @@ class RequestCreatorTest {
}
@Test fun intoTargetWithSkipMemoryPolicy() {
- val target = mockTarget()
+ val target = mockBitmapTarget()
RequestCreator(picasso, URI_1, 0).memoryPolicy(NO_CACHE).into(target)
verify(picasso, never()).quickMemoryCacheCheck(URI_KEY_1)
}
@Test fun intoTargetAndNotInCacheSubmitsTargetRequest() {
- val target = mockTarget()
+ val target = mockBitmapTarget()
val placeHolderDrawable = mock(Drawable::class.java)
RequestCreator(picasso, URI_1, 0).placeholder(placeHolderDrawable).into(target)
verify(target).onPrepareLoad(placeHolderDrawable)
@@ -199,29 +200,78 @@ class RequestCreatorTest {
}
@Test fun targetActionWithDefaultPriority() {
- RequestCreator(picasso, URI_1, 0).into(mockTarget())
+ RequestCreator(picasso, URI_1, 0).into(mockBitmapTarget())
verify(picasso).enqueueAndSubmit(actionCaptor.capture())
assertThat(actionCaptor.value.request.priority).isEqualTo(NORMAL)
}
@Test fun targetActionWithCustomPriority() {
- RequestCreator(picasso, URI_1, 0).priority(HIGH).into(mockTarget())
+ RequestCreator(picasso, URI_1, 0).priority(HIGH).into(mockBitmapTarget())
verify(picasso).enqueueAndSubmit(actionCaptor.capture())
assertThat(actionCaptor.value.request.priority).isEqualTo(HIGH)
}
@Test fun targetActionWithDefaultTag() {
- RequestCreator(picasso, URI_1, 0).into(mockTarget())
+ RequestCreator(picasso, URI_1, 0).into(mockBitmapTarget())
verify(picasso).enqueueAndSubmit(actionCaptor.capture())
assertThat(actionCaptor.value.tag).isEqualTo(actionCaptor.value)
}
@Test fun targetActionWithCustomTag() {
- RequestCreator(picasso, URI_1, 0).tag("tag").into(mockTarget())
+ RequestCreator(picasso, URI_1, 0).tag("tag").into(mockBitmapTarget())
verify(picasso).enqueueAndSubmit(actionCaptor.capture())
assertThat(actionCaptor.value.tag).isEqualTo("tag")
}
+ @Test fun intoDrawableTargetWithFitThrows() {
+ try {
+ RequestCreator(picasso, URI_1, 0).fit().into(mockDrawableTarget())
+ fail("Calling into() drawable target with fit() should throw exception")
+ } catch (ignored: IllegalStateException) {
+ }
+ }
+
+ @Test fun intoDrawableTargetNoPlaceholderCallsWithNull() {
+ val target = mockDrawableTarget()
+ RequestCreator(picasso, URI_1, 0).noPlaceholder().into(target)
+ verify(target).onPrepareLoad(null)
+ }
+
+ @Test fun intoDrawableTargetWithNullUriAndResourceIdSkipsAndCancels() {
+ val target = mockDrawableTarget()
+ val placeHolderDrawable = mock(Drawable::class.java)
+ RequestCreator(picasso, null, 0).placeholder(placeHolderDrawable).into(target)
+ verify(picasso).defaultBitmapConfig
+ verify(picasso).shutdown
+ verify(picasso).cancelRequest(target)
+ verify(target).onPrepareLoad(placeHolderDrawable)
+ verifyNoMoreInteractions(picasso)
+ }
+
+ @Test fun intoDrawableTargetWithQuickMemoryCacheCheckDoesNotSubmit() {
+ `when`(picasso.quickMemoryCacheCheck(URI_KEY_1)).thenReturn(bitmap)
+ val target = mockDrawableTarget()
+ RequestCreator(picasso, URI_1, 0).into(target)
+ verify(target).onDrawableLoaded(any(PicassoDrawable::class.java), eq(MEMORY))
+ verify(picasso).cancelRequest(target)
+ verify(picasso, never()).enqueueAndSubmit(any(Action::class.java))
+ }
+
+ @Test fun intoDrawableTargetWithSkipMemoryPolicy() {
+ val target = mockDrawableTarget()
+ RequestCreator(picasso, URI_1, 0).memoryPolicy(NO_CACHE).into(target)
+ verify(picasso, never()).quickMemoryCacheCheck(URI_KEY_1)
+ }
+
+ @Test fun intoDrawableTargetAndNotInCacheSubmitsTargetRequest() {
+ val target = mockDrawableTarget()
+ val placeHolderDrawable = mock(Drawable::class.java)
+ RequestCreator(picasso, URI_1, 0).placeholder(placeHolderDrawable).into(target)
+ verify(target).onPrepareLoad(placeHolderDrawable)
+ verify(picasso).enqueueAndSubmit(actionCaptor.capture())
+ assertThat(actionCaptor.value).isInstanceOf(DrawableTargetAction::class.java)
+ }
+
@Test fun intoImageViewWithNullUriAndResourceIdSkipsAndCancels() {
val target = mockImageViewTarget()
RequestCreator(picasso, null, 0).into(target)
@@ -306,7 +356,7 @@ class RequestCreatorTest {
val latch = CountDownLatch(1)
Thread {
try {
- RequestCreator(picasso, null, 0).into(mockTarget())
+ RequestCreator(picasso, null, 0).into(mockBitmapTarget())
fail("Should have thrown IllegalStateException")
} catch (ignored: IllegalStateException) {
} finally {
@@ -463,12 +513,12 @@ class RequestCreatorTest {
@Test fun intoTargetNoResizeWithCenterInsideOrCenterCropThrows() {
try {
- RequestCreator(picasso, URI_1, 0).centerInside().into(mockTarget())
+ RequestCreator(picasso, URI_1, 0).centerInside().into(mockBitmapTarget())
fail("Center inside with unknown width should throw exception.")
} catch (ignored: IllegalStateException) {
}
try {
- RequestCreator(picasso, URI_1, 0).centerCrop().into(mockTarget())
+ RequestCreator(picasso, URI_1, 0).centerCrop().into(mockBitmapTarget())
fail("Center inside with unknown height should throw exception.")
} catch (ignored: IllegalStateException) {
}
diff --git a/picasso/src/test/java/com/squareup/picasso3/TestUtils.kt b/picasso/src/test/java/com/squareup/picasso3/TestUtils.kt
index 26cd684569..1cad7e3f62 100644
--- a/picasso/src/test/java/com/squareup/picasso3/TestUtils.kt
+++ b/picasso/src/test/java/com/squareup/picasso3/TestUtils.kt
@@ -145,7 +145,7 @@ internal object TestUtils {
picasso: Picasso,
key: String,
uri: Uri? = null,
- target: Any = mockTarget(),
+ target: Any = mockBitmapTarget(),
resourceId: Int = 0,
priority: Priority? = null,
tag: String? = null,
@@ -165,7 +165,7 @@ internal object TestUtils {
return mockAction(picasso, request, target)
}
- fun mockAction(picasso: Picasso, request: Request, target: Any = mockTarget()) =
+ fun mockAction(picasso: Picasso, request: Request, target: Any = mockBitmapTarget()) =
FakeAction(picasso, request, target)
fun mockImageViewTarget(): ImageView = mock(ImageView::class.java)
@@ -183,7 +183,9 @@ internal object TestUtils {
return mock
}
- fun mockTarget(): BitmapTarget = mock(BitmapTarget::class.java)
+ fun mockBitmapTarget(): BitmapTarget = mock(BitmapTarget::class.java)
+
+ fun mockDrawableTarget(): DrawableTarget = mock(DrawableTarget::class.java)
fun mockCallback(): Callback = mock(Callback::class.java)
diff --git a/settings.gradle b/settings.gradle
index 687bc5ddc3..1a1c0b607e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,6 +1,7 @@
rootProject.name = 'picasso-root'
include 'picasso'
+include 'picasso-compose'
include 'picasso-pollexor'
include 'picasso-sample'
include 'picasso-stats'