This article uses two ways to implement asynchronous loading of images in Compose
preface
Loading images asynchronously is a very common requirement in Android development. This article will walk you through this requirement. This paper will be divided into the following two aspects:
- Write your own function
- With the open source library
implementation
Write your own with Glide library
Glide open source library is basically the first choice for loading images on Android. Its easy to use API and powerful caching capabilities make this process very convenient. Naturally, it’s also available in Jetpack Compose.
Introduction of depend on
Add to build.gradle in the module
implementation 'com. Making. Bumptech. Glide: glide: 4.12.0'
annotationProcessor 'com. Making. Bumptech. Glide: the compiler: 4.12.0'
Copy the code
Write a function
How do I get Glide to load an image into the Compose component? For example, into(Target) is used to specify a custom Target, and the return value of mutableState
is used for Compose, for example, when an image is loaded, it automatically updates Compose. Let Glide load a local image for us first and then load the network image. We wrote the following function:
/** * Use Glide library to load network images *@author [FunnySaltyFish](https://funnysaltyfish.github.io)
* @dateThe 2021-07-14 *@paramContext context reasonable context *@paramUrl String Url * of the loaded image@paramDefaultImageId Int Local image * loaded by default@returnMutableState<Bitmap? > Load complete (failure null) Bitmap -state */
fun loadImage(
context: Context,
url: String.@DrawableRes defaultImageId: Int = R.drawable.load_holder
): MutableState<Bitmap? > {val TAG = "LoadImage"
valbitmapState: MutableState<Bitmap? > = mutableStateOf(null)
// Add Headers to the request to increase the success rate of access
val glideUrl = GlideUrl(url,LazyHeaders.Builder().addHeader("User-Agent"."Mozilla / 5.0 (Windows NT 10.0; Win64; X64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/91.0.4472.124 Safari/ 537.36edg /91.0.864.67").build())
// Load the local image first
Glide.with(context)
.asBitmap()
.load(defaultImageId)
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>? {
// Customize the Target to pass the image resources to bitmapState after loading
bitmapState.value = resource
}
override fun onLoadCleared(placeholder: Drawable?).{}})// Then load the network image
try {
Glide.with(context)
.asBitmap()
.load(glideUrl)
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>? {
// Customize the Target to pass the image resources to bitmapState after loading
bitmapState.value = resource
}
override fun onLoadCleared(placeholder: Drawable?).{}})}catch (glideException: GlideException) {
Log.d(TAG, "error: ${glideException.rootCauses}")}return bitmapState
}
Copy the code
Using the example
Here’s a simple example:
@Composable
fun LoadPicture(
url : String
){
val imageState = loadImage(
context = LocalContext.current,
url = url,
)
Card(modifier = Modifier
.padding(4.dp)
.clickable { }) {
// If the image loads successfullyimageState.value? .let { Image( bitmap = it.asImageBitmap(), contentDescription ="",
modifier = Modifier
.padding(4.dp)
.fillMaxWidth()
)
}
}
}
/ /...
LazyColumn {
val urls = arrayListOf<String>()
for (i in 500.550.){urls.add("https://nyc3.digitaloceanspaces.com/food2fork/food2fork-static/featured_images/$i/featured_image.png")}
itemsIndexed(urls){ _ , url -> LoadPicture(url = url)}
}
Copy the code
The effect is as shown in the figure below: Loading
To load P.S. : Don't forget to declare your network permissions!
With open source frameworks
In fact, Google is in itsDevelopment of the document, using an open source libraryAccompanist So we can use this as well
Simple example
implementation "Com. Google. Accompanist: accompanist - coil: 0.13.0"
Copy the code
/ * * *@author [FunnySaltyFish](https://funnysaltyfish.github.io)
* @dateThe 2021-07-14 *@paramUrl loaded link */
@Composable
fun LoadPicture2(url:String){
val painter = rememberCoilPainter(url)
Box {
Image(
painter = painter,
contentDescription = "".)when (painter.loadState) {
is ImageLoadState.Loading -> {
// Display a loading progress bar
CircularProgressIndicator(Modifier.align(Alignment.Center))
}
is ImageLoadState.Error -> {
// If something went wrong, you can write here
Text(text = "An error occurred.", color = MaterialColors.RedA200)
}
else -> Text(text = "Unknown situation", color = MaterialColors.PurpleA400)
}
}
}
Copy the code
The Material colors in the above example come from the open source library CMaterialColors
The effect is as follows:
P.S. : If you want to see better loading, you can set the network type to a slower type in the emulator Settings
Some restrictions
Personally, this approach has the following problems:
- Slide loading is not as smooth as Glide
- There is a requirement for Kotlin edition, i.e. current (as of writing time)
0.13.0
Version must be usedkotlin1.5
Or above, otherwise a compilation error will occur
reference
- video
The end. If you are interested in my article, please visit my Github. IO interface guide!