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)
}
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
2 Asked on January 8, 2021 by titatovenaar
1 Asked on January 8, 2021 by jason-sui
0 Asked on January 8, 2021 by stavros-koureas
1 Asked on January 8, 2021 by a-nice-guy
0 Asked on January 8, 2021 by karlos-margaritos
3 Asked on January 8, 2021 by winklerrr
1 Asked on January 8, 2021 by thinkingboutcode
1 Asked on January 7, 2021 by user14781783
1 Asked on January 7, 2021 by thorsten-westheider
1 Asked on January 7, 2021 by hassam-saeed
2 Asked on January 7, 2021
3 Asked on January 7, 2021 by david-vittori
1 Asked on January 7, 2021 by positiveguy
1 Asked on January 7, 2021 by nikhil-ponduri
1 Asked on January 7, 2021 by sara-ree
1 Asked on January 7, 2021 by werner-germn-busch
Get help from others!
Recent Answers
© 2022 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP, SolveDir