> 文章列表 > Jetpack Compose 实战 宝可梦图鉴

Jetpack Compose 实战 宝可梦图鉴

Jetpack Compose 实战 宝可梦图鉴

文章目录

  • 前言
  • 实现效果
  • 一、架构介绍
  • 二、一些的功能点的介绍
    • 加载图片并获取主色,再讲主色设置为背景
    • 一个进度缓慢增加的圆形进度条
    • 单Activity使用navigation跳转Compose可组合项返回时页面重组的问题
    • hiltViewModel()
  • 主要参考项目
  • 总结

前言

阅读本文需要一定compose基础,如果没有请移步Jetpack Compose入门详解(实时更新)
学Compose学了有小半年的时间了,一直都是看官方的一些基础的教程并总结学习。最近终于实战了一个宝可梦图鉴的小项目,麻雀虽小五脏俱全。除了Compose外,还使用了一下一些Jetpack组件

  • accompanist-pager

  • coil

  • hilt

  • paging3

  • navigation-compose

  • accompanist-systemuicontroller

  • Retrofit

  • Kotlin Flow

接口数据来源于pokeapi

项目源代码


实现效果

闲话不多说,让我们来看看实现效果
Jetpack Compose 实战 宝可梦图鉴
可以看到我们实现了一个非常简洁的宝可梦图鉴,展示了所有世代的宝可梦,并提供了搜索,点击进入详情查看他们的属性

一、架构介绍

如图,展示了主要的一些文件:
Jetpack Compose 实战 宝可梦图鉴

  • api - 接口
  • nav - navigation导航
  • utils -工具类
  • view -Compose组件
  • viewmodels - viewmodel

二、一些的功能点的介绍

主要是开发过程中遇到的一些问题

加载图片并获取主色,再讲主色设置为背景

展示图片本来有封装好的CommonImage.kt用来展示图片,但是在列表中每一张图片的背景色都是动态获取的,当时做的时候觉得比较难弄,后面实现了过后就觉得还好啦。

引入的库

    implementation "io.coil-kt:coil-compose:2.1.0"//get Dominant image colorimplementation 'androidx.palette:palette-ktx:1.0.0'

主要代码在FullScreenView.kt中的 item()

	//我们所动态获取的图片背景色var backgroundColor by remember { mutableStateOf(0) }val context = LocalContext.current//ImageRequestval modelBuilder = ImageRequest.Builder(context).data(item.url.getPicUrl()).crossfade(false).allowHardware(false).transformations().placeholder(R.drawable.ic_pokeball).error(R.drawable.ic_pokeball)//开启一个获取协程的附带效应当ImageRequest发生改变时,通过ImageRequest来动态获取bitmap//再通过Palette来获取其主色LaunchedEffect(modelBuilder.build()) {val bitmap = context.imageLoader.execute(modelBuilder.build()).drawable?.toBitmap(config = Bitmap.Config.RGBA_F16)bitmap?.let {val palette = Palette.from(bitmap).generate()//当backgroundColor得到值,可组合项重组backgroundColor = palette.getDominantColor(0)}}

上面的代码最终能实现我想要的效果,但是我始终觉得不够优雅,后面有机会在封装一下吧

一个进度缓慢增加的圆形进度条

也是封装好的通用组件CommonCircularProgress.kt

@Composable
fun CommonAttributeCircularProgress(text:String,content:String,mProgress: Float,modifier: Modifier){Column(horizontalAlignment = Alignment.CenterHorizontally) {var progress = remember {mutableStateOf(0.0f)}LaunchedEffect(true){var state = 0.0fwhile (state <= mProgress) {progress.value = statestate += mProgress / 10fdelay(50)}}Box(){Text(text = text,modifier = modifier.align(Alignment.Center))CircularProgressIndicator(progress = 1f,color = Color(0xFFffcba4),modifier = modifier.align(Alignment.Center).size(150.cdp, 150.cdp))CircularProgressIndicator(progress = progress.value,color = MaterialTheme.colors.secondary,modifier = modifier.align(Alignment.Center).size(150.cdp, 150.cdp))}Text(text = content, modifier = modifier.padding(top = 10.cdp))}
}

我没有找到能给CircularProgressIndicator可组合项目设置进度条范围内的背景的属性,所以使用了box将其覆盖一个CircularProgressIndicator可组合项来实现其背景的假象

单Activity使用navigation跳转Compose可组合项返回时页面重组的问题

列表项数据我按照官方推荐使用的方法直接使用了collectAsLazyPagingItems,然后我发现它确实起作用了,但是也发生了上诉问题,我每一次从详情页返回到列表页,列表页都会闪烁然后重组。这是因为每一次返回,可组合项都重新进行了请求导致数据发生变化,从而导致重组,为了解决这一问题,我在viewmodel中保存了一份请求得到的数据

@HiltViewModel
class PokemonListViewModel @Inject constructor(private val pokemonRepository: PokemonRepository
) :ViewModel() {// 宝可梦列表数据流  currentResult是为了保证从详情页面返回时不重新加载数据var currentResult: Flow<PagingData<PokemonResult>>? = nullfun getPokemon(searchString: String?): Flow<PagingData<PokemonResult>> {val newResult = pokemonRepository.getPokemon(searchString).cachedIn(viewModelScope)currentResult = newResultreturn newResult}}

并在页面中这样正确使用collectAsLazyPagingItems

    var list: LazyPagingItems<PokemonResult>? = nulllist = if (vm.currentResult != null) {vm.currentResult!!.collectAsLazyPagingItems()} else {vm.getPokemon(searchString.value).collectAsLazyPagingItems()}

这样当我从详情页返回到列表页时,页面显示正常

hiltViewModel()

在使用viemodel时,一开始我按照官方使用viewmodel的示例使用了viewModel()方法,并且在调试中是正常的。

val vm: PokemonListViewModel = viewModel()

可当我在加入navigation 后,viewmodel并不能正常的工作,后来查阅资料发现要使用

    implementation "androidx.navigation:navigation-compose:2.5.0-beta01"

包中的 hiltViewModel()

val vm: PokemonListViewModel = hiltViewModel()

主要参考项目

Jetpack Compose仿写网易云音乐
NCMusic;
一个使用原生xml kotlin写的宝可梦图鉴
PokeApi-Pokedex;

总结

整个项目其实就两个可组合项,一个是FullScreenView(列表页),一个是AttributeDetailView(详情页),每个页面就200行代码左右,对比起原生xml,的确是少了很多样板代码