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

Android-ViewModel.pdf

TaeHwan
November 25, 2018

 Android-ViewModel.pdf

Androd TipTip
2018. 11. 25(Sun) Introduction in Android AAC-ViewModel

TaeHwan

November 25, 2018
Tweet

More Decks by TaeHwan

Other Decks in Programming

Transcript

  1. ࣗѐ • GDG Seoul ਍৔૓ • ٘۽੉٘ ա੉எ ਍৔૓ •

    RGP Korea • ਃӝਃ উ٘۽੉٘ ѐߊ • Blog : Է ݆਷ ѐߊ੗о غ ੗! (https://thdev.tech)
  2. ViewModel ੜ ঌӝ • ViewModel ҳઑ ঌӝ • ViewModelਸ ٜ݅ӝ

    ਤೠ بҳ • ViewModelਸ ੜ ഝਊೞӝ ਤೠ ܻ࠙ • ܻ࠙ೞ׮ ࠁݶ ࢤӝח Ҋ޹ • ؊ ա਷ ViewModel
  3. ViewModel View Model DataBinding and commands ViewModel updates the model

    Send notifications Send notifications ViewModel ҳઑ ঌӝ
  4. ViewModelਸ ٜ݅ӝ ਤೠ بҳ • View ViewModel р੄ ҙ҅ܳ ױ੺

    दఃӝ ਤೠ ݾ੸ • DI(Dagger, koin) ഝਊೞৈ Ѿ೤بܳ ઴ੋ׮. • DataBinding ഝਊਵ۽ View৬੄ ੄ઓبܳ ઴ੋ׮.
  5. ViewModelਸ ੜ ഝਊೞӝ ਤೠ ܻ࠙ • ViewModelҗ Model਷ ৉ೡী ٮۄ

    ୭؀ೠ ܻ࠙ೠ׮ • ܻ࠙ೡ ࣻ ੓ח ೠ ୭؀۽ ܻ࠙ೞৈ, ৮੹ೠ Factory pattern ୶ҳ
  6. ܻ࠙ೞ׮ ࠁݶ ࢤӝח Ҋ޹ • അप਷ DataBinding੄ Ѿ೤بо ֫ইઉ ৮੹ೠ

    ഋకܳ ٜ݅ӝ औ૑ ঋ׮ • ழझథ ࠭৬ DataBindingਸ ୭؀ೠ ഝਊೞח ഋక۽ ࢸ҅ೡ ೙ਃо ੓׮
  7. ؊ ա਷ ViewModel • ղࠗীࢲ ࢎਊೞח Rx/Coroutines ١ਸ ਤೠ ۄ੉೐

    ࢎ੉௿ਸ ٮܰب۾ ࢸ҅ೡ ೙ਃо ੓׮ • ૒੽ Lifecycle ଻ਊೞח ഋక۽ ѐߊ ೙ਃ • AAC-ViewModelਸ ഝਊೞѢա
  8. AAC-ViewModel ݾ੸ • The ViewModel class is designed to store

    and manage UI-related data in a lifecycle conscious way. The ViewModel class allows data to survive configuration changes such as screen rotations. • Android AAC ViewModel਷ ചݶ ഥ੹ द ؘ੉ఠܳ ਬ૑ೡ ࣻ ੓ח ҳઑ۽ ٣੗ੋೞ৓ਵݴ, Android Lifecycle੄ onDestroy() ௏٘о ز੘ೠ׮. https://developer.android.com/topic/libraries/architecture/viewmodel
  9. AAC-ViewModel ੿ܻೞݶ • ݾ੸ : ചݶ ഥ੹ द ؘ੉ఠ ਬ૑ܳ

    ਤೠ ҳઑ۽ ViewModelਸ ٣੗ੋ • Activity/Fragment੄ Lifecycleী ٮۄ ViewModel ਬ૑ܳ ೞҊ ੓׮. • ղࠗীࢲ Lifecycleਸ ࢎਊೡ ࣻ ੓ب۾ ୡӝചೞҊ ੓ਵݴ, onDestroy() ز੘ द ViewModel ղ ࠗ੄ onCleared() ഐ୹ਸ ా೧ Releaseܳ ਬبೠ׮.
  10. AAC-ViewModel • AAC ViewModel਷ Androidীࢲ ࢎਊ਷ оמೞ૑݅ • MSDN੄ ViewModelҗח

    ইޖ ࢚ҙহҊ, Ӓր ੉ܴ ݅ ViewModel੐ਸ ঌҊ о੗ • উ٘۽੉٘ ѐߊ ಞ੄ࢿਸ ୶ҳೞח ViewModel ੿ب۽ ౵ঈೞ੗ • ಞ੄࢚ Application ઱ੑ੉ оמೞҊ • ಞ੄࢚ AAC-ViewModel਷ ؘ੉ఠ ਬ૑ب ೧ળ׮
  11. AAC-ViewModel ୡӝച • AAC-ViewModel ୡӝചח ViewModelProviders۽ ୡӝചೠ׮ • Activity/Fragment 2ѐ

    ઺ী ೞա۽ ୡӝച оמ • ӝࠄ ViewModel ࢤࢿ੗ ߧਤܳ ߩযաݶ Factoryܳ ࢚ࣘ߉ই ߹ب ҳഅ೧ঠ ೠ׮
  12. AAC-ViewModel class MasterFragment : Fragment() { private lateinit var itemSelector:

    Selector private lateinit var model: SharedViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) model = activity?.run { ViewModelProviders.of(this).get(SharedViewModel::class.java) } ?: throw Exception("Invalid Activity") itemSelector.setOnClickListener { item -> // Update the UI } } } ViewModelProviders.of(this)
  13. ViewModelProviders.of(this) • thisী Activity/Fragment۽੄ ୡӝചо оמ • Activity ࢎਊ द

    Activity Lifecycleਸ ٮܲ׮ • Fragment ࢎਊ द Fragment Lifecycleਸ ٮܲ׮
  14. ViewModelProviders.of(this) ӝࠄ ੿੄ @NonNull @MainThread public static ViewModelProvider of(@NonNull Fragment

    fragment) { return of(fragment, null); } @NonNull @MainThread public static ViewModelProvider of(@NonNull FragmentActivity activity) { return of(activity, null); }
  15. ViewModelProviders.of(this) Factory ੿੄ @NonNull @MainThread public static ViewModelProvider of(@NonNull Fragment

    fragment, @Nullable Factory factory) { Application application = checkApplication(checkActivity(fragment)); if (factory == null) { factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); } return new ViewModelProvider(fragment.getViewModelStore(), factory); } @NonNull @MainThread public static ViewModelProvider of(@NonNull FragmentActivity activity, @Nullable Factory factory) { Application application = checkApplication(activity); if (factory == null) { factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); } return new ViewModelProvider(activity.getViewModelStore(), factory); } fragment.getViewModelStore() activity.getViewModelStore() ViewModelStore()ܳ ా೧ ӝઓ ViewModel ࢤࢿ ؘ੉ఠо թওח૑ ୓௼ ViewModelStore()ܳ ా೧ ӝઓ ViewModel ࢤࢿ ؘ੉ఠо թওח૑ ୓௼
  16. Fragment.java @NonNull @Override public ViewModelStore getViewModelStore() { if (getContext() ==

    null) { throw new IllegalStateException("Can't access ViewModels from detached fragment"); } if (mViewModelStore == null) { mViewModelStore = new ViewModelStore(); } return mViewModelStore; }
  17. FragmentActivity.java @NonNull @Override public ViewModelStore getViewModelStore() { if (getApplication() ==

    null) { throw new IllegalStateException("Your activity is not yet attached to the " + "Application instance. You can't request ViewModel before onCreate call."); } if (mViewModelStore == null) { NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc != null) { // Restore the ViewModelStore from NonConfigurationInstances mViewModelStore = nc.viewModelStore; } if (mViewModelStore == null) { mViewModelStore = new ViewModelStore(); } } return mViewModelStore; }
  18. ViewModelStore.java package androidx.lifecycle; public class ViewModelStore { private final HashMap<String,

    ViewModel> mMap = new HashMap<>(); final void put(String key, ViewModel viewModel) { ViewModel oldViewModel = mMap.put(key, viewModel); if (oldViewModel != null) { oldViewModel.onCleared(); } } final ViewModel get(String key) { return mMap.get(key); } /** * Clears internal storage and notifies ViewModels that they are no longer used. */ public final void clear() { for (ViewModel vm : mMap.values()) { vm.onCleared(); } mMap.clear(); } }
  19. AAC-ViewModel class MasterFragment : Fragment() { private lateinit var itemSelector:

    Selector private lateinit var model: SharedViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) model = activity?.run { ViewModelProviders.of(this).get(SharedViewModel::class.java) } ?: throw Exception("Invalid Activity") itemSelector.setOnClickListener { item -> // Update the UI } } } ViewModelProviders.of(this) get(SharedViewModel::class.java)
  20. get(SharedViewModel::class.java) • Activity/Fragmentীࢲ ࠁҙ ઺ੋ ViewModelStore ё୓ܳ ੉ਊೞৈ getਸ ୊ܻ

    • getীࢲח ࢜۽਍ ё୓ܳ ࢤࢿೞѢա, ViewModelStoreী ӝઓ ё୓ܳ ׮द ࠛ۞ৡ׮ • HashMapী ੷੢ೞӝ ਤೠ Ҋਬఃܳ ੿੄ೠ׮.
  21. get(Class<T>) / Ҋਬః @NonNull @MainThread public <T extends ViewModel> T

    get(@NonNull Class<T> modelClass) { String canonicalName = modelClass.getCanonicalName(); if (canonicalName == null) { throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels"); } return get(DEFAULT_KEY + ":" + canonicalName, modelClass); } private static final String DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey"; Default৬ canonicalNameਸ ೤୛ Ҋਬః ࢤࢿ Package name.SharedViewModel
  22. get(Key, Class<T>) @NonNull @MainThread public <T extends ViewModel> T get(@NonNull

    String key, @NonNull Class<T> modelClass) { ViewModel viewModel = mViewModelStore.get(key); if (modelClass.isInstance(viewModel)) { //noinspection unchecked return (T) viewModel; } else { //noinspection StatementWithEmptyBody if (viewModel != null) { // TODO: log a warning. } } viewModel = mFactory.create(modelClass); mViewModelStore.put(key, viewModel); //noinspection unchecked return (T) viewModel; } ViewModelStore۽ࠗఠ getValue viewModel੉ null੉ ইפݶ return null੉ݶ ViewModelFactory۽ࠗఠ new Factoryח ӝࠄ ViewModelFactory ੿੄о ઓ੤ ViewModelStoreী put
  23. ViewModelFactory @NonNull @MainThread public static ViewModelProvider of(@NonNull Fragment fragment, @Nullable

    Factory factory) { Application application = checkApplication(checkActivity(fragment)); if (factory == null) { factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); } return new ViewModelProvider(fragment.getViewModelStore(), factory); } @NonNull @MainThread public static ViewModelProvider of(@NonNull FragmentActivity activity, @Nullable Factory factory) { Application application = checkApplication(activity); if (factory == null) { factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); } return new ViewModelProvider(activity.getViewModelStore(), factory); } fragment.getViewModelStore() activity.getViewModelStore() Factory ੿੄ܳ ೞ૑ ঋਵݶ AndroidViewModelFactoryࢎਊ Factory ੿੄ܳ ೞ૑ ঋਵݶ AndroidViewModelFactoryࢎਊ if (factory == null) { factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); } if (factory == null) { factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); }
  24. ViewModelFactory Application ೞա݅ ੓ਸ ҃਋ /** * {@link Factory} which

    may create {@link AndroidViewModel} and * {@link ViewModel}, which have an empty constructor. */ public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory { private static AndroidViewModelFactory sInstance; /** * Retrieve a singleton instance of AndroidViewModelFactory. * * @param application an application to pass in {@link AndroidViewModel} * @return A valid {@link AndroidViewModelFactory} */ @NonNull public static AndroidViewModelFactory getInstance(@NonNull Application application) { if (sInstance == null) { sInstance = new AndroidViewModelFactory(application); } return sInstance; } private Application mApplication; /** * Creates a {@code AndroidViewModelFactory} * * @param application an application to pass in {@link AndroidViewModel} */ public AndroidViewModelFactory(@NonNull Application application) { mApplication = application;
  25. ViewModelFactory ࢤࢿ੗о হח ҃਋ public static class NewInstanceFactory implements Factory

    { @SuppressWarnings("ClassNewInstance") @NonNull @Override public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { //noinspection TryWithIdenticalCatches try { return modelClass.newInstance(); } catch (InstantiationException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (IllegalAccessException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } } }
  26. ViewModelFactory ழझథ ࢤࢿ੗о ੓׮ݶ? class SharedViewModelFactory(data data data) : ViewModelProvider.Factory

    { override fun <T : ViewModel?> create(modelClass: Class<T>): T { return SharedViewModel(data, data, data) as T } } ViewModelProviders.of(this, SharedViewModelFactory(data, data, data)).get(SharedViewModel::class.java)
  27. FragmentActivity.java /** * Destroy all fragments. */ @Override protected void

    onDestroy() { super.onDestroy(); if (mViewModelStore != null && !isChangingConfigurations()) { mViewModelStore.clear(); } mFragments.dispatchDestroy(); }
  28. FragmentActivity.java /** * Called when the fragment is no longer

    in use. This is called * after {@link #onStop()} and before {@link #onDetach()}. */ @CallSuper public void onDestroy() { mCalled = true; FragmentActivity activity = getActivity(); boolean isChangingConfigurations = activity != null && activity.isChangingConfigurations(); if (mViewModelStore != null && !isChangingConfigurations) { mViewModelStore.clear(); } }
  29. ViewModelStore.java /** * Clears internal storage and notifies ViewModels that

    they are no longer used. */ public final void clear() { for (ViewModel vm : mMap.values()) { vm.onCleared(); } mMap.clear(); }
  30. ViewModel.java public abstract class ViewModel { /** * This method

    will be called when this ViewModel is no longer used and will be destroyed. * <p> * It is useful when ViewModel observes some data and you need to clear this subscription to * prevent a leak of this ViewModel. */ @SuppressWarnings("WeakerAccess") protected void onCleared() { } }
  31. ਬਊೠ ViewModel? • Activity੄ ചݶ ഥ੹ द ؘ੉ఠ ਬ૑о ೙ਃೠ

    ҃਋ ਬਊೞ׮. • 1ѐ੄ Activityীࢲ ׮઺੄ Fragmentীࢲ زੌೠ ੉߮౟/ؘ੉ఠܳ ୊ܻೞҊ रਸ ҃਋ • onClearedীࢲ releaseо ೙ਃೞ׮
  32. 1ѐ੄ Activityীࢲ ׮઺੄ Fragment • Fragmentীࢲ fragmentо ইצ activityܳ ֈѹળ׮.

    • ViewModelProviders.of(activity).get(SharedViewModel::class.java)
  33. RxJava disposable abstract class BaseViewModel : ViewModel() { val disposable:

    CompositeDisposable = CompositeDisposable() override fun onCleared() { super.onCleared() disposable.clear() } }
  34. Coroutines cancel abstract class BaseViewModel : ViewModel(), CoroutineScope { val

    job: Job = Job() override val coroutineContext: CoroutineContext get() = Dispatchers.Default + job override fun onCleared() { super.onCleared() job.cancel() } }