使用底部导航 android kotlin 在片段中实现 MVVM 的最佳实践
Best practice to implement MVVM in fragment using Bottom navigation android kotlin
我正在使用带 firebase 的底部导航在片段中实现 MVVM。但这对我来说不起作用。我搜索了很多解决方案,但没有解决我的问题。
我在片段中实现了 viewModel 并将观察者应用于它。在 ViewModel class 中,使用 return 从存储库中键入 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
}
Fragment.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()
})
}
不确定这是否会为您解决问题,但如果您正在使用 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
}
我正在使用带 firebase 的底部导航在片段中实现 MVVM。但这对我来说不起作用。我搜索了很多解决方案,但没有解决我的问题。
我在片段中实现了 viewModel 并将观察者应用于它。在 ViewModel class 中,使用 return 从存储库中键入 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
}
Fragment.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()
})
}
不确定这是否会为您解决问题,但如果您正在使用 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
}