Observables updates in the live data dont working in fragment

Viewed 323

I have one fragment that instance that instantiates a view model injected by koin, the problem is that, one of the observed attributes are not stimulated in the fragment after the view model's postValue () action, it simply does not enter the method in the fragment even though it has been updated.

Fragement:

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)
}

}

I try to call the viewmodel method to update the displayed list when the recyclerView scrolls.

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)
                }
    }
}

 }

In this case after the request result of the next method has updated the viewmodel, the fragment is not stimulated in viewmodel.next.observer()

1 Answers

OPAH! after a unit test I was able to find out what the problem was, the problem was ctrl + v, the next property, it was returning the _post property and not the _next property, so the view was not notified of the update. The correction the correction was in the viewmoldel, changing the get method of the next variable:

private val _next = MutableLiveData<Result<List<PostsDTO>>>()
val next: LiveData<Result<List<PostsDTO>>>
    get() =_next
Related