我有一个片段,它实例化了一个由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方法来更新显示的列表。
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)
}
}
}
}在这种情况下,在下一个方法的请求结果更新了视图模型之后,片段不会在viewmodel.next.observer()中被激发
发布于 2021-03-29 19:49:04
啊!在一次单元测试之后,我找到了问题所在,问题出在ctrl + v,也就是下一个属性,它返回的是_post属性,而不是_next属性,所以视图没有收到更新的通知。更正更正在视图模型中,更改了下一个变量的get方法:
private val _next = MutableLiveData<Result<List<PostsDTO>>>()
val next: LiveData<Result<List<PostsDTO>>>
get() =_nexthttps://stackoverflow.com/questions/66851035
复制相似问题