我的LazyColumn没有重新组合,但值正在更新.
如果我向下滚动列表并向上滚动,我会看到UI的正确值
主要活动
class 主要活动 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyTheme {
MyApp()
}
}
}
}
// Start building your app here!
@Composable
fun MyApp(vm: PuppyListViewModel = viewModel()) {
val puppers by vm.pups.collectAsState(emptyList())
Surface(color = MaterialTheme.colors.background) {
Column {
Toolbar()
LazyColumn {
items(puppers) { pup -> PuppyUI(pup, vm::seeDetails, vm::togglePuppyAdoption) }
}
}
}
}
The ViewModel
class PuppyListViewModel : ViewModel() {
val pups = PuppyRepo.getPuppies().onEach {
println("FlowEmitted: $it")
}
fun togglePuppyAdoption(puppy: Puppy) = viewModelScope.launch {
PuppyRepo.toggleAdoption(puppy.id)
}
fun seeDetails(puppy: Puppy) {
println("seeDetails $puppy")
}
}
该模型
internal var IDS = 0L
data class Puppy (
val name: String,
val tagline: String = "",
val race: String,
@DrawableRes val image: Int,
var adopted: Boolean = false,
val id: Long = ++IDS,
)
The repository
object PuppyRepo {
private val changeFlow = MutableStateFlow(0)
private val pups: List<Puppy>
private val puppyImages = listOf(
R.drawable._1,
R.drawable._2,
R.drawable._3,
R.drawable._4,
R.drawable._5,
R.drawable._6,
R.drawable._7,
R.drawable._8,
R.drawable._9,
R.drawable._10,
R.drawable._11,
R.drawable._12,
R.drawable._13,
R.drawable._14,
R.drawable._15,
R.drawable._16,
R.drawable._17,
R.drawable._18,
R.drawable._19,
)
private val puppyNames = listOf(
"Gordie",
"Alice",
"Belle",
"Olivia",
"Bubba",
"Pandora",
"Bailey",
"Nala",
"Rosco",
"Butch",
"Matilda",
"Molly",
"Piper",
"Kelsey",
"Rufus",
"Duke",
"Ozzy"
)
private val puppyTags = listOf(
"doggo",
"doge",
"special dogo",
"wrinkler",
"corgo",
"shoob",
"puggo",
"pupper",
"small dogo",
"big ol dogo",
"woofer",
"floofer",
"yapper",
"pupper",
"good-boye",
"grizlord",
"snip-snap dogo"
)
private val puppyBreeds = listOf(
"Labrador Retriever",
"German Shepard",
"Golden Retriever",
"French Bulldog",
"Bulldog",
"Beagle",
"Poodle",
"Rottweiler",
"German Shorthaired Pointer",
"Yorkshire Terrier",
"Boxer"
)
init {
pups = puppyImages.map { image ->
val name = puppyNames.random()
val tagline = puppyTags.random()
val breed = puppyBreeds.random()
Puppy(name, tagline, breed, image)
}
}
@OptIn(ExperimentalCoroutinesApi::class)
fun getPuppies() = changeFlow.flatMapLatest { flowOf(pups) }
fun getPuppy(puppyId: Long) = flow {
emit(pups.find { it.id == puppyId })
}
suspend fun toggleAdoption(puppyId: Long): Boolean {
val found = getPuppy(puppyId).first()?.toggleAdoption()?.let { true } ?: false
if (found) {
// Trigger a new emission for those that are consuming a Flow from getPuppies
changeFlow.value = changeFlow.value + 1
}
return found
}
private fun Puppy.toggleAdoption() {
adopted = !adopted
}
}
正如你在我的日志(log)中看到的,Flow
只幼崽正在产生更新的值
I've put print statements on my composables and they are not getting re-composed after the flow emits a new value.
Edit.
Lookslike Compose compares the references of the objects and since those didn't change, recomposition didn't happen even if flows were emitting new values (a bug on Compose perhaps?)
更改了toggle
功能以重新创建列表元素的实例,如下所示,现在正在运行.
Note:我把Puppy.adopted
改成了val
suspend fun toggleAdoption(puppyId: Long): Boolean {
var found = false
pups = pups.map {
val isThePuppy = it.id == puppyId
found = found || isThePuppy
if(isThePuppy) it.copy(adopted = !it.adopted) else it.copy()
}
if (found) {
// Trigger a new emission for those that are consuming a Flow from getPuppies
changeFlow.value = changeFlow.value + 1
}
return found
}