RecyclerView 仅在方向更改后从 ViewModel 填充数据
RecyclerView only populates data from ViewModel after the orientation changes
我正在使用 NavigationDrawer
并试用 MVVM 架构,所有布局都很好,然后我实现了一个 RecyclerView,它在其中一个片段中显示来自 Firebase 的数据。
未显示任何错误,但 RecyclerView 未填充数据。我向应用程序添加了日志记录,发现适配器 returns 大小,data != null
,但有趣的是 recyclerView
仅在设备配置更改时填充数据,例如设备方向
在片段之间切换并返回到 RecyclerView
片段:再次出现同样的问题,直到我旋转设备
我试过:
将流程与对 onCreateView
的引用分开
将数据源更改为虚拟集,它起作用了
在终端显示数据,并打印数据
HomeFragment
...
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
lateinit var recyclerView: RecyclerView
lateinit var swipeRefresh: SwipeRefreshLayout
lateinit var postAdapter: PostAdapter
val viewModelFactory = HomeViewModelFactory()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_home, container, false)
homeViewModel = ViewModelProviders.of(this, viewModelFactory).get(HomeViewModel::class.java)
recyclerView = view.findViewById(R.id.post_recycler_view)
recyclerView.setHasFixedSize(true)
val linearLayoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, true)
linearLayoutManager.stackFromEnd = true
recyclerView.layoutManager = linearLayoutManager
// Observe the model
homeViewModel.postList.observe(this@HomeFragment, Observer { posts ->
postAdapter = PostAdapter(context!!, posts)
recyclerView.adapter = postAdapter
postAdapter.notifyDataSetChanged()
homeViewModel.myRef.keepSynced(true)
})
swipeRefresh = view.findViewById(R.id.swiperefresh)
swipeRefresh.setOnRefreshListener {
Toast.makeText(context, " Adapter size: ${postAdapter.itemCount}", Toast.LENGTH_LONG).show() // works : returns 12
println("list:${homeViewmodel.postList.value} ") works : prints data
swipeRefresh.isRefreshing = false
}
return view
}
viewModel
class HomeViewModel() : ViewModel() {
var postList = loadPosts()
fun loadPosts(): MutableLiveData<MutableList<Post>> {
val postList = mutableListOf<Post>()
val l_postList = MutableLiveData<MutableList<Post>>()
firebaseRepo.retrievePosts(postList)
l_postList.value = postList
return l_postList
}
}
firebaseRepo
fun retrievePosts(postList: MutableList<Post>) {
val postsRef = ref.child("Posts")
postsRef.addValueEventListener(object : ValueEventListener{
override fun onCancelled(p0: DatabaseError) {}
override fun onDataChange(p0: DataSnapshot) {
postList.clear()
for(snapshot in p0.children){
val post = snapshot.getValue(Post::class.java)
postList.add(post!!)
}
}
})
}
您的 retrievePosts
方法仅更改 postList
中的 MutableList<Post>
,而不是 l_postList
中的 MutableLiveData<MutableList<Post>>
,因此 RecyclerView
永远不会被通知更改。 MutableLiveData
只能检测通过设置其 value
.
发生的变化
您应该更新 retrievePosts
方法以引用 MutableLiveData
并在更改时设置 MutableLiveData
的 value
。
我正在使用 NavigationDrawer
并试用 MVVM 架构,所有布局都很好,然后我实现了一个 RecyclerView,它在其中一个片段中显示来自 Firebase 的数据。
未显示任何错误,但 RecyclerView 未填充数据。我向应用程序添加了日志记录,发现适配器 returns 大小,data != null
,但有趣的是 recyclerView
仅在设备配置更改时填充数据,例如设备方向
在片段之间切换并返回到 RecyclerView
片段:再次出现同样的问题,直到我旋转设备
我试过:
将流程与对
onCreateView
的引用分开
将数据源更改为虚拟集,它起作用了
在终端显示数据,并打印数据
HomeFragment
...
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
lateinit var recyclerView: RecyclerView
lateinit var swipeRefresh: SwipeRefreshLayout
lateinit var postAdapter: PostAdapter
val viewModelFactory = HomeViewModelFactory()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_home, container, false)
homeViewModel = ViewModelProviders.of(this, viewModelFactory).get(HomeViewModel::class.java)
recyclerView = view.findViewById(R.id.post_recycler_view)
recyclerView.setHasFixedSize(true)
val linearLayoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, true)
linearLayoutManager.stackFromEnd = true
recyclerView.layoutManager = linearLayoutManager
// Observe the model
homeViewModel.postList.observe(this@HomeFragment, Observer { posts ->
postAdapter = PostAdapter(context!!, posts)
recyclerView.adapter = postAdapter
postAdapter.notifyDataSetChanged()
homeViewModel.myRef.keepSynced(true)
})
swipeRefresh = view.findViewById(R.id.swiperefresh)
swipeRefresh.setOnRefreshListener {
Toast.makeText(context, " Adapter size: ${postAdapter.itemCount}", Toast.LENGTH_LONG).show() // works : returns 12
println("list:${homeViewmodel.postList.value} ") works : prints data
swipeRefresh.isRefreshing = false
}
return view
}
viewModel
class HomeViewModel() : ViewModel() {
var postList = loadPosts()
fun loadPosts(): MutableLiveData<MutableList<Post>> {
val postList = mutableListOf<Post>()
val l_postList = MutableLiveData<MutableList<Post>>()
firebaseRepo.retrievePosts(postList)
l_postList.value = postList
return l_postList
}
}
firebaseRepo
fun retrievePosts(postList: MutableList<Post>) {
val postsRef = ref.child("Posts")
postsRef.addValueEventListener(object : ValueEventListener{
override fun onCancelled(p0: DatabaseError) {}
override fun onDataChange(p0: DataSnapshot) {
postList.clear()
for(snapshot in p0.children){
val post = snapshot.getValue(Post::class.java)
postList.add(post!!)
}
}
})
}
您的 retrievePosts
方法仅更改 postList
中的 MutableList<Post>
,而不是 l_postList
中的 MutableLiveData<MutableList<Post>>
,因此 RecyclerView
永远不会被通知更改。 MutableLiveData
只能检测通过设置其 value
.
您应该更新 retrievePosts
方法以引用 MutableLiveData
并在更改时设置 MutableLiveData
的 value
。