ViewModel of AAC

ViewModel of AAC

Introduction to ViewModel of Android Architecture Components

6dd0483f1353a4a359e92633cfd65c64?s=128

Daichi Furiya (Wasabeef)

February 22, 2018
Tweet

Transcript

  1. 2.

    Architecture Componentsษڧձ ͱ͸ • Architecture Componentsͷجૅ஌ࣝʹֶ͍ͭͯͿษڧձ • ओ࠵ɿGDG Tokyo ϋογϡλά:

    #gdgtokyo • ߨࢣɺνϡʔλʔɿGoogleࣾһͱGoogle Developer Expert ʢ͋Μ͍͟Ώ͖ɺ ͕͑ΘɺΘ͞ͼʔ;ɺ͋Β͖ʣ • ౰೔νϡʔλʔɿ
 ɹ@satorufujiwaraɺ@STAR_ZEROɺ@95kugoɺ@zaki50ɺ@itog
  2. 3.

    Architecture Componentsษڧձ ͱ͸ • ܭ4ճͷ༧ఆ • ୈ1ճ:Handling Lifecycles • ୈ2ճ:LiveData

    • ୈ3ճ:ViewModel • ୈ4ճ:Room λΠϜςʔϒϧ 19:30ʙ19:35 ѫࡰˍઆ໌ 19:35ʙ20:15 ViewModel ͷઆ໌ 20:15ʙ20:25 ٳܜ 20:25ʙ ՝୊औΓ૊Έ
  3. 7.

    Architecture Components ͱ͸ • ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData •

    ViewModel • Room • Paging ݸผར༻OK ૊Έ߹Θͤར༻OK
  4. 8.

    Architecture Components ͱ͸ • ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData •

    ViewModel • Room • Paging ࠓ೔ͷςʔϚ͸͜Ε લճ ࣍ճ * RxJava * ReactiveStreams * Dagger ʹ͍ͭͯ͸ࠓճ͸औΓ্͛·ͤΜ
  5. 9.

    Architecture Components ͱ͸ • Google I/O 2017 Ͱൃදʢ1.0.0 alpha 1ʣ

    • ݱࡏͷ҆ఆόʔδϣϯ : 1.1.0 ʢ2018೥2݄22೔ʣ https://developer.android.com/topic/libraries/architecture/release-notes.html
  6. 10.

    Architecture Components ͷઃఆ dependencies { // ViewModel and LiveData implementation

    “android.arch.lifecycle:extensions:x.y.z" kapt “android.arch.lifecycle:compiler:x.y.z” } ϓϩδΣΫτͷ build.gradle https://developer.android.com/topic/libraries/architecture/adding-components.html
  7. 11.
  8. 13.

    Lifecycles • Lifecycles = Lifecycle-aware Components • ϥΠϑαΠΫϧΛݕ஌͢Δίϯϙʔωϯτ • Activity

    ΍ Fragment ͷϥΠϑαΠΫϧঢ়ଶ͕มΘͬͨͱ͖ʹԿ͔ ΞΫγϣϯΛى͜͢ɺͱ͍͏͜ͱ͕Ͱ͖ΔΑ͏ʹͳΔ
  9. 14.

    Lifecycle.State • ݱࡏͷϥΠϑαΠΫϧঢ়ଶΛද͢ enum • INITIALIZED • DESTROYED • CREATED

    • STARTED • RESUMED https://developer.android.com/topic/libraries/architecture/lifecycle.html
  10. 16.

    ݱࡏͷϥΠϑαΠΫϧΛऔಘ΍؂ࢹ͢Δ val state: Lifecycle.State = lifecycle.currentState // state.compareTo(Lifecycle.State.INITIALIZED) lifecycle.addObserver(object :

    LifecycleObserver { @OnLifecycleEvent(Event.ON_ANY) fun onAny(source: LifecycleOwner, event: Event) { // ... } })
  11. 18.

    ओͳLiveData • LiveData (android.arch.lifecycle) ௨ৗͷ LiveData • MutableLiveData (android.arch.lifecycle) ֎෦͔ΒมߋՄೳͳ

    LiveData • MediatorLiveData (android.arch.lifecycle) ෳ਺ͷ LiveData ΛଋͶͯ؅ཧ͢Δ LiveData
  12. 19.
  13. 20.

    ViewModel • Activity ͷը໘ճస࣌ͷσʔλอ࣋ • Activity ͷෳ਺ Fragment ؒͰͷσʔλड͚౉͠ •

    LiveData ͱซ༻͢Δ͜ͱ͕ଟ͍ • ϓϩηεఀࢭޙ͸෮چͰ͖ͳ͍ • σʔλͷӬଓԽͰ͸ͳ͍
  14. 21.
  15. 25.

    class BeefActivity : AppCompatActivity() { companion object { private const

    val EXTRA_BEEF_KEY = "8044" } // ... public override fun onSaveInstanceState(outState: Bundle) { outState.putString(EXTRA_BEEF_KEY, beef.text as String) super.onSaveInstanceState(outState) } override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) beef.text = savedInstanceState.getString(EXTRA_BEEF_KEY) } } Activity#onSaveInstanceState() onRestoreInstanceStateͰ͸ͳ͘onCreate()Ͱ΋Մ
  16. 29.

    onRetainCustomNonConfigurationInstance() class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } override fun onRetainCustomNonConfigurationInstance(): Any { return Dog("chip", 6) } } data class Dog(val name: String, val age: Int) อ͍࣋ͨ͠ΠϯελϯεΛฦ٫
  17. 30.

    onRetainCustomNonConfigurationInstance() class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val dog = lastCustomNonConfigurationInstance as Dog? ?: Dog("wasa", 18) } override fun onRetainCustomNonConfigurationInstance(): Any { return Dog("chip", 6) } } data class Dog(val name: String, val age: Int) औಘ
  18. 33.

    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public class HolderFragment extends Fragment ɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹimplements ViewModelStoreOwner { private

    static final String LOG_TAG = "ViewModelStores"; // ... public HolderFragment() { setRetainInstance(true); } // ... } Fragment#setRetainInstance() AACͷ಺෦࣮૷ΛҰ෦ൈਮ
  19. 35.
  20. 36.

    ViewModelͷܧঝ ୯७ʹViewModelΛܧঝ͢Δ # View΍ActivityContext͸࣋ͬͯ͸͍͚ͳ͍ data class User(val name: String, val

    age: Int) class UserViewModel : ViewModel() { private var user: MutableLiveData<User>? = null fun getUser() { if (user == null) { user = MutableLiveData() load() } } private fun load() { // ... } }
  21. 37.
  22. 39.

    class UserViewModel : ViewModel() { var disposables = CompositeDisposable() //

    ... override fun onCleared() { super.onCleared() // ϦʔΫ๷ࢭ౳ɺղ์͢Δ৔߹͸͜͜Ͱɻ disposables.dispose() } } ViewModel#onCleared()ͰϦʔΫ๷ࢭ
  23. 41.

    AndroidViewModelͷܧঝ class DogsViewModel(app: Application) : AndroidViewModel(app) { @Inject lateinit var

    repo: DogRepository var dogs: MutableLiveData<Dogs>? = null init { // (app as BeefApp).applicationInjector() as AppComponent } // ... } ViewModel಺ͰApplication͕ඞཁͳ৔߹ʹ࢖͑Δ
  24. 45.

    val user = ViewModelProviders.of(this) .get(UserViewModel::class.java) val user = ViewModelProviders.of(<FragmentActivity ||

    Fragment>) .get(<T : ViewModel>::class.java) ViewModelProvider /s ViewModelProviders.of()ʹࢦఆͰ͖Δͷ͸ FragmentActivity͔Fragment͚ͩ
  25. 46.

    ViewModelProviders#of() @NonNull @MainThread public static ViewModelProvider of(@NonNull Fragment fragment) {}

    @NonNull @MainThread public static ViewModelProvider of(@NonNull FragmentActivity activity) {} @NonNull @MainThread public static ViewModelProvider of(@NonNull Fragment fragment, @NonNull Factory factory) {} @NonNull @MainThread public static ViewModelProvider of(@NonNull FragmentActivity activity, @NonNull Factory factory) {} Fragment͔FragmentActivityͷΈαϙʔτ͍ͯ͠Δ
  26. 47.

    val user = ViewModelProviders.of(<FragmentActivity || Fragment>) .get(<T : ViewModel>::class.java) val

    user = ViewModelProviders.of(this) .get(UserViewModel::class.java) ViewModelProvider /s ViewModelProvider.get()ʹ͸ ViewModelΛܧঝͨ͠ΫϥεΛࢦఆ͢Δ
  27. 48.

    ViewModelProvider /s class MyDogFragment : Fragment() { override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) val userA = ViewModelProviders.of(this).get(UserViewModel::class.java) val userB = ViewModelProviders.of(activity!!).get(UserViewModel::class.java) } } userAͱuserB͸Πϯελϯε͕ҧ͍ ViewModelProviders.of()ʹ౉ͨ͠ΫϥεʹΑͬͯΠϯελϯε͕ܾ·Δ
  28. 52.

    val user = ViewModelProviders.of(this, object : ViewModelProvider.Factory { override fun

    <T : ViewModel?> create(modelClass: Class<T>): T { // Կ͔͠Βॲཧ @Suppress("UNCHECKED_CAST") return UserViewModel(repo) as T } }).get(UserViewModel::class.java) ViewModelProvider.Factoryͷࢦఆ
  29. 53.

    ViewModelProvider.Factoryͷܧঝ class UserViewModelFactory @Inject constructor(val repo: UserRepository) : ViewModelProvider.Factory {

    @Suppress("UNCHECKED_CAST") override fun <T : ViewModel?> create(modelClass: Class<T>): T { return UserViewModel(repo) as T } } ViewModelProvider.FactoryΛܧঝͯ͠Ҿ਺Λ༩͑ͨΓ΋Ͱ͖Δ Dagger౳ͰɺFactoryʹ@Singleton͚ͭͯ؅ཧͨ͠Γ ViewModel΋Injectͨ͠Γ͢Δ৔߹͸ɺ͜ͷܧঝ͕ඞཁʹͳΓ·͢ https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/viewmodel/GithubViewModelFactory.java
  30. 54.

    ViewModelProvider.Factoryؔ࿈ /** * Simple factory, which calls empty constructor on

    the give class. */ public static class NewInstanceFactory implements Factory {} /** * {@link Factory} which may create {@link AndroidViewModel} and * {@link ViewModel}, which have an empty constructor. */ public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {} ͦͷଞ
  31. 57.

    ՝୊ 0 • Empty Activity Ͱ৽͍͠KotlinϓϩδΣΫτΛ࡞Δ ʢύοέʔδ໊͸ com.sample.viewmodel Λ૝ఆʣ //

    build.gradle apply plugin: 'kotlin-kapt' dependencies { implementation "com.android.support:appcompat-v7:27.0.2" // … implementation "android.arch.lifecycle:extensions:1.1.0" kapt "android.arch.lifecycle:compiler:1.1.0" } http://bit.ly/AAC-VM
  32. 59.

    ՝୊ 1 • ViewModelΛܧঝͨ͠UserViewModelʹॻ͖׵͑ͯΈΑ͏ class UserViewModel { private var user:

    User? = null fun getUser(): User? { if (user == null) { load() } return user } private fun load() { user = User("Hanyu", 23) } } data class User(val name: String, val age: Int) http://bit.ly/AAC-VM
  33. 60.

    ՝୊ 1 (ྫ) class UserViewModel : ViewModel() { private var

    user: MutableLiveData<User>? = null fun getUser(): MutableLiveData<User>? { if (user == null) { user = MutableLiveData() load() } return user } private fun load() { user?.postValue(User("Hanyu", 23)) } } data class User(val name: String, val age: Int) http://bit.ly/AAC-VM
  34. 61.

    ՝୊ 1 - 2 • ܧঝͨ͠UserViewModelΛActivity಺Ͱ࢖ͬͯΈΑ͏ class MainActivity : AppCompatActivity()

    { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val user = UserViewModel() Log.d("OLYMPICS", user.getUser()?.toString()) } } http://bit.ly/AAC-VM
  35. 62.

    ՝୊ 1 - 2 (ྫ) class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val user = ViewModelProviders.of(this).get(UserViewModel::class.java) user.getUser()?.observe(this, Observer { Log.d(“OLYMPICS", it?.toString()) }) } } http://bit.ly/AAC-VM
  36. 65.

    ՝୊ 2 • Fragment ಺Ͱ userA/B/C ͕ಉ͔֬͡ೝ͠Α͏ class DogFragment :

    Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val userA = ViewModelProviders.of(this).get(UserViewModel::class.java) val userB = ViewModelProviders.of(activity!!).get(UserViewModel::class.java) val userC = ViewModelProviders.of(this).get(UserViewModel::class.java) } } http://bit.ly/AAC-VM
  37. 67.

    ՝୊ 3 • 2ͭͷFragment ಺Ͱ user ͕ಉ͔֬͡ೝ͠Α͏ class TopFragment :

    Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val user = ViewModelProviders.of(this).get(UserViewModel::class.java) } } class BottomFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val user = ViewModelProviders.of(this).get(UserViewModel::class.java) } } http://bit.ly/AAC-VM
  38. 68.

    ViewModelProvider /s ෮श class MyDogFragment : Fragment() { override fun

    onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val userA = ViewModelProviders.of(this).get(UserViewModel::class.java) val userB = ViewModelProviders.of(activity!!).get(UserViewModel::class.java) } } userAͱuserB͸Πϯελϯε͕ҧ͍ ViewModelProviders.of()ʹ౉ͨ͠ΫϥεʹΑͬͯΠϯελϯε͕ܾ·Δ