首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实时数据中的可观察性更新在片段中不起作用

实时数据中的可观察性更新在片段中不起作用
EN

Stack Overflow用户
提问于 2021-03-29 16:37:03
回答 1查看 70关注 0票数 3

我有一个片段,它实例化了一个由koin注入的视图模型,问题是,在视图模型的postValue ()操作之后,其中一个观察到的属性并没有在片段中被激发,它只是没有进入片段中的方法,即使它已经更新了。

欺诈:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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()中被激发

EN

回答 1

Stack Overflow用户

发布于 2021-03-29 19:49:04

啊!在一次单元测试之后,我找到了问题所在,问题出在ctrl + v,也就是下一个属性,它返回的是_post属性,而不是_next属性,所以视图没有收到更新的通知。更正更正在视图模型中,更改了下一个变量的get方法:

代码语言:javascript
复制
private val _next = MutableLiveData<Result<List<PostsDTO>>>()
val next: LiveData<Result<List<PostsDTO>>>
    get() =_next
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66851035

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档