Work on result

This commit is contained in:
Oupson 2021-06-25 13:50:27 +02:00
parent 4ef644632a
commit 31c7529d45
2 changed files with 454 additions and 451 deletions

View File

@ -53,7 +53,7 @@ class ApngDecoder(input: InputStream, val config: Config) {
}
}
private val inputStream: InputStream? = input
private var inputStream: InputStream? = input
private var result: Result<Drawable>? = null
/**
@ -65,7 +65,9 @@ class ApngDecoder(input: InputStream, val config: Config) {
*/
suspend fun decodeApng(
context: Context
): Drawable = withContext(Dispatchers.Default) {
): Result<Drawable> =
kotlin.runCatching {
withContext(Dispatchers.Default) {
val inputStream = BufferedInputStream(inputStream)
val bytes = ByteArray(8)
inputStream.mark(8)
@ -83,7 +85,8 @@ class ApngDecoder(input: InputStream, val config: Config) {
var tnrs: ByteArray? = null
var maxWidth = 0
var maxHeight = 0
var blendOp: Utils.Companion.BlendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE
var blendOp: Utils.Companion.BlendOp =
Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE
var disposeOp: Utils.Companion.DisposeOp =
Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
@ -494,13 +497,13 @@ class ApngDecoder(input: InputStream, val config: Config) {
withContext(Dispatchers.IO) {
inputStream.close()
}
return@withContext drawable
drawable
} else {
if (BuildConfig.DEBUG)
Log.i(TAG, "Decoding non APNG stream")
inputStream.reset()
return@withContext if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val bytesRead: ByteArray
withContext(Dispatchers.IO) {
bytesRead = inputStream.readBytes()
@ -519,16 +522,17 @@ class ApngDecoder(input: InputStream, val config: Config) {
withContext(Dispatchers.IO) {
inputStream.close()
}
drawable
drawable!!
}
}
}
}
suspend fun getDecoded(context: Context): Result<Drawable> {
if (result == null) {
result = kotlin.runCatching {
result =
decodeApng(context)
}
kotlin.runCatching {
withContext(Dispatchers.IO) {
@ -537,6 +541,8 @@ class ApngDecoder(input: InputStream, val config: Config) {
}.onFailure {
return Result.failure(it)
}
inputStream = null
}
return result ?: Result.failure(NullPointerException("result is null"))
@ -639,12 +645,13 @@ class ApngDecoder(input: InputStream, val config: Config) {
* @param config Decoder configuration
* @return [ApngDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif.
*/
@Suppress("unused", "BlockingMethodInNonBlockingContext")
@Suppress("unused")
@JvmStatic
suspend fun constructFromUrl(
url: URL,
config: Config = Config()
) =
): Result<ApngDecoder> =
kotlin.runCatching {
withContext(Dispatchers.IO) {
ApngDecoder(
ByteArrayInputStream(Loader.load(url)),
@ -653,3 +660,4 @@ class ApngDecoder(input: InputStream, val config: Config) {
}
}
}
}

View File

@ -153,7 +153,9 @@ class ApngLoader(parent: Job? = null) {
imageView: ImageView,
config: ApngDecoder.Config = ApngDecoder.Config()
): Result<Drawable> {
val result = ApngDecoder.constructFromUrl(url, config).getDecoded(context)
val result =
ApngDecoder.constructFromUrl(url, config).getOrElse { return Result.failure(it) }
.getDecoded(context)
if (result.isSuccess) {
withContext(Dispatchers.Main) {
val drawable = result.getOrNull()
@ -204,10 +206,10 @@ class ApngLoader(parent: Job? = null) {
withContext(Dispatchers.IO) {
context.assets.open(string.replace("file:///android_asset/", ""))
}
}.onFailure {
}.getOrElse {
return Result.failure(it)
}
val result = ApngDecoder(inputStream.getOrThrow(), config).getDecoded(context)
val result = ApngDecoder(inputStream, config).getDecoded(context)
if (result.isSuccess) {
withContext(Dispatchers.Main) {
val drawable = result.getOrNull()
@ -246,11 +248,9 @@ class ApngLoader(parent: Job? = null) {
coroutineScope.launch(Dispatchers.Default) {
val drawable = decodeApngInto(context, file, imageView, config)
withContext(Dispatchers.Main) {
if (drawable.isSuccess) {
callback?.onSuccess(drawable.getOrNull()!!)
} else {
callback?.onError(drawable.exceptionOrNull()!!)
}
drawable
.onSuccess { callback?.onSuccess(it) }
.onFailure { callback?.onError(it) }
}
}
@ -274,11 +274,9 @@ class ApngLoader(parent: Job? = null) {
) = coroutineScope.launch(Dispatchers.Default) {
val drawable = decodeApngInto(context, uri, imageView, config)
withContext(Dispatchers.Main) {
if (drawable.isSuccess) {
callback?.onSuccess(drawable.getOrNull()!!)
} else {
callback?.onError(drawable.exceptionOrNull()!!)
}
drawable
.onSuccess { callback?.onSuccess(it) }
.onFailure { callback?.onError(it) }
}
}
@ -300,11 +298,9 @@ class ApngLoader(parent: Job? = null) {
) = coroutineScope.launch(Dispatchers.Default) {
val drawable = decodeApngInto(context, res, imageView, config)
withContext(Dispatchers.Main) {
if (drawable.isSuccess) {
callback?.onSuccess(drawable.getOrNull()!!)
} else {
callback?.onError(drawable.exceptionOrNull()!!)
}
drawable
.onSuccess { callback?.onSuccess(it) }
.onFailure { callback?.onError(it) }
}
}
@ -327,14 +323,13 @@ class ApngLoader(parent: Job? = null) {
) = coroutineScope.launch(Dispatchers.Default) {
val drawable = decodeApngInto(context, url, imageView, config)
withContext(Dispatchers.Main) {
if (drawable.isSuccess) {
callback?.onSuccess(drawable.getOrNull()!!)
} else {
callback?.onError(drawable.exceptionOrNull()!!)
}
drawable
.onSuccess { callback?.onSuccess(it) }
.onFailure { callback?.onError(it) }
}
}
/**
* Load Apng into an imageView, asynchronously.
* @param context Context needed for decoding the image and creating the animation drawable.