在可组合函数之外更新状态。 (喷气背包组合)

Update State outside the composable function. (Jetpack compose)

我正在尝试使用 Jetpack compose 实现 redux。场景如下所示:

我有一个列表视图,需要在可组合函数中显示数据。

    @Composable
    fun CreateListView(text: String) {
     val listdata = state { store.state }

        LazyColumn {
         //some listview code here
        }
    }

以上,我想使用从 redux store 获取的数据。但商店。订阅方法是独立的,在可组合项之外。其中,虽然我能够通过新数据更新状态,但更改不会反映回可组合列表视图:

    // activity page outside composable
    private fun storeSubscription(){
        viewModel.storeSubscription = store.subscribe {

            when (store.state) {
                store.state = // list data from some source
            }
        }
    }

是否可以像上面那样从函数外部更新可组合项,而不发送任何参数?由于 redux 商店是全球商店,所以我认为它应该可以工作。

您必须遵循状态托管模式 来自 Android Domcumentaiton

Key Term: State hoisting is a pattern of moving state up the tree to make a component stateless.

When applied to composables, this often means introducing two parameters to the composable:

value: T: the current value to display. onValueChange: (T) -> Unit: an event that requests the value to change where T is the proposed new value.

所以在你的情况下,你会将状态保存在需要访问它的上层Composable中,并通过状态的值和一个lambda函数将其更改为另一个Composable,你可以从官方了解更多文档。

尝试类似的东西,

@Composable
fun <T> Store<T>.asState(): State<T> {
   val result = remember { mutableStateOf(store.state) }
   DisposableEffect {
       val unsubscribe = store.subscribe {
           result.value = store.state
       }
       onDispose { unsubscribe() }
   }
   return result
}

@Composable
fun CreateListView(text: String) {
    val listdata by store.asState()

    LazyColumn {
     //some listview code here
    }
}

确切的代码可能有所不同,因为我不知道您使用的是什么 redux 实现。

这将创建一个可观察的状态对象,只要传递给 subscribe 的 lambda 被调用,该对象就会更新。此外,当 CreateListView 不再是作品的一部分时,它将自动取消订阅。

您可以在可组合函数之外使用 MutableLiveData。在可组合项中使用 observeAsState() 以在数据更改时重新组合。

private val myLive = MutableLiveData<String>()

fun nonComposableScope(){
  myLive.postValue("hello")
}

@Composable
fun MyScreen(textLive:LiveData<String>){
  val text: String? by textLive.observeAsState()
  // use text here
}