【问题标题】:How to send values from fragment to viewmodel (Repository)?如何将值从片段发送到视图模型(存储库)?
【发布时间】:2021-07-23 20:25:58
【问题描述】:

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

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 是我必须传递给存储库的值,以便我可以获取所选值对的值。

存储库代码 -

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**")
    }
}

【问题讨论】:

    标签: android kotlin android-fragments android-livedata android-mvvm


    【解决方案1】:

    我没有专门使用Kodein,但我已经使用Dependency InjectionMVVM 使用KoinDagger Hilt,所以这里的基本思想应该仍然保持不变。

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

    片段

    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)
    }
    

    视图模型

    class MyVm(
     private val repository: Repository          // inject respository
    ): ViewModel() {
    
        fun doSomething(value: String) {
    
             viewModelScope.launch {
             repository.fetchNameValue(value)
             }
        }
    }
    

    存储库

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

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

    【讨论】:

    • 了解,问题在于存储库无法从 viewModel 获取值。感谢您的解决方案!
    • 很高兴听到您找到了解决方案! :)
    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多