Setting up LiveData observer in custom view without LifecycleOwner

kcrimi picture kcrimi · Sep 14, 2018 · Viewed 8k times · Source

I'm trying out the new Android Architecture components and have run into a road block when trying to use the MVVM model for a custom view.

Essentially I have created a custom view to encapsulate a common UI and it's respective logic to use throughout the app. I can set up the ViewModel in the custom view but then I'd have to either use observeForever() or manually set a LifecycleOwner in the custom view like below but neither seem correct.

Option 1) Using observeForever()

Activity

class MyActivity : AppCompatActivity() {

    lateinit var myCustomView : CustomView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        myCustomView = findViewById(R.id.custom_view)
        myCustomView.onAttach()
    }

    override fun onStop() {
        myCustomView.onDetach()
    }
}

Custom View

class (context: Context, attrs: AttributeSet) : RelativeLayout(context,attrs){

    private val viewModel = CustomViewModel()

    fun onAttach() {
        viewModel.state.observeForever{ myObserver }
    }

    fun onDetach() {
        viewModel.state.removeObserver{ myObserver }
    }
}

Option 2) Setting lifecycleOwner from Activity`

Activity

class MyActivity : AppCompatActivity() {

    lateinit var myCustomView : CustomView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        myCustomView = findViewById(R.id.custom_view)
        myCustomView.setLifeCycleOwner(this)
    }
}

Custom View

class (context: Context, attrs: AttributeSet) : RelativeLayout(context,attrs){

    private val viewModel = CustomViewModel()

    fun setLifecycleOwner(lifecycleOwner: LifecycleOwner) {
        viewModel.state.observe(lifecycleOwner)
    }
}

Am I just misusing the patterns and components? I feel like there should be a cleaner way to compose complex views from multiple sub-views without tying them to the Activity/Fragment

Answer

Mike picture Mike · Sep 17, 2018

1 Option - With good intention, you still have to do some manual work - like, calling onAttach\ onDetach Main purpose of Architecture components is to prevent doing this.

2 Option - In my opinion is better, but I would say it's a bit wrong to bind your logic around ViewModel and View. I believe you can do same logic inside Activity/Fragment without passing ViewModel and LifecycleOwner to CustomView. Single method updateData is enough for this purpose.

So, in this particular case, I would say it's overuse of Architecture Components.