如何将值从片段发送到视图模型(存储库)?

How to send values from fragment to viewmodel (Repository)?

我正在开发一个基于 MVVM 架构的应用程序,其中我有一个值,用户 select 在我必须在我在 API 调用请求中更新的片段上RepositoryImpl class 使用 LiveData,我该怎么做?

class Fragment1 : ScopedFragment(), KodeinAware {
    override val kodein by closestKodein()
    private val viewModelFactory: Fragment1ViewModelFactory by instance()

    private lateinit var viewModel: Fragment1ViewModel

    private var selected1 = ""
    private var selected2 = ""
    private var selected3 = ""

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment1, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProvider(this, viewModelFactory)
            .get(Fragment1ViewModel::class.java)
        bindUI()
        }

        setSpinner1()
        setSpinner2()

        setButton.setOnClickListener {
            val modalbottomSheetFragment = MyBottomSheetDialogFragment()
            modalbottomSheetFragment.show(parentFragmentManager, modalbottomSheetFragment.tag)
        }

    }

    private fun bindUI() = launch {
        valueContainer.visibility = View.VISIBLE
        val currentValue = viewModel.fragment1
        currentValue.observe(viewLifecycleOwner, Observer {
            if (it == null) return@Observer
            value.text = it.Val
        })
        comboSelected = selected1 + selected2
    }

comboSelected 是我必须传递给存储库的值,以便我可以获取 selected 值对的值。

存储库代码 -

class NameRepositoryImpl(
    private val NameValueDao: NameValueDao,
    private val NameNetworkDataSource: NameNetworkDataSource
) : NameRepository {

    init {
        NameNetworkDataSource.downloadedName.observeForever { newNameValue ->
            persistFetchedNameValue(newNameValue)
        }
    }

    private val value: Flow<NameResponseDB> = NameValueDao.getNameValue()

    override suspend fun getCurrentValue() {
        return withContext(Dispatchers.IO) {
            initNameData()
        }
    }

    override fun getCurrentNameValue(): Flow<NameResponseDB> {
        return value
    }

    private fun persistFetchedNameValue(nameValue: NameResponse) {
        GlobalScope.launch(Dispatchers.IO) {
            NameValueDao.upsert(
                NameResponseDB(
                    valueCode = NameValue.valueCode,
                    nameVal = NameValue.nameVal
                )
            )
        }
    }

    private suspend fun initNameData() {
        if (isFetchNameNeeded(ZonedDateTime.now().minusMinutes(30)))
            fetchNameValue()
    }

    private suspend fun fetchNameValue() {
        NameNetworkDataSource.fetchCurrentValue(valueCode = "**Need the combo Selected Value here**")
        val value = NameNetworkDataSource.fetchCurrentValue(valueCode = "**Need the combo Selected Value here**")
    }
}

我没有具体使用过 Kodein,但我使用过 Dependency InjectionMVVM,使用过 KoinDagger Hilt,所以基本思路应该这里也是一样。

您需要向 viewModel 提供 repository 的实例,并从该函数 fetchNameValue 中删除 private,以便 viewModel 可以调用这个 suspend fun 通过 viewmodelscope。另外,viewModelrepository 不是一回事。您应该单独创建它们的逻辑。所以应该是这样的:

Fragment

private fun bindUI() = launch {
    valueContainer.visibility = View.VISIBLE
    val currentValue = viewModel.fragment1
    currentValue.observe(viewLifecycleOwner, Observer {
        if (it == null) return@Observer
        value.text = it.Val
    })
    comboSelected = selected1 + selected2
    viewModel.doSomething(comboSelected)
}

ViewModel

class MyVm(
 private val repository: Repository          // inject respository
): ViewModel() {

    fun doSomething(value: String) {

         viewModelScope.launch {
         repository.fetchNameValue(value)
         }
    }
}

Repository

class Repository {

    suspend fun fetchNameValue(nameValue: String) {
    NameNetworkDataSource.fetchCurrentValue(valueCode = nameValue)
    val value = NameNetworkDataSource.fetchCurrentValue(valueCode = nameValue)
}
}

如果您仍有疑问,请告诉我,我会尝试更新我的答案:)