Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android LiveData Observer not active after first update

I'm trying out a basic implementation of Architecture Component's Live Data with Kotlin like this:

class MarketFragment : LifecycleFragment(){
......
 override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel=ViewModelProviders.of(this).get(MarketViewModel::class.java)
        viewModel.book?.observe(this, Observer { book-> //updateUI })
....

My ViewModel class is created like this:

class MarketViewModel : ViewModel()
{
    var book: MutableLiveData<Book>? =MutableLiveData()
    var repository: Repository?= Repository()

    init {
        update("parameter")
    }

    fun update(s: String)
    {
         book=repository?.getBook(s)

    }

}

And My Repository:

fun getBook(bookSymbol:String):MutableLiveData<Book>
{
    val book=MutableLiveData<Book>()
    ......

            call . enqueue (object : Callback<Book> {
        override fun onResponse(call: Call<Book>?, response: Response<Book>?) {

            book.value=response?.body()

        }
     .....
    })
            return book
}

}

And all of this works great and UI is updated as it should but only for the first time. If i try to make manual calls to update the viewModel from a UI action, the retrofit call still works as expected but the new data is not sent to the Observer in the Fragment:

//this doesn't work:
viewModel.update("string")
//This returns false:
viewModel.book.hasActiveObservers()

Is it the expected behaviour for an Observer to become inactive after the first trigger?

like image 818
Roberto Betancourt Avatar asked Aug 18 '17 14:08

Roberto Betancourt


1 Answers

You are creating a new MutableLiveData instance each time you are calling getBooks

Hence your observer is not observing the right LiveData anymore.

To solve this

  1. Your ViewModel should keep only one (immutable) LiveData instance
  2. That immutable LiveData instance could either be:

    • A MediatorLiveData, which source is the repository's LiveData
    • A transformation of the repository's LiveData

That implies the repository method getBooks is only called once on initialization of the ViewModel, and that either refreshes itself OR you have to call another method on the repository to trigger a refresh.

like image 142
Vincent Mimoun-Prat Avatar answered Sep 19 '22 04:09

Vincent Mimoun-Prat