AnswerBun.com

Android: LiveData postValue() getting null

Stack Overflow Asked by efoc on September 28, 2020

I am trying to transfer a value from one LiveData (Repository.getMovieList(editTextContent.value.toString()).value) to another LiveData (this.movieList.postValue) using postValue().

I am observing the movieList and want to change it’s value from the Repo depending on different buttons that were clicked but I when it runs, it only gets the null value and doesn’t wait till the Repo’s LiveData gets their value.

Fragment xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="viewmodel"
            type="com.example.movieapp.ui.search.SearchMovieFragmentViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".ui.search.SearchMovieFragment">

        <EditText
            android:id="@+id/search_movie_edit_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={viewmodel.editTextContent}"
            android:inputType="text"
            android:hint="Movie Name" />

        <Button
            android:id="@+id/search_fragment_search_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Search"
            android:onClick="@{() -> viewmodel.getMovieSearchList()}"/>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/search_movie_fragment_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>
</layout>

SearchMovieFragment

class SearchMovieFragment : Fragment(), MovieSearchItemViewModel {

    companion object {
        fun newInstance() = SearchMovieFragment()
    }

    private lateinit var searchMovieFragmentViewModel: SearchMovieFragmentViewModel
    private lateinit var binding: SearchMovieFragmentBinding
    private lateinit var movieRecyclerView: RecyclerView

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        binding = DataBindingUtil.inflate(inflater, R.layout.search_movie_fragment, container, false)
        searchMovieFragmentViewModel = ViewModelProvider(this).get(SearchMovieFragmentViewModel::class.java)
        binding.lifecycleOwner = this
        binding.viewmodel = searchMovieFragmentViewModel

        setUpRecyclerView(container!!.context)
        return binding.root
    }

    private fun setUpRecyclerView(context: Context) {
        movieRecyclerView = binding.searchMovieFragmentRecyclerView.apply {
            this.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
        }
        val adapter = MovieListAdapter()
        adapter.setCallback(this)
        binding.searchMovieFragmentRecyclerView.adapter = adapter

        searchMovieFragmentViewModel.getMovieListLiveData().observe(viewLifecycleOwner, Observer {movieList ->
            adapter.submitList(movieList)
        })
    }

}

SearchMovieViewModel

class SearchMovieFragmentViewModel : ViewModel() {

    val editTextContent = MutableLiveData<String>()
    var movieList: MutableLiveData<List<Movie>> =  MutableLiveData()

    fun getMovieSearchList(){
        this.movieList.postValue(Repository.getMovieList(editTextContent.value.toString()).value)
    }

    fun getTrendingMovies() {
        movieList.postValue(Repository.getTrendingMovies().value)
    }

    fun getMovieDetail(movieId: String): MutableLiveData<Movie> {
        return Repository.getMovieDetail(movieId)
    }

    fun getMovieListLiveData() : LiveData<List<Movie>> {
        return movieList
    } 

    private fun getMovieList(movieSearch: String): MutableLiveData<List<Movie>> = Repository.getMovieList(movieSearch)

}

One Answer

I think you are implementing it the wrong way, Instead, using the MediatorLiveData will be a good and practical solution as it allows you to observe multiple LiveData objects and select between them based on your preferences (a specific action for example).

This is an example of how to implement it in your case

    val editTextContent = MutableLiveData<String>()

    val finalList = MediatorLiveData<List<Movie>>()

    // Here.. Define all of your LiveData objects
    private val movieList = repository.getMovieList(editTextContent.value.toString())
    private val trendingMovies = repository.getTrendingMovies()
    private val movieDetail = repository.getMovieDetail()

    fun setSelection(selection: String) {
        finalList.addSource(movieList) { result ->
            if (selection == "movieList") {
                result?.let { finalList.value = it }
            }
        }
        finalList.addSource(trendingMovies) { result ->
            if (selection == "trendingMovies") {
                result?.let { finalList.value = it }
            }
        }
        finalList.addSource(movieDetail) { result ->
            if (selection == "movieDetail") {
                result?.let { finalList.value = it }
            }
        }
    }

So what you have to do is to only observe the MediatorLiveData and then call the setSelection function and send the correspondent selection action to it as a parameter and it will switch the observation to another LiveData

Answered by Hamza Sharuf on September 28, 2020

Add your own answers!

Related Questions

from and to ranges in mysql

2  Asked on January 8, 2021 by rae-ian

       

Can’t activate workbook by variable

1  Asked on January 8, 2021 by rainbowthug

   

C++17 static template lazy evaluation

4  Asked on January 8, 2021 by gcalin

     

Docker images and modules

0  Asked on January 8, 2021 by stavros-koureas

         

Rotating and moving object (follow into mouse) – Javascript

0  Asked on January 8, 2021 by karlos-margaritos

 

Method scrollToItemAtIndexPath is not working on iOS 14

3  Asked on January 7, 2021 by david-vittori

       

Adding horizontal gradient to borderline

1  Asked on January 7, 2021 by tarvo-mesepp

 

How to use flags with python’s regular expressions in string notation?

1  Asked on January 7, 2021 by werner-germn-busch

   

Ask a Question

Get help from others!

© 2022 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP, SolveDir