Roberto Betancourt
Roberto Betancourt

Reputation: 2515

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?

Upvotes: 6

Views: 11191

Answers (1)

Vincent Mimoun-Prat
Vincent Mimoun-Prat

Reputation: 28561

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.

Upvotes: 10

Related Questions