使用Retrofit2+OkHttp3请求API后如何将XML布局迁移至Jetpack Compose
Jetpack Compose 实现电影卡片列表方案
1. 前置依赖添加
在模块级build.gradle的dependencies块中添加Coil图片加载依赖,用于替代原Glide的图片加载逻辑:
implementation "io.coil-kt:coil-compose:2.5.0"
2. 重构MainActivity代码
移除原XML相关的布局绑定、RecyclerView逻辑,新增可观察状态持有网络请求返回的数据,Compose会自动根据状态变化刷新界面:
class MainActivity : AppCompatActivity() { // 存储电影列表的可观察状态 private val movieList = mutableStateListOf<Result>() // 加载状态的可观察状态 private val isLoading = mutableStateOf(true) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MovieSpotterTheme { Box(modifier = Modifier.fillMaxSize()) { // 加载中显示进度条 if (isLoading.value) { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } else { // LazyColumn替代原RecyclerView LazyColumn(modifier = Modifier.fillMaxSize()) { items(movieList) { movie -> MovieItem(movie = movie) } } } } } } val request = ServiceBuilder.buildService(TmdbEndpoints::class.java) val call = request.getMovies(getString(R.string.api_key)) call.enqueue(object : Callback<PopularMovies>{ override fun onResponse(call: Call<PopularMovies>, response: Response<PopularMovies>) { if (response.isSuccessful){ isLoading.value = false response.body()?.results?.let { movieList.addAll(it) } } } override fun onFailure(call: Call<PopularMovies>, t: Throwable) { isLoading.value = false Toast.makeText(this@MainActivity, t.message.orEmpty(), Toast.LENGTH_SHORT).show() } }) } }
3. 实现电影卡片组件(替代原movie_item.xml和ViewHolder逻辑)
直接通过Compose的布局组合实现原RelativeLayout的效果,不需要参考ConstraintLayout的迁移方案:
@Composable fun MovieItem(movie: Result) { Card( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 8.dp), elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) ) { Row(modifier = Modifier.padding(12.dp)) { // 左侧电影海报 AsyncImage( model = "https://image.tmdb.org/t/p/w500${movie.poster_path}", contentDescription = movie.title, modifier = Modifier .width(120.dp) .height(180.dp) .clip(RoundedCornerShape(8.dp)), placeholder = painterResource(R.drawable.space_dog_laika1), error = painterResource(R.drawable.space_dog_laika1) ) // 右侧文本信息 Column( modifier = Modifier .padding(start = 16.dp) .align(Alignment.CenterVertically) ) { Text( text = "标题:${movie.title}", fontSize = 18.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(bottom = 8.dp) ) Text( text = "用户评分:${movie.vote_average}", fontSize = 14.sp, color = Color(0xFFFF9800), modifier = Modifier.padding(bottom = 8.dp) ) Text( text = movie.overview, fontSize = 13.sp, maxLines = 3, overflow = TextOverflow.Ellipsis, color = Color.Gray ) } } } }
说明
原MoviesAdapter、MoviesViewHolder、activity_main.xml、movie_item.xml全部可以删除,不需要再使用。如果需要调整卡片布局样式,直接修改MovieItem中的Compose布局代码即可,比XML布局灵活性更高。
内容的提问来源于stack exchange,提问作者petestmart
相关产品推荐
相关产品推荐

