如何在Kotlinjetpack compose中创建singleton对象并用于UI和viewmodel两个屏幕?

qgelzfjb  于 7个月前  发布在  Kotlin
关注(0)|答案(2)|浏览(86)

我有一个这样的清单

data class SelectedNtrItem(
        val items:ArrayList<NutritionSearchItem> = arrayListOf()
    )

字符串
我需要在两个可组合的屏幕上使用这个列表,所以我需要访问它的一个示例。我的想法是用singelton创建它,并在UI和Viewmodel端使用它,但我不能完全做到这一点。

class SelectedNtrItemManager {
    companion object{
        private val _selectedNtrItem = MutableStateFlow(SelectedNtrItem())
        val selectedNtrItem: StateFlow<SelectedNtrItem> = _selectedNtrItem.asStateFlow()
    }
}


这是我作为singelton创建的类。我如何在两个可组合屏幕的viewmodel和UI端使用它,也就是说,我如何在两个屏幕的UI端和viewmodel端作为单个对象访问这个列表,因为我需要相同的列表?

@Composable
fun FirstScreen(
    navHostController: NavHostController,
    viewModel: FirstScreenViewModel = hiltViewModel()
) {
...

@HiltViewModel
class FirstScreenViewModel @Inject constructor(
       .... ) : ViewModel() { ....
@Composable
fun SecondScreen(
    navHostController: NavHostController,
    viewModel: SecondScreenViewModel = hiltViewModel()
) {
...

@HiltViewModel
class SecondScreenViewModel @Inject constructor(
       .... ) : ViewModel() { ....

的字符串

已解决

我解决了下面的问题:

object SelectedNtrItemManager {

    var selectedItems =  SnapshotStateList<NutritionSearchItem>()

    fun addItem(item: NutritionSearchItem) {
        selectedItems.add(item)
    }

    fun removeItem(item: NutritionSearchItem) {
        selectedItems.remove(item)
    }
}

FirstScreen VM:

val selectedItems: SnapshotStateList<NutritionSearchItem>
        get() = SelectedNtrItemManager.selectedItems

  fun addSelectedNutritionItem(
       ntrItem: NutritionSearchItem
   ) {
       if (selectedItems.contains(ntrItem)) {
           SelectedNtrItemManager.removeItem(ntrItem)
       } else {
           SelectedNtrItemManager.addItem(ntrItem)
       }
   }

SecondScreen VM

class SecondScreenVM : ViewModel() {

    val list: SnapshotStateList<NutritionSearchItem>
        get() = SelectedNtrItemManager.selectedItems

    fun deleteItemFromList(item: NutritionSearchItem) {
        SelectedNtrItemManager.removeItem(item)
    }
}

秒屏界面:

val list = viewModel.list
  LazyColumn(modifier = Modifier.padding(15.dp)) {
                items(list) { item ->....


为了检测我所做的更改,我使用了SnapshotStateList。SnapshotStateList检测何时有更改并通知侦听器,我像上面一样更新了我的SelectedNtrItemManager,它工作得很好。

fjaof16o

fjaof16o1#

您需要按如下所示创建ViewModel,并将其作为参数传递给相关屏幕。

private val sharedViewModel by viewModels<SharedViewModel>()

@Composable
fun FirstScreen(
    viewModel: SharedViewModel
) {
}

@Composable
fun SecondScreen(
    viewModel: SharedViewModel
) {
}

字符串

aor9mmx1

aor9mmx12#

我会把数据对象放到某种Repository类中,这个类会被注入到你的两个ViewModel中。在那里你可以把它作为一个流收集,然后把它收集到你的Composable中。

class Repository {

    val itemListFlow = MutableSharedFlow<SelectedNtrItem>()

}

class FirstScreenViewModel(repository: Repository): ViewModel() {

    val itemListFlow = repository.itemListFlow.stateIn(viewModelScope, SharingStarted.Eagerly, null)

}

@Composable
fun FirstScreen(
    navHostController: NavHostController,
    viewModel: FirstScreenViewModel = hiltViewModel()
) {
    val list by viewModel.itemListFlow.collectAsState()
}

class SecondScreenViewModel(repository: Repository): ViewModel() {

    val itemListFlow = repository.itemListFlow.stateIn(viewModelScope, SharingStarted.Eagerly, null)

}

@Composable
fun SecondScreen(
    navHostController: NavHostController,
    viewModel: FirstScreenViewModel = hiltViewModel()
) {
    val list by viewModel.itemListFlow.collectAsState()
}

字符串

相关问题