【问题标题】:Best practice to implement MVVM in fragment using Bottom navigation android kotlin使用底部导航android kotlin在片段中实现MVVM的最佳实践
【发布时间】:2021-09-24 10:49:51
【问题描述】:

我正在使用带有 firebase 的底部导航在片段中实现 MVVM。但在我的情况下它不起作用。我搜索了很多解决方案,但没有解决我的问题。

我在片段中实现了 viewModel 并对其应用了观察者。在 ViewModel 类中,使用来自存储库的返回类型 LiveData 调用方法(从 firebase 获取数据)。

我正在使用这些依赖项

依赖

//    Fragment Navigation using JetPack
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'

Repository.kt


    // Get emergency requests
    fun getEmergencyRequests(): LiveData<MutableList<EmergencyRequests>> {
        val mutableData = MutableLiveData<MutableList<EmergencyRequests>>()

        val requestListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                if (dataSnapshot.exists() && dataSnapshot.hasChildren()) {

                    // Get Post object and use the values to update the UI
                    val listData = mutableListOf<EmergencyRequests>()

                    for (snapshot in dataSnapshot.children) {
                        val model = snapshot.getValue(EmergencyRequests::class.java)

                        model?.let {
                            model.requestId = snapshot.ref.key.toString()
                            listData.add(it)
                        }
                    }

                    listData.sortByDescending { it.timestamp }
                    mutableData.value = listData


                }
            }

            override fun onCancelled(error: DatabaseError) {
                Log.e("EMERGENCIES_FAIL", error.message)
            }

        }

        emergencyRequestRef?.addValueEventListener(requestListener)

        return mutableData
    }

ViewModel.kt

private val repository: HomeRepository = HomeRepository()

    fun getRequests(): LiveData<MutableList<EmergencyRequests>> {
        repository.getEmergencyRequests()
        val mutableData = MutableLiveData<MutableList<EmergencyRequests>>()
        repository.getEmergencyRequests().observeForever {
            mutableData.value = it
        }
        return mutableData
    }

片段.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

//        Initialize
        initialization()

//        Recyclerview
        binding.recyclerView.layoutManager = LinearLayoutManager(mContext)
        adapter = EmergenciesAdapter(mContext,  object : OnRequestClick {
            override fun onClick(model: EmergencyRequests) {

            }
        })
        binding.recyclerView.adapter = adapter

//        Get emergencies
//        getEmergencies()
        viewModel = ViewModelProvider(mContext).get(HomeViewModel::class.java)


        observer()

    }

    private fun observer() {
        viewModel.getRequests().observe(viewLifecycleOwner, {
            adapter.setDataList(it)
            adapter.notifyDataSetChanged()
        })
    }

【问题讨论】:

  • 您好,您想解决问题还是底部导航的最佳实践?
  • 如果通过最佳实践解决,对我来说是最好的
  • 既然你说解决了,那是什么问题呢?
  • 片段总是重新创建,我只想创建第一次片段,每当我去访问它不应该重新创建的片段时,它必须保存它们的状态

标签: android kotlin mvvm viewmodel bottomnavigationview


【解决方案1】:

不确定这是否会为您解决问题,但如果您使用 bottom navigation view 并希望 fragments 为访问过的目的地维护 backstack,那么使用此版本的 Navigation dependency 您可以保存backstacks 自动使用这些Navigation dependencies:

implementation 'androidx.navigation:navigation-fragment-ktx:2.4.0-alpha01'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.0-alpha01'

更新

在您的存储库中,您能否取回数据?因为该函数可能在从 firebase 获取数据之前返回。我建议像这样重构它:

Repository.kt

private val _data: MutableLiveData<MutableList<EmergencyRequests>> = MutableLiveData()

val data: LiveData<MutableList<EmergencyRequests>> get() = _data

// Get emergency requests
fun getEmergencyRequests() {

    val requestListener = object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            if (dataSnapshot.exists() && dataSnapshot.hasChildren()) {

                // Get Post object and use the values to update the UI
                val listData = mutableListOf<EmergencyRequests>()

                for (snapshot in dataSnapshot.children) {
                    val model = snapshot.getValue(EmergencyRequests::class.java)

                    model?.let {
                        model.requestId = snapshot.ref.key.toString()
                        listData.add(it)
                    }
                }

                listData.sortByDescending { it.timestamp }
                _data.value = listData


            }
        }

        override fun onCancelled(error: DatabaseError) {
            Log.e("EMERGENCIES_FAIL", error.message)
        }

    }

    emergencyRequestRef?.addValueEventListener(requestListener)
}

ViewModel.kt

private val repository: HomeRepository = HomeRepository()

fun getRequests(): LiveData<MutableList<EmergencyRequests>> {
    repository.getEmergencyRequests()
    
    return repository.data
}

【讨论】:

  • 不需要修改fragment和viewModel类?
  • fragment 仍应从 viewmodel 获取 livedata,我将更新我的答案并为 viewmodel 添加代码:)
  • 好的,我在等你的答复。提前致谢
  • 感谢您的回答。它现在正在工作。你为我节省了很多时间。
  • 如果它为您解决了所有问题并且您没有更多疑问,请将其标记为您的问题的已接受答案:)
猜你喜欢
  • 2019-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-26
  • 2017-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多