Jetpack Compose 通用加载微件的实现

加载数据在Android开发中应该算是非常频繁的操作了,因此简单在Jetpack Compose中实现一个通用的加载微件

效果如下:

加载中(转圈圈)

加载完成(显示内容)

另外加载失败后显示失败并可以点击重试

实现

实现这个微件其实非常简单,无非就是根据不同的状态加载不同页面

加载状态Bean

首先把加载的状态抽象出来,写个数据类

 sealed class LoadingState<out R> {
     object Loading : LoadingState<Nothing>()
     data class Failure(val error : Throwable) : LoadingState<Nothing>()
     data class Success<T>(val data : T) : LoadingState<T>()
 ​
     val isLoading
         get() = this is Loading
     val isSuccess
         get() = this is Success<*>
 }
复制代码

此处借鉴了朱江大佬写的玩安卓Compose版本,在此感谢

微件

然后就是加载了。考虑到加载一般耗时,所以用协程。

写成微件大概就是下面这个样子

 private const val TAG = "LoadingWidget"
 ​
 /**
  * 通用加载微件
  * @author [FunnySaltyFish](https://blog.funnysaltyfish.fun/)
  * @param modifier Modifier 整个微件包围在Box中,此处修饰此Box
  * @param loader  加载函数,返回值为正常加载出的结果
  * @param loading 加载中显示的页面,默认为转圈圈
  * @param failure 加载失败显示的页面,默认为文本,点击可以重新加载(retry即为重新加载的函数)
  * @param success 加载成功后的页面,参数[T]即为返回的结果
  */
 @Composable
 fun <T> LoadingContent(
     modifier: Modifier = Modifier,
     loader : suspend ()->T,
     loading : @Composable ()->Unit = { DefaultLoading() },
     failure : @Composable (error : Throwable, retry : ()->Unit)->Unit = { error, retry->
         DefaultFailure(error, retry)
     },
     success : @Composable (data : T?)->Unit
 ) {
     var key by remember {
         mutableStateOf(false)
     }
     val state : LoadingState<T> by produceState<LoadingState<T>>(initialValue = LoadingState.Loading, key){
         value = try {
             Log.d(TAG, "LoadingContent: loading...")
             LoadingState.Success(loader())
         }catch (e: Exception){
             LoadingState.Failure(e)
         }
     }
     Box(modifier = modifier){
         when(state){
             is LoadingState.Loading -> loading()
             is LoadingState.Success<T> -> success((state as LoadingState.Success<T>).data)
             is LoadingState.Failure -> failure((state as LoadingState.Failure).error){
                 key = !key
                 Log.d(TAG, "LoadingContent: newKey:$key")
             }
         }
     }
 }
复制代码

里面的默认页面如下:

 @Composable
 fun DefaultLoading() {
     CircularProgressIndicator()
 }
 ​
 @Composable
 fun DefaultFailure(error: Throwable, retry : ()->Unit) {
     Text(text = stringResource(id = R.string.loading_error), modifier = Modifier.clickable(onClick = retry))
 }
复制代码

使用起来也很简单直接

 LoadingContent(
     modifier = Modifier.align(CenterHorizontally) ,
     loader = (vm.sponsorService::getAllSponsor) 
 ) { sponsorList ->
             sponsorList?.let{
                 Column {
                     SponsorList(it)
                     Text("加载完成")
                 }
             }
         }
复制代码

完整代码在这里:FunnyTranslation/ThanksScreen.kt

完了。

最后再自荐一下我的开源项目(就是上面那个链接),Jetpack Compose实现的翻译软件。不妨点个star,万一什么地方有用呢(逃~

猜你喜欢

转载自juejin.im/post/7033755169213022216