gpt4 book ai didi

android - 在 Jetpack Compose 中的 API 响应后更新 LazyColumn

转载 作者:行者123 更新时间:2023-12-05 01:57:37 25 4
gpt4 key购买 nike

我对 Jetpack Compose 和 Kotlin 完全陌生,但对使用 Java 进行 Android 开发并不陌生。想要第一次接触这两种技术,我想制作一个非常简单的应用程序,它使用来自 Dog API 的图像填充 LazyColumn。 .

所有 Retrofit 连接部分工作正常,因为我设法用随机小狗填充了一张卡片,但是当需要填充列表时,这是不可能的。这是发生了什么:

  1. 已创建界面并显示白屏。
  2. API 被调用。
  3. 等待大约 20 秒(大约有 400 张图片!)。
  4. dogImages 会自动更新。
  5. LazyColumn 再也不会重新组合,因此白屏会保持原样。

你有什么想法吗?我找不到关于这个问题的任何教程,只是关于滚动监听状态的模糊解释。

这是我的代码:

class MainActivity : ComponentActivity() {
private val dogImages = mutableStateListOf<String>()

@ExperimentalCoilApi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PuppyWallpapersTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
DogList(dogImages)
searchByName("poodle")
}
}
}
}

private fun getRetrofit():Retrofit {
return Retrofit.Builder()
.baseUrl("https://dog.ceo/api/breed/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}

private fun searchByName(query: String) {
CoroutineScope(Dispatchers.IO).launch {
val call = getRetrofit().create(APIService::class.java).getDogsByBreed("$query/images")
val puppies = call.body()
runOnUiThread {
if (call.isSuccessful) {
val images = puppies?.images ?: emptyList()
dogImages.clear()
dogImages.addAll(images)
}
}
}
}

@ExperimentalCoilApi
@Composable
fun DogList(dogs: SnapshotStateList<String>) {
LazyColumn() {
items(dogs) { dog ->
DogCard(dog)
}
}
}

@ExperimentalCoilApi
@Composable
fun DogCard(dog: String) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(15.dp),
elevation = 10.dp
) {
Image(
painter = rememberImagePainter(dog),
contentDescription = null
)
}
}
}

提前致谢! :)

最佳答案

您的 ImageView 在加载之前无法确定纵横比,并且由于计算出的高度为零,因此不会开始加载。参见 this reply获取更多信息。

还有一些关于您的代码的提示。

  1. MainActivity 中存储状态是不好的做法,您可以使用 view models .在 View 模型中,您可以使用 viewModelScope,它将绑定(bind)到您的屏幕:所有任务都将被取消,屏幕关闭时对象将被销毁。
  2. 您不应像使用 searchByName 那样直接从 View 构造函数进行状态修改调用。这段代码在重构的时候可以调用很多次,所以你的调用会重复。你应该用 side effects 来做到这一点.在这种情况下,您可以使用 LaunchedEffect,但您也可以在 init View 模型中执行此操作,因为它会在您的屏幕出现时创建。
  3. 将 Modifier 作为最后一个参数传递非常方便,在这种情况下您不需要在末尾添加逗号,您可以轻松添加/删除修饰符。
  4. 您可能有很多可组合项,将它们全部存储在 MainActivity 中不是很方便。一个好的做法是将它们简单地存储在一个文件中,并通过文件在逻辑上将它们分开。

您的代码可以更新为以下内容:

class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PuppyWallpapersTheme {
DogsListScreen()
}
}
}
}

@Composable
fun DogsListScreen(
// pass the view model in this form for convenient testing
viewModel: DogsModel = viewModel()
) {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
DogList(viewModel.dogImages)
}
}

@Composable
fun DogList(dogs: SnapshotStateList<String>) {
LazyColumn {
items(dogs) { dog ->
DogCard(dog)
}
}
}

@Composable
fun DogCard(dog: String) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(15.dp),
elevation = 10.dp
) {
Image(
painter = rememberImagePainter(
data = dog,
builder = {
// don't use it blindly, it can be tricky.
// check out https://stackoverflow.com/a/68908392/3585796
size(OriginalSize)
},
),
contentDescription = null,
)
}
}

class DogsModel : ViewModel() {
val dogImages = mutableStateListOf<String>()

init {
searchByName("poodle")
}

private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://dog.ceo/api/breed/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}

private fun searchByName(query: String) {
viewModelScope
.launch {
val call = getRetrofit()
.create(APIService::class.java)
.getDogsByBreed("$query/images")
val puppies = call.body()
if (call.isSuccessful) {
val images = puppies?.images ?: emptyList()
dogImages.clear()
dogImages.addAll(images)
}
}
}
}

关于android - 在 Jetpack Compose 中的 API 响应后更新 LazyColumn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69080824/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com