实时数据中的 Observables 更新在片段中不起作用
Posted
技术标签:
【中文标题】实时数据中的 Observables 更新在片段中不起作用【英文标题】:Observables updates in the live data dont working in fragment 【发布时间】:2021-06-25 07:04:46 【问题描述】:我有一个片段实例化一个由koin注入的视图模型,问题是,在视图模型的postValue()动作之后,观察到的属性之一没有在片段中激发,它根本没有进入方法片段中,即使它已被更新。
片段:
class ListFragment : Fragment()
private lateinit var adapter: PostAdapter
private val viewModel: PostsViewModel by viewModel()
private var _binding: ListFragmentBinding? = null
private var defaultTopic = "news"
private var afterPage: String = ""
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View?
return inflater.inflate(R.layout.list_fragment, container, false)
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
super.onViewCreated(view, savedInstanceState)
_binding = ListFragmentBinding.bind(view)
adapter = PostAdapter(mutableListOf(), requireContext())
val action = ListFragmentDirections.openDetailsFragment(it)
findNavController().navigate(action)
_binding?.let
val llm = LinearLayoutManager(requireContext())
it.recyclerviewPosts.layoutManager = llm
it.recyclerviewPosts.adapter = adapter
recyclerViewListenerSetup(it, llm)
setupObservers()
private fun recyclerViewListenerSetup(it: ListFragmentBinding, llm: LinearLayoutManager)
it.recyclerviewPosts.addOnScrollListener(object : RecyclerView.OnScrollListener()
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int)
super.onScrolled(recyclerView, dx, dy)
val visibleItemCount: Int = llm.childCount
val totalItemCount: Int = llm.itemCount
val firstVisibleItemPosition: Int = llm.findFirstVisibleItemPosition()
if((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
&& firstVisibleItemPosition >= 0)
viewModel.getNextPage(defaultTopic, afterPage)
)
private fun setupObservers()
viewModel.getPostList(defaultTopic)
viewModel.posts.observe(this as LifecycleOwner, posts ->
if (posts.isSuccess && posts.getOrNull() != null)
adapter.updateList(posts.getOrNull()!! as MutableList<PostsDTO>)
afterPage = posts.getOrNull()!![0].after
showList()
else
showError()
)
viewModel.loading.observe(this as LifecycleOwner,
if (it)
showLoading()
else
hideLoading()
)
viewModel.next.observe(this as LifecycleOwner,
if (it.isSuccess && it.getOrNull() != null)
adapter.addList(it.getOrNull() as MutableList<PostsDTO>)
afterPage = it.getOrNull()!![0].after
)
private fun showList()
_binding?.let
it.recyclerviewPosts.visibility = VISIBLE
private fun showLoading()
_binding?.let
it.loading.visibility = VISIBLE
it.containerError.root.visibility = GONE
it.recyclerviewPosts.visibility = GONE
private fun hideLoading()
_binding?.let
it.loading.visibility = GONE
private fun showError()
_binding?.let
it.containerError.root.visibility = VISIBLE
it.recyclerviewPosts.visibility = GONE
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater)
inflater.inflate(R.menu.menu_main, menu)
val searchItem = menu.findItem(R.id.action_search)
val searchManager =
requireActivity().getSystemService(Context.SEARCH_SERVICE) as SearchManager
val searchView = searchItem.actionView as SearchView
searchView.setSearchableInfo(searchManager.getSearchableInfo(activity?.componentName))
searchView.apply
queryHint = "Search SubReddit"
setOnQueryTextListener(object : SearchView.OnQueryTextListener
override fun onQueryTextSubmit(query: String?): Boolean
defaultTopic = query!!
viewModel.getPostList(defaultTopic)
return false
override fun onQueryTextChange(newText: String?): Boolean
return true
)
super.onCreateOptionsMenu(menu, inflater)
我尝试在recyclerView滚动时调用viewmodel方法更新显示的列表。
视图模型:
class PostsViewModel(private val repository: PostsRepository) : ViewModel()
private val _posts = MutableLiveData<Result<List<PostsDTO>>>()
val posts: LiveData<Result<List<PostsDTO>>>
get() =_posts
private val _loading = MutableLiveData<Boolean>()
val loading: LiveData<Boolean>
get() = _loading
private val _next = MutableLiveData<Result<List<PostsDTO>>>()
val next: LiveData<Result<List<PostsDTO>>>
get() =_posts
fun getPostList(q: String)
viewModelScope.launch
_loading.postValue(true)
repository.fetchPosts(q)
.collect
_posts.value = it
_loading.postValue(false)
fun getNextPage(topic: String, afterPage: String)
viewModelScope.launch
repository.fetchNextPage(topic, afterPage)
.collect
_next.postValue(it)
这种情况下next方法的请求结果更新完viewmodel后,viewmodel.next.observer()中就不会激发fragment
【问题讨论】:
这可能是视图模型的生命周期所有者的原因,我无法从您的代码中弄清楚。您可以将活动作为 viewmodel 生命周期所有者仅用于测试。 【参考方案1】:奥帕!经过单元测试后,我能够找出问题所在,问题是 ctrl + v,下一个属性,它返回的是 _post 属性而不是 _next 属性,因此视图没有收到更新通知。 更正的修正是在viewmodel中,改变下一个变量的get方法:
private val _next = MutableLiveData<Result<List<PostsDTO>>>()
val next: LiveData<Result<List<PostsDTO>>>
get() =_next
【讨论】:
以上是关于实时数据中的 Observables 更新在片段中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
当 Firestore 字段更新时,Observables 会重新查询所有数据吗?