Translations: 简体中文
AsyncImage is a composable function that asynchronously executes image requests and renders the results. You can use it directly to load and load images, as follows:
// val imageUri = "/Users/my/Downloads/image.jpg"
// val imageUri = file:///compose_resource/composeResources/com.github.panpf.sketch.sample.resources/files/sample.png
val imageUri = "https://example.com/image.jpg"
AsyncImage(
uri = imageUri,
contentDescription = "photo"
)
AsyncImage(
uri = imageUri,
state = rememberAsyncImageState(ComposableImageOptions {
placeholder(Res.drawable.placeholder)
error(Res.drawable.error)
crossfade()
// There is a lot more...
}),
contentDescription = "photo"
)
AsyncImage(
rqeuest = ComposableImageRequest(imageUri) {
placeholder(Res.drawable.placeholder)
error(Res.drawable.error)
crossfade()
// There is a lot more...
},
contentDescription = "photo"
)
Tip
placeholder(Res.drawable.placeholder)
needs to import the sketch-compose-resources
module
SubcomposeAsyncImage is a variant of AsyncImage, which allows you to draw content completely independently, as follows:
SubcomposeAsyncImage(
uri = "https://example.com/image.jpg",
loading = {
Text("Loading")
},
contentDescription = "photo"
)
SubcomposeAsyncImage(
uri = "https://example.com/image.jpg",
contentDescription = "photo",
content = {
when (state.painterState) {
is PainterState.Loading -> {
Text("Loading")
}
is PainterState.Error -> {
Text("Error")
}
else -> {
Image(
painter = painter,
contentDescription = "photo"
)
}
}
}
)
Tip
SubcomposeAsyncImage may not perform as well as AsyncImage, so this combination may not be suitable for performance-critical parts of the list
If you must use the Image component, you can also use AsyncImagePainter directly to load images, as follows:
Image(
painter = rememberAsyncImagePainter(uri = "https://example.com/image.jpg"),
contentDescription = "photo"
)
Image(
painter = rememberAsyncImagePainter(
rqeuest = ComposableImageRequest("https://example.com/image.jpg") {
placeholder(Res.drawable.placeholder)
error(Res.drawable.error)
crossfade()
// There is a lot more...
}
),
contentDescription = "photo"
)
Tip
Image + AsyncImagePainter
will be slightly slower than AsyncImage, this is due to [Sketch] Depends on the exact size of the component before loading the image, AsyncImage The size of the component can be obtained during the layout stage, whileImage + AsyncImagePainter
cannot obtain the component size until the drawing stage.- If the contentScale is modified on the Image, the contentScale of rememberAsyncImagePainter must also be modified simultaneously.
placeholder(Res.drawable.placeholder)
needs to import thesketch-compose-resources
module
AsyncImageState is the core of AsyncImage and AsyncImagePainter. AsyncImageState is responsible for execution ImageRequest and management state, AsyncImagePainter is responsible for reading Painter from AsyncImageState and drawing, AsyncImage is responsible for layout
You can read the status, progress, and Painter of the request from AsyncImageState, and you can also reload the image through its restart() method, as follows:
val state = rememberAsyncImageState()
AsyncImage(
uri = "https://example.com/image.jpg",
contentDescription = "photo",
state = state,
)
val result: ImageResult? = state.result
val loadState: LoadState? = state.loadState
val request: ImageRequest = loadState.request
when (loadState) {
is Started -> {
}
is Success -> {
val cacheKey: String = loadState.result.cacheKey
val imageInfo: ImageInfo = loadState.result.imageInfo
val dataFrom: DataFrom = loadState.result.dataFrom
val resize: Resize = loadState.result.resize
val transformeds: List<String>? = loadState.result.transformeds
val extras: Map<String, String>? = loadState.result.extras
}
is Error -> {
val throwable: Throwable = loadState.result.throwable
}
is Canceled -> {}
else -> {
// null
}
}
val progress: Progress? = state.progress
val painterState: PainterState = state.painterState
when (painterState) {
is Loading -> {}
is Success -> {}
is Error -> {}
}
val painter: Painter? = state.painter
// Reload
state.restart()
When using AsyncImage, SubcomposeAsyncImage and AsyncImagePainter, you cannot call ImageRequest addListener(), addProgressListener() methods, which will cause the app to crash
The reason is that when using Listener and ProgressListener, in most cases, they directly new a new instance, which will cause The equals result of ImageRequest is false and triggers reorganization, thus reducing performance
Therefore you must use the loadState and progress properties of AsyncImageState instead of addListener(), addProgressListener()
When using AsyncImage, SubcomposeAsyncImage and AsyncImagePainter, you cannot call ImageRequest target() method, which will cause the app to crash because the Target must be configured by AsyncImageState