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

GDG Tokyo Android Architecture Components - Liv...

GDG Tokyo Android Architecture Components - LiveData

GDG Tokyo Techtalk Android Architecture Components - LiveData on Jan 24, 2018.

Takashi EGAWA

January 24, 2018
Tweet

More Decks by Takashi EGAWA

Other Decks in Programming

Transcript

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

    #gdgtokyo • ߨࢣɺνϡʔλʔɿGoogleࣾһͱGoogle Developer Expert ʢ͋Μ͍͟Ώ͖ɺ ͕͑ΘɺΘ͞ͼʔ;ɺ͋Β͖ʣ
  2. Architecture Componentsษڧձ ͱ͸ • ܭ4ճͷ༧ఆ • ୈ1ճ:Handling Lifecycles • ୈ2ճ:LiveData

    • ୈ3ճ:ViewModel • ୈ4ճ:Room λΠϜςʔϒϧ 19:30ʙ19:35 ѫࡰˍઆ໌ 19:35ʙ20:15 LiveData ͷઆ໌ 20:15ʙ20:25 ٳܜ 20:25ʙ22:00 ՝୊औΓ૊Έ
  3. Architecture Components ͱ͸ • ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData •

    ViewModel • Room • Paging ݸผར༻OK ૊Έ߹Θͤར༻OK
  4. LiveData • observe (؂ࢹ) Մೳͳσʔλ • Activity/Fragment/Service ͳͲͷϥΠϑαΠΫϧΛҙࣝ (Lifecyclesͷ࢓૊ΈΛར༻ʣ •

    Ұൠతʹ͸ ViewModel ͱ࿈ܞͯ͠ར༻͢Δ (ViewModelͱViewͷؒͷކͷΑ͏ͳ໾໨ΛՌͨ͢ʣ
  5. Lifecycles • Lifecycles = Lifecycle-aware Components • ϥΠϑαΠΫϧΛݕ஌͢Δίϯϙʔωϯτ • Activity

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

    • STARTED • RESUMED https://developer.android.com/topic/libraries/architecture/lifecycle.html
  7. FragmentActivity ͔Β Lifecycle Λऔಘ͢Δ public class MainActivity extends AppCompatActivity {

    @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Lifecycle lifecycle = getLifecycle(); }
  8. ओͳLiveData • LiveData (android.arch.lifecycle) ௨ৗͷ LiveData • MutableLiveData (android.arch.lifecycle) ֎෦͔ΒมߋՄೳͳ

    LiveData • MediatorLiveData (android.arch.lifecycle) ෳ਺ͷ LiveData ΛଋͶͯ؅ཧ͢Δ LiveData * Java8 Language Support * RxJava * ReactiveStreams ʹ͍ͭͯ͸ࠓճ͸औΓ্͛·ͤΜ
  9. android.arch.lifecycle.MediatorLiveData<T> addSource(@NonNull LiveData<S> source, @NonNull Observer<S> onChanged) LiveData Λ௥Ճ͢Δ removeSource(@NonNull

    LiveData<S> toRemote) LiveData Λ࡟আ͢Δ ෳ਺ͷ LiveData ΛଋͶͯ؅ཧͰ͖ΔΫϥε ܕͷҧ͏ෳ਺ͷLiveDataʹΠϕϯτΛ఻೻ͤ͞Δ͜ͱ͕Ͱ͖Δ
  10. android.arch.lifecycle.Transformations static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source, @NonNull final

    Function<X, Y> func) LiveData ʹରͯؔ͠਺(func)Λద༻͠ɺผͷ LiveData ʹΠϕϯτΛ఻೻ͤ͞Δ static <X, Y> LiveData<Y> switchMap(@NonNull LiveData<X> trigger, @NonNull final Function<X, LiveData<Y>> func) mapͱྨࣅͨ͠ϝιου͕ͩؔ਺(func)಺͔Β LiveData Λฦ͢͜ͱ͕Ͱ͖Δ MediatorLiveData Λ࢖͍΍ͨ͘͢͠ϢʔςΟϦςΟ Java͔Β࢖͏ͱͱͯ΋μα͘ͳΔʂKotlinਪ঑
  11. ՝୊ 0 • Empty Activity Ͱ৽͍͠ϓϩδΣΫτΛ࡞Δ ʢύοέʔδ໊͸ com.example.livedatacodelab Λ૝ఆʣ •

    build.grade dependencies { implementation “com.android.support:appcompat-v7:27.0.2” … implementation "android.arch.lifecycle:extensions:1.1.0" annotationProcessor "android.arch.lifecycle:compiler:1.1.0" } • MainActivity ͷ onCreate ͷதͰ LifecycleObserver Λ࢖ͬͯɺϥΠϑαΠΫϧ มߋ࣌ʹݱࡏͷϥΠϑαΠΫϧͷঢ়ଶΛϩάʹग़ྗ͢ΔΑ͏ʹ͢Δ • Ͱ͖ͨΒɺը໘Λดͨ͡Γɺ։͍ͨΓɺཪʹճͨ͠Γɺը໘Λճసͤͨ͞Γͯ͠ϥΠϑα ΠΫϧͷঢ়ଶ͕ͲͷΑ͏ʹมΘΔ͔Λ֬ೝ͢Δ
  12. public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle

    savedInstanceState) { super.onCreate(savedInstanceState); … final LifecycleObserver lifecycleObserver = new LifecycleObserver() { @OnLifecycleEvent(Lifecycle.Event.ON_ANY) public void calledWhenOnAny(LifecycleOwner source, Lifecycle.Event event) { Log.d("CODELAB", "Lifecycle state:" + source.getLifecycle().getCurrentState().name()); } }; getLifecycle().addObserver(lifecycleObserver); } } ྫ https://gist.github.com/egglang/f9014730def32395daae657429a08f1b
  13. ՝୊ 1 • ݱࡏ࣌ࠁͷ࣌෼ HH:MM Λը໘ʹදࣔ͢Δ࣌ܭΞϓϦΛ࡞Δ ʢϩέʔϧͳͲͷࡉ͔͍͜ͱ͸ؾʹ͠ͳ͍Ͱʣ activity_main.xml ͷ TextView

    ʹద౰ͳ id Λ͚ͭͯɺͦ͜ʹग़͢ • ·ͣ͸ɺݹ͍ํ๏Ͱ΍ͬͯΈΔ • Ұྫͱͯ͠ɺ࣍ͷϖʔδʹ ClockLegacy ΫϥεΛهࡌ͍ͯ͠·͢ɻ • ͜ͷΫϥεΛίϐϖͯ͠ MainActivity ͔Β࢖ͬͯԼ͍͞ • ࣗ෼Ͱ΍Γ͍ͨਓ͸͜ΕΛ࢖Θͣʹ޷͖ʹ࣮૷ͯ͘͠Εͯ΋͍͍Ͱ͢ɻ
  14. import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import java.util.Calendar;

    import java.util.Date; public class ClockLegacy { private final Context mAppContext; public interface ClockListener { void onReceive(Date date); } private ClockListener mListener; private BroadcastReceiver mTimeTickBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (mListener != null) { mListener.onReceive(Calendar.getInstance().getTime()); } } }; public ClockLegacy(Context appContext) { mAppContext = appContext; } public void setClockListener(ClockListener listener) { if (mListener != null) { return; } mListener = listener; IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_TIME_TICK); mAppContext.registerReceiver(mTimeTickBroadcastReceiver, intentFilter); } public void removeClockListener() { mListener = null; mAppContext.unregisterReceiver(mTimeTickBroadcastReceiver); } } https://gist.github.com/egglang/ae119ac753b901bbd2301dc323fd7402
  15. private TextView mText; private ClockLegacy.ClockListener mListener = new ClockLegacy.ClockListener() {

    @Override public void onReceive(Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); String dateString = String.format("%02d:%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); mText.setText(dateString); Log.d("CODELAB", “The current time is " + dateString); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); .. mText = findViewById(R.id.text); mClockData = new ClockLegacy(getApplicationContext()); final LifecycleObserver observer = new LifecycleObserver() { @OnLifecycleEvent(Lifecycle.Event.ON_START) public void calledWhenOnStart(LifecycleOwner source) { mClockData.setClockListener(mListener); } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void calledWhenOnStop(LifecycleOwner source) { mClockData.removeClockListener(); } }; getLifecycle().addObserver(observer); } ClockLegacy Λ࢖ͬͨ MainActivity ͷ࣮૷ྫ https://gist.github.com/egglang/8862bc8ed7131dc5b847dcd5680a2d4e
  16. ՝୊ 2 • ݹ͍ํ๏ ClockLegacy Ϋϥεͷ࣮૷Λ LiveData Ͱॻ͖׵͑ͯΈΔ • ClockLiveData

    ΫϥεΛ࡞੒͢Δʢ࣍ͷϖʔδʹςϯϓϨ public class ClockLiveData extends LiveData<Date> { ... } • MainActivity ͷ onCreate ͷதͰ ClockLiveData ʹ observe ͢Δ ʢClockLegacy Λ࢖͏ͷ͸ࢭΊΔʣ
  17. import android.arch.lifecycle.LiveData; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter;

    import android.util.Log; import java.util.Calendar; import java.util.Date; public class ClockLiveData extends LiveData<Date> { private final Context mAppContext; private BroadcastReceiver mTimeTickBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // ... } }; public ClockLiveData(Context appContext) { mAppContext = appContext; } @Override protected void onActive() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_TIME_TICK); mAppContext.registerReceiver(mTimeTickBroadcastReceiver, intentFilter); } @Override protected void onInactive() { mAppContext.unregisterReceiver(mTimeTickBroadcastReceiver); } } https://gist.github.com/egglang/319231352e5538bfb9641634480aee04
  18. ՝୊ 2 ͷ 2 • ClockLiveDataͷonActive, onInactive ʹϩάΛૠೖ͠ɺ͍ͭݺ͹Εͯ ͍Δ͔֬ೝ͠·͠ΐ͏ •

    HomeϘλϯΛԡͯ͠Recent Apps͔Β෮ؼͨ͠ͱ͖ʹɺ࣌෼ͷදࣔ͸Ͳ͏ͳ Δʁ • ͙͢ʹ෮ؼͤͨ͞৔߹͸ʁ਺෼଴͔ͬͯΒ෮ؼͤͨ͞৔߹͸ʁ • observe ϝιουͷ୅ΘΓʹ observeForever ϝιουΛ࢖ͬͨΒʁ • ը໘Λճసͤͨ͞ͱ͖͸ʁ • MainActivity ͔Β ClockLiveData ʹ௚઀ setValue ͠Α͏ͱͨ͠Βʁ
  19. ՝୊ 3 • ؆୯ͳ ViewModel Λͪΐͬͱ͚ͩ࢖ͬͯΈ·͠ΐ͏ • ClockLiveData ͷ਌Λ MutableLiveData

    ʹม͑ΔʢViewModel͔ΒΞΫηεͰ͖ΔΑ͏ʹʣ public class ClockLiveData extends MutableLiveData<Date> • ClockViewModel ΫϥεΛ৽ͨʹ࡞Δ public class ClockViewModel extends AndroidViewModel { private MutableLiveData<Date> clock; public ClockViewModel(@NonNull Application application) { super(application); } public LiveData<Date> getClock() { if (clock == null) { clock = new ClockLiveData(getApplication()); } return clock; } } • MainActivity ͷ onCreate Ͱ ViewModel Λऔಘ͠ɺgetClock Ͱ observer Λઃఆ͢Δ ClockViewModel clockViewModel = ViewModelProviders.of(this).get(ClockViewModel.class); clockViewModel.getClock().observe(...); • Ͱ͖ͨΒɺը໘Λճసͤͨ͞ͱ͖ʹ࣌෼ͷද͕ࣔͲ͏ͳΔ͔༡ΜͰΈͯԼ͍͞ ViewModelͷৄࡉ͸ ࣍ճʹ΍Γ·͢ͷͰ ਂ͘ߟ͑ͳ͍ͰԼ͍͞ https://gist.github.com/egglang/221a0dcb016d80766cabee91fe42d476
  20. ՝୊ 4 • σʔλόΠϯσΟϯάΛ࢖ͬͯ LiveDataͱ TextView Λܨ͛ͯΈ·͠ΐ͏ • build.gradle android

    { compileSdkVersion 27 dataBinding { enabled = true } ... • ClockLiveData ͸Ұ੾มߋ͠ͳ͍ͰɺܕҾ਺΋ Date ͷ··ͰʢStringʹ͠ͳ͍Ͱʣ΍ͬͯΈ·͠ΐ͏ • ҎԼͷ˚ͷΑ͏ͳํ๏΋͋ΓͰ͕͢ࠓճ͸ͳΔ΂͘ແ͠Ͱ Transformations ͰLiveDataΛม׵ͯ͠Լ͞ ͍ △ <TextView android:text="@{DateFormatUtils.format(hoge, `HH:mm`)}" /> ◦ <TextView android:text=“@{foo.bar)}" /> ࢀߟɿσʔλόΠϯσΟϯά https://developer.android.com/topic/libraries/data-binding/index.html?hl=ja
  21. <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="clockModel" type="com.example.livedatacodelab.ClockViewModel"/>

    </data> <android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{clockModel.clock}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"/> </android.support.constraint.ConstraintLayout> </layout> ώϯτ: activity_main.xml ͷྫ https://gist.github.com/egglang/95fbd6d5748f54960030e51d07eab1e4
  22. package com.example.livedatacodelab; import android.arch.lifecycle.ViewModelProviders; import android.databinding.DataBindingUtil; import android.os.Bundle; import android.support.v7.app.AppCompatActivity;

    import com.example.livedatacodelab.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ClockViewModel clockViewModel = ViewModelProviders.of(this).get(ClockViewModel.class); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.setLifecycleOwner(this); binding.setClockModel(clockViewModel); } } ώϯτ: MainActivity ͷྫ https://gist.github.com/egglang/e7aef650555b932298d6a0c21917c889
  23. EOF