Viraj Tank

MBition GmbH

@viraj49

Viraj Tank

MBition

Mercedez-Benz Innovation Lab

@viraj49

God Activity Problem

Rise of Architectures

God P/VM Problem

Clean Architecture

Lifecycle Question

Bind/Subscribe - onResume/onStart

UnBind/Dispose - onPause/onStop

View

Partially/

Fully

Blocked

View

Partially/

Fully

Blocked

View Reloading Problem

RunTime Config Change

e.g. Orientation, Keyboard availability, Language, Docking etc

Android restarts running Activity

  • View reloading

  • Data call may get interrupted

  • Context Leak

  • View state management

View State Management

  • View data

  • State changing action

  • One time action

View Data

State Changing Action

One Time Action

- Lifecycle changes

- Configuration changes

  • View reloading

  • Data call may get interrupted

  • Context Leak

  • View state management

Problem Summary

Android Architecture Components

  • Lifecycle

  • ViewModel

  • LiveData

  • Room*

  • Paging Library*

AAC - Lifecycle

AAC - ViewModel

  • Retained Fragment Storage

  • Lifecycle Aware

  • onDestroy() clean up

  • onCleared() clean up

AAC - LiveData

  • ~ Hot Observables

  • Lifecycle Aware

  • STARTED or RESUMED

  • onDestroy() clean up

AAC- core concept

Should I use ViewModel with MVP?

NO

Can I use ViewModel with MVP?

YES

- Lifecycle changes

- Configuration changes

  • Reloading the view

  • Data call may get interrupted

  • Context Leak

  • View state management*

Problem Summary

SingleLiveEvent

Activity


  class MyActiviy : LifecycleActivity() {

  class MyActiviy : LifecycleActivity() {

    private val myViewModelFactory = MyViewModelFactory()
    private lateinit var myViewModel: MyViewModel

  class MyActiviy : LifecycleActivity() {

    private val myViewModelFactory = MyViewModelFactory()
    private lateinit var myViewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      myViewModel = ViewModelProviders.of(this, myViewModelFactory)
                                      .get(MyViewModel::class.java)

  class MyActiviy : LifecycleActivity() {

    private val myViewModelFactory = MyViewModelFactory()
    private lateinit var myViewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      myViewModel = ViewModelProviders.of(this, myViewModelFactory)
                                      .get(MyViewModel::class.java)

      myViewModel.myLiveData.observe(this, Observer {
        /* Update View */
      })
    }
  }

Fragment


  class MyFragment : LifecycleFragment() {

    private val myViewModelFactory = MyViewModelFactory()
    private lateinit var myViewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      myViewModel = ViewModelProviders.of(this, myViewModelFactory)
                                      .get(MyViewModel::class.java)

      myViewModel.myLiveData.observe(this, Observer {
        /* Update View */
      })
    }
  }

ViewModelFactory


  class MyViewModelFactory : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
      if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
        return MyViewModel() as T
      }
      
      throw IllegalArgumentException("Unknown MyViewModel class")
    }
  }

ViewModel


  class MyViewModel : ViewModel() {
    private val dataSubscription = CompositeDisposable()

  class MyViewModel : ViewModel() {
    private val dataSubscription = CompositeDisposable()

    private var myViewState = MyViewState()
    val myLiveData = MutableLiveData<MyViewState>()

  class MyViewModel : ViewModel() {
    private val dataSubscription = CompositeDisposable()

    private var myViewState = MyViewState()
    val myLiveData = MutableLiveData<MyViewState>()

    init {
      getData()
    }

  class MyViewModel : ViewModel() {
    private val dataSubscription = CompositeDisposable()

    private var myViewState = MyViewState()
    val myLiveData = MutableLiveData<MyViewState>()

    init {
      getData()
    }

    fun getData() {
      dataSubscriptions.add(myDataSource.getData())
              .subscribeOn(Schedulers.computation())
              .observeOn(Schedulers.computation())

  class MyViewModel : ViewModel() {
    private val dataSubscription = CompositeDisposable()

    private var myViewState = MyViewState()
    val myLiveData = MutableLiveData<MyViewState>()

    init {
      getData()
    }

    fun getData() {
      dataSubscriptions.add(myDataSource.getData())
              .subscribeOn(Schedulers.computation())
              .observeOn(Schedulers.computation())
              .subscribe({ data ->
                myViewState = myViewState.copy(myData = data)
                myLiveData.postValue(myViewState)
              })
    }

  class MyViewModel : ViewModel() {
    private val dataSubscription = CompositeDisposable()

    private var myViewState = MyViewState()
    val myLiveData = MutableLiveData<MyViewState>()

    init {
      getData()
    }

    fun getData() {
      dataSubscriptions.add(myDataSource.getData())
              .subscribeOn(Schedulers.computation())
              .observeOn(Schedulers.computation())
              .subscribe({ data ->
                myViewState = myViewState.copy(myData = data)
                myLiveData.postValue(myViewState)
              })
    }

    override fun onCleared() {
      dataSubscription.dispose()
      super.onCleared()
    }
  }

Summary

- Lifecycle changes

- Configuration changes

  • Reloading the view

  • Data call may get interrupted

  • Context Leak

  • Recreating view state

- MVVM

- Clean Architecture

- Android Arch Components

Thanks

github.com/viraj49

twitter.com/viraj49

speakerdeck.com/viraj49

mbtion.io/

Offline first using Android Architecture Components

By Viraj Tank

Offline first using Android Architecture Components

How to design an offline first experience using Android Architecture Components

  • 1,792