Skip to content

Latest commit

 

History

History
205 lines (165 loc) · 6.34 KB

compose.md

File metadata and controls

205 lines (165 loc) · 6.34 KB

Compose

Translations: 简体中文

AsyncImage

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 = "compose.resource://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

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

AsyncImagePainter

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

  1. 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, while Image + AsyncImagePainter cannot obtain the component size until the drawing stage.
  2. If the contentScale is modified on the Image, the contentScale of rememberAsyncImagePainter must also be modified simultaneously.
  3. placeholder(Res.drawable.placeholder) needs to import the sketch-compose-resources module

AsyncImageState

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 -> {}
    is Empty -> {}
}
val painter: Painter? = state.painter

// Reload
state.restart()

listener/progressListener

When using AsyncImage, SubcomposeAsyncImage and AsyncImagePainter, you cannot call ImageRequest listener(), progressListener() 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 listener(), progressListener()

Target

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