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

ViewModel of AAC

ViewModel of AAC

Introduction to ViewModel of Android Architecture Components

Daichi Furiya (Wasabeef)

February 22, 2018
Tweet

More Decks by Daichi Furiya (Wasabeef)

Other Decks in Programming

Transcript

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

    #gdgtokyo • ߨࢣɺνϡʔλʔɿGoogleࣾһͱGoogle Developer Expert ʢ͋Μ͍͟Ώ͖ɺ ͕͑ΘɺΘ͞ͼʔ;ɺ͋Β͖ʣ • ౰೔νϡʔλʔɿ
 ɹ@satorufujiwaraɺ@STAR_ZEROɺ@95kugoɺ@zaki50ɺ@itog
  2. 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. Architecture Components ͱ͸ • ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData •

    ViewModel • Room • Paging ݸผར༻OK ૊Έ߹Θͤར༻OK
  4. Architecture Components ͱ͸ • ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData •

    ViewModel • Room • Paging ࠓ೔ͷςʔϚ͸͜Ε લճ ࣍ճ * RxJava * ReactiveStreams * Dagger ʹ͍ͭͯ͸ࠓճ͸औΓ্͛·ͤΜ
  5. 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. 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. Lifecycles • Lifecycles = Lifecycle-aware Components • ϥΠϑαΠΫϧΛݕ஌͢Δίϯϙʔωϯτ • Activity

    ΍ Fragment ͷϥΠϑαΠΫϧঢ়ଶ͕มΘͬͨͱ͖ʹԿ͔ ΞΫγϣϯΛى͜͢ɺͱ͍͏͜ͱ͕Ͱ͖ΔΑ͏ʹͳΔ
  8. Lifecycle.State • ݱࡏͷϥΠϑαΠΫϧঢ়ଶΛද͢ enum • INITIALIZED • DESTROYED • CREATED

    • STARTED • RESUMED https://developer.android.com/topic/libraries/architecture/lifecycle.html
  9. ݱࡏͷϥΠϑαΠΫϧΛऔಘ΍؂ࢹ͢Δ 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) { // ... } })
  10. ओͳLiveData • LiveData (android.arch.lifecycle) ௨ৗͷ LiveData • MutableLiveData (android.arch.lifecycle) ֎෦͔ΒมߋՄೳͳ

    LiveData • MediatorLiveData (android.arch.lifecycle) ෳ਺ͷ LiveData ΛଋͶͯ؅ཧ͢Δ LiveData
  11. ViewModel • Activity ͷը໘ճస࣌ͷσʔλอ࣋ • Activity ͷෳ਺ Fragment ؒͰͷσʔλड͚౉͠ •

    LiveData ͱซ༻͢Δ͜ͱ͕ଟ͍ • ϓϩηεఀࢭޙ͸෮چͰ͖ͳ͍ • σʔλͷӬଓԽͰ͸ͳ͍
  12. 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()Ͱ΋Մ
  13. 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) อ͍࣋ͨ͠ΠϯελϯεΛฦ٫
  14. 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) औಘ
  15. @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ͷ಺෦࣮૷ΛҰ෦ൈਮ
  16. 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() { // ... } }
  17. class UserViewModel : ViewModel() { var disposables = CompositeDisposable() //

    ... override fun onCleared() { super.onCleared() // ϦʔΫ๷ࢭ౳ɺղ์͢Δ৔߹͸͜͜Ͱɻ disposables.dispose() } } ViewModel#onCleared()ͰϦʔΫ๷ࢭ
  18. 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͕ඞཁͳ৔߹ʹ࢖͑Δ
  19. 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͚ͩ
  20. 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ͷΈαϙʔτ͍ͯ͠Δ
  21. 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Λܧঝͨ͠ΫϥεΛࢦఆ͢Δ
  22. 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()ʹ౉ͨ͠ΫϥεʹΑͬͯΠϯελϯε͕ܾ·Δ
  23. 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ͷࢦఆ
  24. 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
  25. 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 {} ͦͷଞ
  26. ՝୊ 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
  27. ՝୊ 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
  28. ՝୊ 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
  29. ՝୊ 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
  30. ՝୊ 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
  31. ՝୊ 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
  32. ՝୊ 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
  33. 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()ʹ౉ͨ͠ΫϥεʹΑͬͯΠϯελϯε͕ܾ·Δ