Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Inside Jetpack

Inside Jetpack

8766b19fe1c1f8475e233c910ed6440f?s=128

kobito-kaba

November 28, 2018
Tweet

Transcript

  1. Inside Jetpack Architecture Components Hiroyuki Mori @moridroid

  2. • Started as a Venture between Softbank and Yahoo •

    One of biggest search in Japan • Not a part of big
  3. What & Why Architecture Components

  4. 2015

  5. View View Controller Application Logic Network Persistent Model onSendClick sendComment

  6. onSendClick sendComment View View Controller Application Logic Network Persistent Model

  7. View View Controller Application Logic Network Persistent Model

  8. View View Controller Application Logic Network Persistent Model subscribe

  9. View View Controller Application Logic Network Persistent Model onSendClick sendComment

  10. 2016

  11. None
  12. 2016

  13. 2017

  14. 2017

  15. 2017

  16. 2018

  17. 2018 -JGFDZDMFT -JWF%BUB 7JFX.PEFM 3PPN 1BHJOH %BUB#JOEJOH /BWJHBUJPO 8PSL.BOBHFS %PXOMPBE.BOBHFS

    .FEJB1MBZCBDL 1FSNJTTJPOT /PUJDBUJPOT 4IBSJOH 4MJDFT "OJNBUJPO5SBOTJUJPOT "VUP 578FBS &NPKJ 'SBHNFOU -BZPVU 1BMFUUF "QQ$PNQBU "OESPJE,59 .VMUJEFY 5FTU
  18. -JGFDZDMFT -JWF%BUB 7JFX.PEFM 3PPN 1BHJOH %BUB#JOEJOH /BWJHBUJPO 8PSL.BOBHFS

  19. Lifcycle problems

  20. In early days

  21. Steve Pomeroy https://github.com/xxv/android-lifecycle CC-BY-SA 4.0 Today

  22. LifecycleObserver

  23. Android System NetworkReceiver Network state Foo Activity observe observe notify

    notify state changed
  24. class NetworkReceiver(val listener : (NetworkInfo) -> Unit) : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) { val con = context.getSystemService(ConnectivityManager::class.java) listener(con.activeNetworkInfo) } }
  25. class NetworkReceiver(val listener : (NetworkInfo) -> Unit) : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) { val con = context.getSystemService(ConnectivityManager::class.java) listener(con.activeNetworkInfo) } }
  26. class NetworkReceiver(val listener : (NetworkInfo) -> Unit) : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) { val con = context.getSystemService(ConnectivityManager::class.java) listener(con.activeNetworkInfo) } }
  27. class MainActivity : AppCompatActivity() { private lateinit var networkReceiver :

    NetworkReceiver override fun onCreate(...) { networkReceiver = NetworkReceiver { // do something } val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION) registerReceiver(networkReceiver, filter) } override fun onDestroy() { unregisterReceiver(networkReceiver) } }
  28. class MainActivity : AppCompatActivity() { private lateinit var networkReceiver :

    NetworkReceiver override fun onCreate(...) { networkReceiver = NetworkReceiver { // do something } val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION) registerReceiver(networkReceiver, filter) } override fun onDestroy() { unregisterReceiver(networkReceiver) } }
  29. class MainActivity : AppCompatActivity() { private lateinit var networkReceiver :

    NetworkReceiver override fun onCreate(...) { networkReceiver = NetworkReceiver { // do something } val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION) registerReceiver(networkReceiver, filter) } override fun onDestroy() { unregisterReceiver(networkReceiver) } }
  30. class NetworkObserver(val owner : LifecycleOwner, private val context: Context, private

    val listener: (NetworkInfo) -> Unit) : LifecycleObserver { private val receiver = object : BroadcastReceiver() { ... } }
  31. class NetworkObserver(val owner : LifecycleOwner, private val context: Context, private

    val listener: (NetworkInfo) -> Unit) : LifecycleObserver { init { owner.lifecycle.addObserver(this) } private val receiver = object : BroadcastReceiver() { ... } }
  32. ... @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun register() { val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION) context.registerReceiver(receiver,

    filter) } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun unregister() { context.unregisterReceiver(receiver) } }
  33. class MainActivity : AppCompatActivity() { override fun onCreate(...) { NetworkObserver(this,

    this) { // do something } } }
  34. Observer Pattern vs Pub-Sub Pattern

  35. <<interface>> Subject

  36. <<interface>> Subject ConcreteSubject ConcreteSubject

  37. <<interface>> Subject ConcreteSubject ConcreteSubject <<interface>> Observer ConcreteObserve r ConcreteObserve r

    observe
  38. <<interface>> Subject ConcreteSubject ConcreteSubject <<interface>> Observer ConcreteObserve r ConcreteObserve r

    event notify
  39. None
  40. None
  41. None
  42. None
  43. LiveData

  44. None
  45. Activity#0 created onCreate onStart onResume onPause onStop onDestroy Device rotated

    Activity#1 created Exception Call Web API
  46. LiveData addObserver

  47. LiveData Observer value

  48. LiveData Observer Lifecycle Owner

  49. Lifecycle Owner LiveData LifecycleBoundObserver Observer addObserver addObserver dispatch events active

    onChanged LiveData
  50. Lifecycle Owner LiveData LifecycleBoundObserver Observer addObserver addObserver dispatch events inactive

    onChanged LiveData
  51. Lifecycle Owner LiveData LifecycleBoundObserver Observer removeObserver addObserver dispatch events destroyed

    onChanged
  52. object CatRepository { private val _cat = MutableLiveData<Cat>() fun loadCat(catId

    : Int) : LiveData<Cat> { fetch(catId) { newCat -> _cat.postValue(newCat) } return _cat } }
  53. class CatActivity : AppCompatActivity() { override fun onCreate(...) { val

    catId = intent.getIntExtra("cat_id") CatRepository.loadCat(catId).observe(this, Observer { cat -> showCat(cat)}) } }
  54. class CatActivity : AppCompatActivity() { override fun onCreate(...) { ...

    val relatedCatsModule = RelatedCatsModuleAdapter { clicked -> val intent = Intent(this, CatActivity::class.java) intent.putExtra("cat_id", clicked.id) startActivity(intent) } } }
  55. ViewModels

  56. None
  57. Activity#0 created onCreate onStart onResume Call Web API

  58. Activity#0 created onCreate onStart onResume onPause onStop onDestroy Device rotated

    Activity#1 created Call Web API onCreate Call Web API
  59. ViewModel Provider ViewModel Store Activity/Fragment request get null ViewModel

  60. return ViewModel Provider ViewModel Store Activity/Fragment request get null put

    ViewModel ViewModel
  61. ViewModel Store Activity/Fragment ViewModel in NonConfigurationInstance

  62. None
  63. public class FragmentActivity extends ComponentActivity ... { @Override public final

    Object onRetainNonConfigurationInstance() { ... NonConfigurationInstances nci = new NonConfigurationInstances(); nci.custom = custom; nci.viewModelStore = mViewModelStore; nci.fragments = fragments; return nci; }
  64. public class FragmentActivity extends ComponentActivity ... { @Override protected void

    onCreate(...) { ... NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc != null && nc.viewModelStore != null && mViewModelStore == null) { mViewModelStore = nc.viewModelStore; }
  65. None
  66. Repository Model Repository

  67. Repository Model Repository Activity / Fragment

  68. Repository Model

  69. private val _cat = MutableLiveData<List<Cat>>() fun updateCat(new: Cat) { val

    currentCats = _cat.value ?: return val updatedCats = currentCats.toMutableList() .map { old -> if(old.id == new.id) new else old } _cat.postValue(updatedCats) // update storage and web service ... }
  70. private val _cat = MutableLiveData<List<Cat>>() fun updateCat(new: Cat) { val

    currentCats = _cat.value ?: return val updatedCats = currentCats.toMutableList() .map { old -> if(old.id == new.id) new else old } _cat.postValue(updatedCats) // update storage and web service ... }
  71. private val _cat = MutableLiveData<List<Cat>>() fun updateCat(new: Cat) { val

    currentCats = _cat.value ?: return val updatedCats = currentCats.toMutableList() .map { old -> if(old.id == new.id) new else old } _cat.postValue(updatedCats) // update storage and web service ... }
  72. @Entity data class Cat( @PrimaryKey(autoGenerate = true) val id: Int

    = 0, val name: String, val age: Int, val description: String, val loved: Boolean )
  73. @Dao interface CatDao { @Query("SELECT * from Cat") fun loadCats()

    : LiveData<List<Cat>> @Update fun update(cat: Cat) }
  74. @Database(entities = [Cat::class], version = 1) abstract class CatDatabase :

    RoomDatabase() { abstract fun catDao() : CatDao }
  75. fun getCatDatabase(context: Context) = Room.databaseBuilder(context, CatDatabase::class.java, "catDB").build()

  76. fun updateCat(new: Cat) { // update logic here catDao.updateCat(new) catService.updateData(new)

    }
  77. Cat Database Cat table room_master_table Id, identity_hash

  78. Cat Database Cat table room_master_table Id, identity_hash room_table_modification_log InvalidationTracker Updated?

    Version, table_id onInvalidated Observer trigger Oh, yes!
  79. Cat Database Cat table room_master_table Id, identity_hash room_table_modification_log InvalidationTracker Version,

    table_id Observer ComputeLiveDat a addObserver query Cat Dao
  80. Cat Database Cat table room_master_table Id, identity_hash room_table_modification_log InvalidationTracker Version,

    table_id Observer Cat Dao ComputeLiveDat a addObserver query onInvalidated
  81. Why use Paging library?

  82. Repository ViewModel Activity / Fragment What do I display? I

    need cats Give us ALL Cats OK, 1,000,000 cats here. Here you are Show this 1,000,000 cats ¯\_(π)_/¯
  83. PagedList DataSource

  84. PagedList DataSource

  85. PagedList DataSource DataSource.Factory

  86. PagedList DataSource DataSource.Factory invalidate

  87. PagedList DataSource DataSource.Factory

  88. View ViewModel Repository DataSource.Factory LiveData<PagedList > Room LivePagedListBuilder

  89. View Observer ViewModel Repository DataSource.Factory LiveData<PagedList > Room LivePagedListBuilder LivePagedListBuilder

    DataSource.Factory
  90. View ViewModel Repository DataSource.Factory LiveData<PagedList > PagedListAdapter Room Observer LivePagedListBuilder

    AsyncPagedListDiffer
  91. View ViewModel Repository DataSource.Factory LiveData<PagedList > PagedListAdapter Room Observer LivePagedListBuilder

    AsyncPagedListDiffer
  92. public abstract class PagedListAdapter<T, VH> ... { final AsyncPagedListDiffer<T> mDiffer;

    @Nullable protected T getItem(int position) { return mDiffer.getItem(position); } }
  93. public class AsyncPagedListDiffer<T> { ... public T getItem(int index) {

    ... mPagedList.loadAround(index); return mPagedList.get(index); } }
  94. public abstract class PagedList<T> extends AbstractList<T> { ... public void

    loadAround(int index) { ... loadAroundInternal(index); ... } }
  95. class ContiguousPagedList<K, V> extends PagedList<V> ... { protected void loadAroundInternal(int

    index) { int appendItems = getAppendItemsRequested(...); ... mAppendItemsRequested = Math.max(...); if (mAppendItemsRequested > 0) { scheduleAppend(); } }
  96. Summary