【问题标题】:Android Jetpack compose - Observe a live data not trigger after second channgeAndroid Jetpack compose - 观察第二次更改后未触发的实时数据
【发布时间】:2020-10-16 03:01:48
【问题描述】:

我正在使用 viewModel 将数据传递给我的撰写视图。问题是我想通过在 viewModel 中的模型中归档来处理展开和折叠视图。因此,如果某些 UI 点击展开方法,我将调用 viewModel 和 doExpand 方法,如下所示:

 private val _acquiredCoupons = MutableLiveData<List<AcquiredCoupon>>(listOf())
 val acquiredCoupons: LiveData<List<AcquiredCoupon>> = _acquiredCoupons

    fun doExpand(coupon : AcquiredCoupon){
        
        val index = _acquiredCoupons.value?.indexOf(coupon) ?: -1
         val newItems = _acquiredCoupons.value?.toMutableList().also {
            it?.get(index)?.isExpanded = true
        }
        _acquiredCoupons.value = newItems
        Timber.i("Mahdi $index")
    }

但问题是在撰写 UI 中更新模型后不会触发并且重新撰写不会发生! 我正在观察这样的实时数据:

val items = viewModel.acquiredCoupons.observeAsState(initial = emptyList())

【问题讨论】:

  • 你能在你观察livedata的地方显示代码吗?
  • 确保您使用的是by 而不是=
  • 你找到解决办法了吗?
  • @ImMathan 我通过放置新的 stateFlow 解决了它,并且只是观察它而不采取任何行动,并且每次我更新扩展状态时,也会更新该值。这只是对我有用的伎俩。
  • 您能分享一下解决方案吗?谢谢

标签: android kotlin android-jetpack android-jetpack-compose


【解决方案1】:

在您的观察代码中,您需要使用observeAsState,因此您的视图将使用任何更改值的 LiveData 更新来重构。

val items by viewModel.acquiredCoupons.observeAsState()

【讨论】:

  • 是的,我正在使用它,但是在更新后数据更改中的任何值都不会触发!
  • 你能把代码贴在你观察这个实时数据的地方吗?
【解决方案2】:

如果有人在查看列表时仍然遇到此问题,我发现一个很好的解决方案是在 ViewModel/LiveData 中从 List 切换到 SnapshotStateList

从这里转换后:

class MainViewModel : ViewModel() {
    val itemLiveData: LiveData<List<String>>
        get() = items

    private val items = MutableLiveData<List<String>>()
    private val itemImpl = mutableListOf<String>()

    fun addItem(name: String){
        itemImpl.add(name)
        items.postValue(itemImpl)
    }
}

到这个表格:

class MainViewModel : ViewModel() {
    val itemLiveData: LiveData<SnapshotStateList<String>>
        get() = items

    private val items = MutableLiveData<SnapshotStateList<String>>()
    private val itemImpl = mutableStateListOf<String>()

    fun addItem(name: String){
        itemImpl.add(name)
        items.postValue(itemImpl)
    }
}

当项目被添加到列表中时,我的可组合项按预期工作

@Composable
fun ItemList(model: MainViewModel = viewModel()) {
    Column {
        Button( 
            onClick = { model.addItem("New item") },
            content = { Text(text="Add item") } 
        )
                
        val items by model.itemLiveData.observeAsState()

        if( items.isNullOrEmpty() ) {
            Text(text = "No items")
        }
        else {
            items?.forEach { item ->
                Text(text=item)
            }
        }
    }
}

【讨论】:

    【解决方案3】:

    问题很可能是您将原始值传递给Composable(如果有机会,请在您的问题中包含一个示例 sn-p)。如果该值被认为等于之前的值,则不会发生重组。

    解决此问题的一种方法是将State 对象本身传递给目标Composable

    例如,如果您是这样设置的:

    @Composable
    fun CouponBar(
        coupons: List<Coupon>
    ) { ... }
    

    那就试试

    @Composable
    fun CouponBar(
        coupons: State<List<Coupon>>
    ) { ... }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-03
      • 2020-02-01
      • 1970-01-01
      • 2023-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多