如何在 Compose 中预加载线圈图像?
How to preload Coil image in Compose?
我有一个寻呼机(伴奏),其图像是通过 Compose 中的 Coil 从网络上获取的。
rememberPainter()
似乎仅在首次显示 Image
可组合项时调用请求。
因此,当我在寻呼机中滑动页面时,Image
仅在那一刻显示,因此我们必须稍等片刻。
有什么方法可以强制 rememberPainter
(线圈)预加载?
编辑 1:
这是我实现的一个简单版本(删除了很多东西但对结果没有影响):
@Composable
private fun Foo(imageList: List<ImageHolder>) {
if (imageList.isEmpty())
return
val painterList = imageList.map {
rememberImagePainter(
data = it.getDataForPainter(),
builder = {
crossfade(true)
})
}
ImageLayout(imageList, painterList)
}
@Composable
fun ImageLayout(imageList: List<ImageHolder>, painterList: List<Painter>) {
HorizontalPager(
count = imageList.size,
modifier = Modifier.fillMaxWidth(),
) { page ->
Image(
painter = painterList[page],
"",
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
.background(
imageList[page].colorAverage
),
contentScale = ContentScale.Crop
)
}
}
为了以防万一,我也尝试过在图像上直接使用 rememberImagePainter。
但问题显然是第 2、3、4 页的 Image() 未呈现,因此 Image 不会调用画家。我试图查看它在内部的工作原理,但找不到。
编辑 2:我找到了解决方法,但它并不干净
for (painter in painterList)
Image(painter = painter, contentDescription = "", modifier = Modifier.size(0.001.dp))
它强制线圈加载图像,并且尺寸非常小,如 0.001.dp
(0
不加载)。
还有一个问题是,在构建器中你需要强制一个尺寸,否则它只会加载一个像素,所以我强制使用图像的完整尺寸,因为我不知道图像可用的尺寸。
在线圈文档中有 section about preloading. Depending on your architecture, you can do this in different places, the easiest is to use LaunchedEffect
:
val context = LocalContext.current
LaunchedEffect(Unit) {
val request = ImageRequest.Builder(context)
.data("https://www.example.com/image.jpg")
// Optional, but setting a ViewSizeResolver will conserve memory by limiting the size the image should be preloaded into memory at.
// For example you can set static size, or size resolved with Modifier.onSizeChanged
// .size(coil.size.PixelSize(width = 100, height = 100))
// or resolve display size if your images are full screen
// .size(DisplaySizeResolver(context))
.build()
context.imageLoader.enqueue(request)
}
在版本 2.0.0 之前使用 LocalImageLoader.current
而不是 context.imageLoader
来获取图像加载器。
我有一个寻呼机(伴奏),其图像是通过 Compose 中的 Coil 从网络上获取的。
rememberPainter()
似乎仅在首次显示 Image
可组合项时调用请求。
因此,当我在寻呼机中滑动页面时,Image
仅在那一刻显示,因此我们必须稍等片刻。
有什么方法可以强制 rememberPainter
(线圈)预加载?
编辑 1:
这是我实现的一个简单版本(删除了很多东西但对结果没有影响):
@Composable
private fun Foo(imageList: List<ImageHolder>) {
if (imageList.isEmpty())
return
val painterList = imageList.map {
rememberImagePainter(
data = it.getDataForPainter(),
builder = {
crossfade(true)
})
}
ImageLayout(imageList, painterList)
}
@Composable
fun ImageLayout(imageList: List<ImageHolder>, painterList: List<Painter>) {
HorizontalPager(
count = imageList.size,
modifier = Modifier.fillMaxWidth(),
) { page ->
Image(
painter = painterList[page],
"",
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
.background(
imageList[page].colorAverage
),
contentScale = ContentScale.Crop
)
}
}
为了以防万一,我也尝试过在图像上直接使用 rememberImagePainter。 但问题显然是第 2、3、4 页的 Image() 未呈现,因此 Image 不会调用画家。我试图查看它在内部的工作原理,但找不到。
编辑 2:我找到了解决方法,但它并不干净
for (painter in painterList)
Image(painter = painter, contentDescription = "", modifier = Modifier.size(0.001.dp))
它强制线圈加载图像,并且尺寸非常小,如 0.001.dp
(0
不加载)。
还有一个问题是,在构建器中你需要强制一个尺寸,否则它只会加载一个像素,所以我强制使用图像的完整尺寸,因为我不知道图像可用的尺寸。
在线圈文档中有 section about preloading. Depending on your architecture, you can do this in different places, the easiest is to use LaunchedEffect
:
val context = LocalContext.current
LaunchedEffect(Unit) {
val request = ImageRequest.Builder(context)
.data("https://www.example.com/image.jpg")
// Optional, but setting a ViewSizeResolver will conserve memory by limiting the size the image should be preloaded into memory at.
// For example you can set static size, or size resolved with Modifier.onSizeChanged
// .size(coil.size.PixelSize(width = 100, height = 100))
// or resolve display size if your images are full screen
// .size(DisplaySizeResolver(context))
.build()
context.imageLoader.enqueue(request)
}
在版本 2.0.0 之前使用 LocalImageLoader.current
而不是 context.imageLoader
来获取图像加载器。