Improved avatar loading
Now avatar loading checks first if there is a cached avatar and before showing the placeholder, to avoid showing the placeholder for a moment when a cached version is available. This will reduce CPU usage by a tiny bit since the placeholder won't have to be rendered.
This commit is contained in:
parent
20e23a9750
commit
dc31181387
@ -20,12 +20,18 @@ object NetworkImageLoader {
|
|||||||
private val loadingImagesSemaphore = Semaphore(MAX_LOADING_IMAGES)
|
private val loadingImagesSemaphore = Semaphore(MAX_LOADING_IMAGES)
|
||||||
private val cache: ImagesCache = InMemoryImagesCache
|
private val cache: ImagesCache = InMemoryImagesCache
|
||||||
|
|
||||||
|
fun loadCachedImage(url: String): ImageBitmap? {
|
||||||
|
val cachedImage = cache.getCachedImage(url)
|
||||||
|
|
||||||
|
return cachedImage?.toComposeImage()
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun loadImageNetwork(url: String): ImageBitmap? = withContext(Dispatchers.IO) {
|
suspend fun loadImageNetwork(url: String): ImageBitmap? = withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val cachedImage = cache.getCachedImage(url)
|
val cachedImage = loadCachedImage(url)
|
||||||
|
|
||||||
if (cachedImage != null)
|
if (cachedImage != null)
|
||||||
return@withContext cachedImage.toComposeImage()
|
return@withContext cachedImage
|
||||||
|
|
||||||
loadingImagesSemaphore.acquireAndUse {
|
loadingImagesSemaphore.acquireAndUse {
|
||||||
val imageByteArray = loadImage(url)
|
val imageByteArray = loadImage(url)
|
||||||
@ -34,7 +40,7 @@ object NetworkImageLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
if(ex !is FileNotFoundException)
|
if (ex !is FileNotFoundException)
|
||||||
ex.printStackTrace()
|
ex.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,24 +60,40 @@ object NetworkImageLoader {
|
|||||||
@Composable
|
@Composable
|
||||||
fun rememberNetworkImageOrNull(url: String, placeHolderImageRes: String? = null): ImageBitmap? {
|
fun rememberNetworkImageOrNull(url: String, placeHolderImageRes: String? = null): ImageBitmap? {
|
||||||
val networkImageLoader = NetworkImageLoader
|
val networkImageLoader = NetworkImageLoader
|
||||||
|
val cacheImageUsed = remember { ValueHolder(false) }
|
||||||
|
|
||||||
var image by remember(url) {
|
var image by remember(url) {
|
||||||
val placeHolderImage = if (placeHolderImageRes != null)
|
val cachedImage = networkImageLoader.loadCachedImage(url)
|
||||||
useResource(placeHolderImageRes) {
|
|
||||||
|
val image: ImageBitmap? = when {
|
||||||
|
cachedImage != null -> {
|
||||||
|
cacheImageUsed.value = true
|
||||||
|
cachedImage
|
||||||
|
}
|
||||||
|
placeHolderImageRes != null -> useResource(placeHolderImageRes) {
|
||||||
Image.makeFromEncoded(it.toByteArray()).toComposeImageBitmap()
|
Image.makeFromEncoded(it.toByteArray()).toComposeImageBitmap()
|
||||||
}
|
}
|
||||||
else
|
else -> null
|
||||||
null
|
}
|
||||||
|
|
||||||
mutableStateOf(placeHolderImage)
|
return@remember mutableStateOf(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(url) {
|
LaunchedEffect(url) {
|
||||||
val networkImage = networkImageLoader.loadImageNetwork(url)
|
if(!cacheImageUsed.value) {
|
||||||
if (networkImage != null)
|
val networkImage = networkImageLoader.loadImageNetwork(url)
|
||||||
image = networkImage
|
|
||||||
|
if (networkImage != null && !cacheImageUsed.value) {
|
||||||
|
image = networkImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return image
|
return image
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ByteArray.toComposeImage() = Image.makeFromEncoded(this).toComposeImageBitmap()
|
fun ByteArray.toComposeImage() = Image.makeFromEncoded(this).toComposeImageBitmap()
|
||||||
|
|
||||||
|
|
||||||
|
internal class ValueHolder<T>(var value: T)
|
Loading…
Reference in New Issue
Block a user