I have this image I want to load, I am using coil in jetpack compose to try and load it yet it didn't load and just gave me an empty composable. Whenever I try to load a different image from any other website it works, yet when I use the same website I am loading this image from. It doesn't Work.
Here is My Code:
#Composable
fun BookItem(
title: String,
cover: String?,
unreadChapters: Int,
) {
Box(
modifier = Modifier
.wrapContentSize(),
contentAlignment = Alignment.Center
) {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(cover)
.crossfade(true)
.build(),
contentDescription = title,
contentScale = ContentScale.Inside,
modifier = Modifier
.clip(RoundedCornerShape(size = 12.dp))
.size(200.dp)
)
}
}
Here is the link:
https://static.lightnovelworld.com/bookcover/300x400/01365-shadow-slave.jpg
I tried using glide instead of coil and I got the same problem.
Thanks and Regards
You can debug it using:
val imageLoader = LocalContext.current.imageLoader.newBuilder()
.logger(DebugLogger())
.build()
AsyncImage(
//...
imageLoader = imageLoader,
)
Result:
🚨 Failed - https://static.lightnovelworld.com/bookcover/300x400/01365-shadow-slave.jpg - coil.network.HttpException: HTTP 403:
You can try to add some headers in you requests using something like:
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(url)
.setHeader("User-Agent", "Mozilla/5.0")
.build(),
//
)
Related
I have a list of photos from the internet and I want to load them into a LazyColumn. The problem is that some of them are loading faster than others so the photos appear in random order.
Here is the code:
val state = viewModel.photos.collectAsState()
val lastIndex = state.value.lastIndex
LazyColumn {
itemsIndexed(state.value) { i, photo ->
AsyncImage(
model = photo.urls.regular,
contentDescription = null,
modifier = Modifier.fillMaxWidth(),
)
if (i >= lastIndex-1 && !viewModel.isLoading.value) {
viewModel.getPhotos(6)
}
}
}
Sometimes image with LastIndex-1 occurs first and it triggers viewModel to get new data.
How can I make a handler for loading a list of images? Or maybe any suggestions on how to make a preloading screen which will end after loading all images into LazyColumn
I also have a Coil version too:
val model = ImageRequest.Builder(LocalContext.current)
.data(photo.urls.regular)
.size(Size.ORIGINAL)
.crossfade(true)
.build()
val painter = rememberAsyncImagePainter(model)
Image(
painter = painter,
contentDescription = null,
modifier = Modifier.fillMaxWidth(),
)
I want to load the image on the spash screen so that I can set the request result to the background on other screens using the coil, but I have not been able to fully realize this in the coil. How can I save the result of my coil request to Cahce and use this result on other screens?
Splash Screen
val imageLoader = ImageLoader.Builder(this)
.memoryCache {
MemoryCache.Builder(this)
.maxSizePercent(0.25)
.strongReferencesEnabled(true)
.build()
}
.diskCache {
DiskCache.Builder()
.directory(this.cacheDir.resolve("image_cache"))
.maxSizePercent(0.02)
.build()
}
.build()
and I used like this on splash
val context = LocalContext.current
val request = ImageRequest.Builder(context)
.memoryCacheKey(Constants.Cache.BACKGROUND_IMAGE_KEY)
.data("https://www.example/image1.jpg")
.target(
onSuccess = {
viewModel.skipImageRequest()
},
onError = {
viewModel.skipImageRequest()
}
)
.build()
imageLoader.enqueue(request)
in another screen that I want to use image
#Composable
fun BackgroundImage(
model: Any?,
contentDescription: String? = "",
modifier: Modifier = Modifier.fillMaxSize(),
//placeholder: Painter? = painterResource(R.drawable.bg_placeholder),
error: Painter? = painterResource(R.drawable.bg_placeholder),
fallback: Painter? = painterResource(R.drawable.bg_placeholder),
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.FillBounds
) {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data("https://www.example/image1.jpg")
.placeholderMemoryCacheKey(Constants.Cache.BACKGROUND_IMAGE_KEY)
.build(),
contentDescription = contentDescription,
modifier = modifier,
//placeholder = placeholder,
error = error,
fallback = fallback,
alignment = alignment,
contentScale = contentScale,
)
}
There is an always problem the placeholder image is shown in initialize of page I could not construct a structure where the placeholder is not visible while the image is being loaded and the image is read and used directly from the cahce.
I would be very happy if you support
Coil internally uses OkHttp's DiskCache in 1.x version
For 2.x they have introduced a disk cache to store your result.
For further information read this
My Gradle
// Coil
implementation "io.coil-kt:coil-compose:1.4.0"
Problem Description
Previously I used the coil together with Google's accompanist, but when I migrate to the new version of the coil as the documentation suggests I'm having problems with the target method:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pokedex, PID: 13502
java.lang.IllegalArgumentException: request.target must be null.
at coil.compose.ImagePainterKt.rememberImagePainter(ImagePainter.kt:94)
...
Coil Implementation
When browsing the internal code of ImagePainter (coil class) you can see that the target method really needs to be null for some reason:
#Composable
fun rememberImagePainter(
request: ImageRequest,
imageLoader: ImageLoader,
onExecute: ExecuteCallback = ExecuteCallback.Default,
): ImagePainter {
requireSupportedData(request.data)
require(request.target == null) { "request.target must be null." }
...
My Code
Here's my component in jetpack compose (the image component is inside a column):
Image(
modifier = Modifier
.size(120.dp)
.align(Alignment.CenterHorizontally),
painter = rememberImagePainter(
data = entry.imageUrl,
builder = {
crossfade(true)
target {
viewModel.calcDominantColor(it) { color ->
dominantColor = color
}
}
transformations(CircleCropTransformation())
},
),
contentDescription = entry.pokemonName
)
I need the target method to do internal operations on my viewModel based on the drawable it passes as a parameter. Can someone help me?
In Coil 2.0.0 both AsyncImage and rememberAsyncImagePainter have onSuccess callback parameter, using which you can get the drawable as follows:
AsyncImage(
model = imageURL,
contentDescription = null,
onSuccess = { success ->
val drawable = success.result.drawable
}
)
Coil 1.4.0 version:
This is intended behaviour since rememberImagePainter sets the target internally.
You can track the painter state, wait for the Success and get the drawable from it. Also use it with LaunchedEffect to prevent re-calculations:
val painter = rememberImagePainter(
data = imageUrl,
builder = {
...
},
)
(painter.state as? ImagePainter.State.Success)
?.let { successState ->
LaunchedEffect(Unit) {
val drawable = successState.result.drawable
viewModel.calcDominantColor(drawable) { color ->
dominantColor = color
}
}
}
Image(
painter = painter,
contentDescription = "...",
modifier = Modifier
...
)
I know you follow this https://www.youtube.com/watch?v=jrIfGAk8PyQ&list=PLQkwcJG4YTCTimTCpEL5FZgaWdIZQuB7m&index=5
by Philipp Lackner
try this code
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(entry.imageUrl)
.crossfade(true)
.build(),
contentDescription = entry.pokemonName,
onSuccess = {
viewModel.calcDominantColor(it.result.drawable) { color ->
dominantColor = color
}
},
modifier = Modifier
.size(120.dp)
.align(CenterHorizontally)
)
and use this library implementation("io.coil-kt:coil-compose:2.2.2")
and to more information https://coil-kt.github.io/coil/compose/
I'm implementing a simple gallery screen using Jetpack Compose which shows all video and image thumbnails on the screen
I have displayed image from file path successfully. However, I've got trouble in showing video thumbnail. How can I do that using Coil?
Here's my code to show image thumbnails:
#Composable
fun ImageLoaderFromLocal(
url: String,
placeHolderResId: Int,
modifier: Modifier,
transformation: Transformation
) {
val painter = rememberImagePainter(data = File(url),
builder = {
placeholder(placeHolderResId)
crossfade(true)
transformations(transformation)
})
Image(
painter = painter,
contentDescription = null,
modifier = modifier,
contentScale = ContentScale.Inside
)
}
According to Coil documentation, you need to add following dependency:
implementation("io.coil-kt:coil-video:$coil_version")
and specify fetcher in the builder:
val context = LocalContext.current
val painter = rememberImagePainter(
data = url,
builder = {
fetcher(VideoFrameUriFetcher(context))
// optionally set frame location
videoFrameMillis(1000)
placeholder(placeHolderResId)
crossfade(true)
transformations(transformation)
}
)
The other answer doesn't really work any more.
so i tried this one and it worked
val context = LocalContext.current
var visible by rememberSaveable { mutableStateOf(false) }
val imageLoader = ImageLoader.Builder(context)
.components {
add(VideoFrameDecoder.Factory())
}.crossfade(true)
.build()
val painter = rememberAsyncImagePainter(
model = "Your file here",
imageLoader = imageLoader,
The painter should be called in the image composable
like this
Image(
painter = painter,
contentDescription = "",
contentScale = ContentScale.Crop,
alignment = Alignment.Center,
modifier = Modifier.fillMaxSize()
)
i hope this help someone
I would like to load saved image on cache into Image of Jetpack Compose using Coil. I searched in stackoverflow but all suggested ways are for loading web urls. I know that It's possible to convert image file to bitmap and then pass it to Coil but is there any builtin solution for it?
You can use Coil to load any object as a data:
val cacheFile = File(context.cacheDir, "filename")
Image(
rememberImagePainter(cacheFile),
contentDescription = "...",
)
If you've a locally saved image path, you can try the following method,
val painter = rememberImagePainter(data = File(filePath))
Image(
painter = painter,
contentDescription = null)
and to load image from remote url,
val painter = rememberImagePainter(data = imageUrl)
Image(
painter = painter,
contentDescription = null)
For the new version of coil 2.2.2, rememberImagePainter didn't give me good results so I used this-
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(<file_path>)
.build(),
contentDescription = "icon",
contentScale = ContentScale.Inside,
modifier = Modifier.size(30.dp)
)
Hope it helps someone