Reacting to activity lifecycle in ViewModel

前端 未结 2 819
温柔的废话
温柔的废话 2021-02-12 15:15

I\'m trying to create an app which will use MVVM architecture and there\'s one thing I quite don\'t understand.

Official Android docs say that\'s not a good idea to refe

2条回答
  •  一生所求
    2021-02-12 15:32

    I know ViewModel's shouldn't do business logic themselves

    Yes, you're right. ViewModel should not contain business logic but it should contain UI related logic. So basically, API calls or Some location related stuffs should be avoided in ViewModel logic.

    So what if you wanna make some scenario which can react to any activity lifecycle? I'll suggest you to use LifecycleObserver.

    Why?, Because LifecycleObserver will provide you callbacks once it's LifecycleOwner will change it's state.

    What is LifecycleOwner here? In our case it may be Activity/Fragment.


    So, how you can achieve this?

    Let's say you want to make location requests during resume & pause period of any activity.

    So, for that you can create a class called LocationUpdates as LifecycleObserver like below:

    class LocationUpdates : LifecycleObserver {
    
    constructor(){
        // some basic location related initialization here
    }
    
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun connectListener() {
        // this method will respond to resume event of our Lifecycle owner (activity/fragment in our case)
       // So let's get location here and provide callback
    }
    
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun disconnectListener() {
        // this method will respond to pause event of our Lifecycle owner (activity/fragment in our case)
       // So let's stop receiveing location updates here and remove callback
    }
    
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) // Optional if you want to cleanup references
    fun cleanUp() {
        // this method will respond to destroy event of our Lifecycle owner (activity/fragment in our case)
       // Clean up code here
    }
    }
    

    Now from your activity, you can directly make your LocationUpdates, and receive callback.

    class MyActivity : AppCompatActivity() {
    
    private lateinit var mLocationUpdates: LocationUpdates
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //Initialize your LifecycleObserver here & assign it to this activity's lifecycle
        lifecycle.addObserver(mLocationUpdates)
    }
    }
    

    You can refer to how to handle Lifecycle & Codelabs example.


    Edit:

    If you want to have ViewModel for that job, consider this:

    class MyViewModel : ViewModel {
    private lateinit var mLocationUpdates: LocationUpdates
    
    constructor() : super() {
        // initialize LocationUpdates here
    }
    
    // Assign our LifecyclerObserver to LifecycleOwner
    fun addLocationUpdates(lifecycle: Lifecycle){
        lifecycle.addObserver(mLocationUpdates)
    }
    
    //Optional, we really don't need this.
    fun removeLocationUpdates(lifecycle: Lifecycle){
        lifecycle.removeObserver(mLocationUpdates)
    }
    }
    

    If your LocationUpdates depends upon Context, consider using AndroidViewModel.

    We can now observe our location updates @ any activity/fragment using LiveData, and assign our LifecycleObserver like below:

    class MyActivity : AppCompatActivity() {
    
    private val viewModel: MyViewModel by lazy {
        return@lazy ViewModelProviders.of(this@MyActivity).get(MyViewModel::class.java)
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel.addLocationUpdates(lifecycle)
    }
    }
    

    Please note: there's still lot to cover but making this answer as short as possible. So, if you're still confused about something related then please feel free to ask me in comment. I will edit my answer.

提交回复
热议问题