From e2200d7776978ecca7b231452774417d34b7ec0b Mon Sep 17 00:00:00 2001 From: skydoves Date: Mon, 30 Dec 2024 15:20:38 +0900 Subject: [PATCH] Use internal modifier's coroutine scope instead of using runblocking --- cloudy/build.gradle.kts | 1 + .../com/skydoves/cloudy/CloudyModifierNode.kt | 21 +++++++++++-------- .../internals/render/RenderScriptToolkit.kt | 7 ++++--- gradle/libs.versions.toml | 14 +++++++------ 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/cloudy/build.gradle.kts b/cloudy/build.gradle.kts index 69c366b..495d746 100644 --- a/cloudy/build.gradle.kts +++ b/cloudy/build.gradle.kts @@ -78,4 +78,5 @@ kotlin { dependencies { implementation(libs.androidx.compose.ui) implementation(libs.androidx.compose.runtime) + implementation(libs.kotlinx.coroutines.android) } diff --git a/cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyModifierNode.kt b/cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyModifierNode.kt index 1f42f2e..b2e3ba4 100644 --- a/cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyModifierNode.kt +++ b/cloudy/src/main/kotlin/com/skydoves/cloudy/CloudyModifierNode.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.graphics.asAndroidBitmap import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.drawscope.ContentDrawScope import androidx.compose.ui.graphics.layer.GraphicsLayer +import androidx.compose.ui.graphics.layer.drawLayer import androidx.compose.ui.graphics.rememberGraphicsLayer import androidx.compose.ui.layout.Measurable import androidx.compose.ui.layout.MeasureResult @@ -38,7 +39,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.offset import com.skydoves.cloudy.internals.render.iterativeBlur import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.launch /** * `Modifier.cloudy()` is a replacement of the [blur] modifier (compatible with under Android 12), @@ -121,24 +122,26 @@ private class CloudyModifierNode( this@draw.drawContent() } + drawLayer(graphicsLayer) + onStateChanged.invoke(CloudyState.Loading) - try { - val blurredBitmap: Bitmap = runBlocking(Dispatchers.IO) { + coroutineScope.launch(Dispatchers.Main.immediate) { + try { val targetBitmap: Bitmap = graphicsLayer.toImageBitmap().asAndroidBitmap() .copy(Bitmap.Config.ARGB_8888, true) - iterativeBlur( + val blurredBitmap = iterativeBlur( androidBitmap = targetBitmap, radius = radius )?.apply { drawImage(this.asImageBitmap()) - } - } ?: throw RuntimeException("Couldn't capture a bitmap from the composable tree") + } ?: throw RuntimeException("Couldn't capture a bitmap from the composable tree") - onStateChanged.invoke(CloudyState.Success(blurredBitmap)) - } catch (e: Exception) { - onStateChanged.invoke(CloudyState.Error(e)) + onStateChanged.invoke(CloudyState.Success(blurredBitmap)) + } catch (e: Exception) { + onStateChanged.invoke(CloudyState.Error(e)) + } } } } diff --git a/cloudy/src/main/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt b/cloudy/src/main/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt index 2ada39e..f89a57d 100644 --- a/cloudy/src/main/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt +++ b/cloudy/src/main/kotlin/com/skydoves/cloudy/internals/render/RenderScriptToolkit.kt @@ -18,6 +18,7 @@ package com.skydoves.cloudy.internals.render import android.graphics.Bitmap +import kotlinx.coroutines.coroutineScope // This string is used for error messages. private const val externalName = "RenderScript Toolkit" @@ -315,10 +316,10 @@ internal fun vectorSize(bitmap: Bitmap): Int { } } -internal fun iterativeBlur( +internal suspend fun iterativeBlur( androidBitmap: Bitmap, radius: Int -): Bitmap? { +): Bitmap? = coroutineScope { val iterate = (radius + 1) / 25 var bitmap: Bitmap? = RenderScriptToolkit.blur( inputBitmap = androidBitmap, @@ -332,5 +333,5 @@ internal fun iterativeBlur( ) } - return bitmap + bitmap } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a7704c5..1cf1f3c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,14 +1,15 @@ [versions] -agp = "8.7.2" -kotlin = "2.0.21" -dokka = "1.9.20" +agp = "8.7.3" +kotlin = "2.1.0" +dokka = "2.0.0" javaRelease = "11" jvmTarget = "11" +kotlinxCoroutinesAndroid = "1.9.0" material = "1.12.0" nexusPlugin = "0.30.0" -binaryCompatibility = "0.16.3" +binaryCompatibility = "0.17.0" androidxActivity = "1.9.3" -androidxCompose = "1.7.5" +androidxCompose = "1.8.0-alpha07" androidxComposeConstraintLayout = "1.1.0" androidxCore = "1.15.0" androidxTest = "1.6.2" @@ -16,7 +17,7 @@ androidxJunit = "1.2.1" androidxMacroBenchmark = "1.3.3" androidxProfileinstaller = "1.4.1" androidxUiAutomator = "2.3.0" -landscapist = "2.4.2" +landscapist = "2.4.4" spotless = "6.7.0" [plugins] @@ -30,6 +31,7 @@ spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } kotlinBinaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binaryCompatibility" } [libraries] +kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" } material = { module = "com.google.android.material:material", version.ref = "material" } androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "androidxCompose" } androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "androidxCompose" }