Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I include LifecycleOwner in ViewModel?

LifecycleOwner is currently needed in order for me to create an observer.

I have code which creates an Observer in the ViewModel so I attach the LifecycleOwner when retrieving the ViewModel in my Fragment.

According to Google's documentation.

Caution: A ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context.

Did I break that warning and If I did, what way do you recommend me to move my creation of an observer for data return?

I only made an observer so I'm wondering if it's still valid. Since also in Google's documentation it also said.

ViewModel objects can contain LifecycleObservers, such as LiveData objects.

MainFragment

private lateinit var model: MainViewModel  /**  * Observer for our ViewModel IpAddress LiveData value.  * @see Observer.onChanged  * */ private val ipObserver = Observer<String> {     textIp.text = it     hideProgressBar() }  override fun onCreate(savedInstanceState: Bundle?) {     super.onCreate(savedInstanceState)     model = ViewModelProviders.of(this).get(MainViewModel::class.java)     model.attach(this) }  override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? =         inflater?.inflate(R.layout.fragment_main, container, false)  override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {     super.onViewCreated(view, savedInstanceState)      buttonRetrieveIp.setOnClickListener {         showProgressBar()         model.fetchMyIp().observe(this, ipObserver) //Here we attach our ipObserver     } }  override fun showProgressBar() {      textIp.visibility = View.GONE     progressBar.visibility = View.VISIBLE }  override fun hideProgressBar() {      progressBar.visibility = View.GONE     textIp.visibility = View.VISIBLE } 

MainViewModel

private var ipAddress = MutableLiveData<String>() private lateinit var owner: LifecycleOwner  fun attach(fragment: MainFragment) {     owner = fragment }  /**  * For more information regarding Fuel Request using Fuel Routing and Live Data Response.  * @see <a href="https://github.com/kittinunf/Fuel#routing-support">Fuel Routing Support</a>  * @see <a href="https://github.com/kittinunf/Fuel#livedata-support">Fuel LiveData Support</a>  * */ fun fetchMyIp(): LiveData<String> {      Fuel.request(IpAddressApi.MyIp())             .liveDataResponse()             .observe(owner, Observer {                  if (it?.first?.statusCode == 200) {//If you want you can add a status code checker here.                      it.second.success {                          ipAddress.value = Ip.toIp(String(it))?.ip                     }                 }             })     return ipAddress } 

Update 1: Improved ViewModel thanks to @pskink suggestion for using Transformations.

private lateinit var ipAddress:LiveData<String>  /**  * Improved ViewModel since January 23, 2018 credits to <a href="https://stackoverflow.com/users/2252830/pskink">pskink</a> <a href="  *  * For more information regarding Fuel Request using Fuel Routing and Live Data Response.  * @see <a href="https://github.com/kittinunf/Fuel#routing-support">Fuel Routing Support</a>  * @see <a href="https://github.com/kittinunf/Fuel#livedata-support">Fuel LiveData Support</a>  * */ fun fetchMyIp(): LiveData<String> {      ipAddress = Transformations.map(Fuel.request(IpAddressApi.MyIp()).liveDataResponse(), {          var ip:String? = ""              it.second.success {                  ip = Ip.toIp(String(it))?.ip             }         ip     })      return ipAddress } 
like image 872
Hiroga Katageri Avatar asked Jan 23 '18 07:01

Hiroga Katageri


People also ask

What is LifecycleOwner in ViewModel?

LifecycleOwner - relates to an Activity or Fragment as it owns the various Android Lifecycles e.g onCreate, onPause, onDestroy etc.

How do you find lifecycle owner in ViewModel?

It traces and provides lifecycle states for ViewModels. You can get the ViewModelLifecycleOwner from your ViewModel as the following: class MyActivity : AppCompatActivity() { private val viewModel by viewModels<MyViewModel>() override fun onCreate(savedInstanceState: Bundle?) { super.

Is ViewModel Life Cycle Aware?

Lifecycle Awareness :Viewmodel is lifecycle aware. It is automatically cleared when the lifecycle they are observing gets permanently destroyed.

Can ViewModel observe LiveData?

ViewModel allows the app's data to survive configuration changes. In this codelab, you'll learn how to integrate LiveData with the data in the ViewModel . The LiveData class is also part of the Android Architecture Components and is a data holder class that can be observed.


2 Answers

No. If you wish to observe changes of some LiveData inside your ViewModel you can use observeForever() which doesn't require LifecycleOwner.

Remember to remove this observer on ViewModel's onCleared() event:

val observer = new Observer() {   override public void onChanged(Integer integer) {     //Do something with "integer"   } } 

...

liveData.observeForever(observer); 

...

override fun onCleared() {     liveData.removeObserver(observer)      super.onCleared() } 

Very good reference with examples of observe LiveData.

like image 193
Vitaliy A Avatar answered Oct 02 '22 18:10

Vitaliy A


Assumptions:

  1. Fuel refers to your ViewModel
  2. Fuel.request(IpAddressApi.MyIp()) is a method in your ViewModel
  3. IpAddressApi.MyIp() does not have a reference to your LifecycleOwner,

If all are true,then you are not violating it. So long as you are not passing a LifecycleOwner reference to the ViewModel you are safe!

LifecycleOwner - relates to an Activity or Fragment as it owns the various Android Lifecycles e.g onCreate, onPause, onDestroy etc

like image 39
martinomburajr Avatar answered Oct 02 '22 16:10

martinomburajr