使用MVVM+Coroutines将"实时数据库"值获取到ArrayList



我想使用协程和MVVM从实时数据库中获得一个数据列表,并将它们放在recycleview中。它运行,但来自实时数据库的数据是在recycleriew.adapter初始化后添加的,因此将list.size返回0

ViewModel.kt

class DasarhukumdetailsViewModel : ViewModel() {
val database = FirebaseDatabase.getInstance().reference
var dasarHukumList = ArrayList<DasarHukum>()
fun getDHData(KEYVALUE: String?) = liveData(Dispatchers.Main.immediate) {
val postListener = object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
for (snapshot in snapshot.children) {
val res = snapshot.getValue(DasarHukum::class.java)
Log.d("dataAdd", "Adding: ${res?.filename}")
dasarHukumList.add(res!!)
}
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed, log a message
Log.w("readDHList", "loadPost:onCancelled", databaseError.toException())
throw databaseError.toException()
}
}
try {
if (KEYVALUE != null) {
database.child("dasarhukum").child(KEYVALUE).addValueEventListener(postListener)
}
emit(Resource.success(dasarHukumList))
} catch (e: Exception) {
emit(Resource.error(
null,
e.message ?: "Unknown Error"
))
}
}

碎片.kt

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
[...]
observerSetup(KEYVALUE)
rvSetup()
return binding.root
}
fun observerSetup(keyvalue: String?) {
viewModel.getDHData(keyvalue).observe(viewLifecycleOwner, {
when (it.status) {
Status.SUCCESS -> {
it?.data.let { dhList ->
dasarHukumAdapter.dasarhukumList = dhList
dasarHukumAdapter.notifyDataSetChanged()
}
}
Status.ERROR -> {
Toast.makeText(context, "Error getting documents: ${it.message}", Toast.LENGTH_LONG)
Log.e("realDB", it.message!!)
}
}
})
}
fun rvSetup() {
with(binding.rvDasarHukum) {
layoutManager = LinearLayoutManager(context)
setHasFixedSize(true)
adapter = dasarHukumAdapter
}
}

RVAdapter.kt

class DasarHukumAdapter : RecyclerView.Adapter<DasarHukumAdapter.DasarHukumViewHolder>() {
var dasarhukumList: List<DasarHukum>? = null
set(value) {
notifyDataSetChanged()
field = value
}
class DasarHukumViewHolder(private val binding: ItemDasarhukumBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(dasarHukum: DasarHukum?) {
binding.dasarhukum = dasarHukum
binding.executePendingBindings()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DasarHukumViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ItemDasarhukumBinding.inflate(layoutInflater, parent, false)
return DasarHukumViewHolder(binding)
}
override fun onBindViewHolder(holder: DasarHukumViewHolder, position: Int) {
val dasarHukum = dasarhukumList?.get(position)
Log.d("dhVH", "Adding: ${dasarHukum?.name}")
holder.bind(dasarHukum)
}
override fun getItemCount(): Int {
Log.d("dhCount", "List size: ${dasarhukumList?.size}")
return dasarhukumList?.size ?: 0
}

回收视图如何等待viewmodel.getDHData((先返回arraylist,然后初始化,以便将其显示给回收视图?

当您尝试使用以下代码行发出结果时:

emit(Resource.success(dasarHukumList))

数据尚未完成加载,因此列表的大小为零。Firebase API是异步的,因此您需要等待数据才能在另一个操作中使用它。因此,任何需要来自实时数据库的数据的代码都需要在";onDataChange(("方法,或者从那里调用。因此,在这种情况下,最简单的解决方案是在回调中移动关于发出结果的逻辑:

fun getDHData(KEYVALUE: String?) = liveData(Dispatchers.Main.immediate) {
val postListener = object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
for (snapshot in snapshot.children) {
val res = snapshot.getValue(DasarHukum::class.java)
Log.d("dataAdd", "Adding: ${res?.filename}")
dasarHukumList.add(res!!)
}
try {
if (KEYVALUE != null) {
database.child("dasarhukum").child(KEYVALUE).addValueEventListener(postListener)
}
emit(Resource.success(dasarHukumList))
} catch (e: Exception) {
emit(Resource.error(
null,
e.message ?: "Unknown Error"))
}
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed, log a message
Log.w("readDHList", "loadPost:onCancelled", databaseError.toException())
throw databaseError.toException()
}
}
}

最新更新