Slide 1

Slide 1 text

Architecture Components ษڧձ ͕͑Θ Θ͞ͼʔ; ͋Β͖ ͋Μ͍͟Ώ͖ ୈ2ճ໨ LiveData

Slide 2

Slide 2 text

Architecture Componentsษڧձ ͱ͸ • Architecture Componentsͷجૅ஌ࣝʹֶ͍ͭͯͿษڧձ • ओ࠵ɿGDG Tokyo ϋογϡλά: #gdgtokyo • ߨࢣɺνϡʔλʔɿGoogleࣾһͱGoogle Developer Expert ʢ͋Μ͍͟Ώ͖ɺ ͕͑ΘɺΘ͞ͼʔ;ɺ͋Β͖ʣ

Slide 3

Slide 3 text

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 ՝୊औΓ૊Έ

Slide 4

Slide 4 text

Download Android Studio 3.1 Canary 8 https://developer.android.com/studio/preview/index.html?hl=ja

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Architecture Components ͱ͸ • ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData • ViewModel • Room • Paging ݸผར༻OK

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

Architecture Components ͱ͸ • ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Lifecycles • LiveData • ViewModel • Room • Paging ࠓ೔ͷςʔϚ͸͜Ε લճ ࣍ճ

Slide 9

Slide 9 text

LiveData

Slide 10

Slide 10 text

LiveData • observe (؂ࢹ) Մೳͳσʔλ • Activity/Fragment/Service ͳͲͷϥΠϑαΠΫϧΛҙࣝ (Lifecyclesͷ࢓૊ΈΛར༻ʣ • Ұൠతʹ͸ ViewModel ͱ࿈ܞͯ͠ར༻͢Δ (ViewModelͱViewͷؒͷކͷΑ͏ͳ໾໨ΛՌͨ͢ʣ

Slide 11

Slide 11 text

Lifecycles ͓͞Β͍

Slide 12

Slide 12 text

Lifecycles • Lifecycles = Lifecycle-aware Components • ϥΠϑαΠΫϧΛݕ஌͢Δίϯϙʔωϯτ • Activity ΍ Fragment ͷϥΠϑαΠΫϧঢ়ଶ͕มΘͬͨͱ͖ʹԿ͔ ΞΫγϣϯΛى͜͢ɺͱ͍͏͜ͱ͕Ͱ͖ΔΑ͏ʹͳΔ

Slide 13

Slide 13 text

Lifecycle.State • ݱࡏͷϥΠϑαΠΫϧঢ়ଶΛද͢ enum • INITIALIZED • DESTROYED • CREATED • STARTED • RESUMED https://developer.android.com/topic/libraries/architecture/lifecycle.html

Slide 14

Slide 14 text

Lifecycle.Event • ϥΠϑαΠΫϧঢ়ଶ͕มΘͬͨ࣌ͷΠϕϯτΛද͢ enum https://developer.android.com/topic/libraries/architecture/lifecycle.html • ON_CREATE • ON_START • ON_RESUME • ON_PAUSE • ON_STOP • ON_DESTROY • ON_ANY

Slide 15

Slide 15 text

FragmentActivity ͔Β Lifecycle Λऔಘ͢Δ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Lifecycle lifecycle = getLifecycle(); }

Slide 16

Slide 16 text

ݱࡏͷϥΠϑαΠΫϧΛऔಘ͢Δ final Lifecycle.State state = lifecycle.getCurrentState();

Slide 17

Slide 17 text

ϥΠϑαΠΫϧΛ؂ࢹ͢Δ lifecycle.addObserver(observer);

Slide 18

Slide 18 text

LiveData

Slide 19

Slide 19 text

ओͳLiveData • LiveData (android.arch.lifecycle) ௨ৗͷ LiveData • MutableLiveData (android.arch.lifecycle) ֎෦͔ΒมߋՄೳͳ LiveData • MediatorLiveData (android.arch.lifecycle) ෳ਺ͷ LiveData ΛଋͶͯ؅ཧ͢Δ LiveData * Java8 Language Support * RxJava * ReactiveStreams ʹ͍ͭͯ͸ࠓճ͸औΓ্͛·ͤΜ

Slide 20

Slide 20 text

android.arch.lifecycle.LiveData observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) ͜ͷLiveDataͷ஋Λ؂ࢹ͢Δ ༩͑ΒΕͨLifeCycleOwnerͷϥΠϑαΠΫϧ ʹैͬͯɺobserverʹ௨஌͞ΕΔ observerʹ௨஌͞ΕΔͷ͸ϥΠϑαΠΫϧ͕ ΞΫςΟϒͷͱ͖ͷΈ active

Slide 21

Slide 21 text

android.arch.lifecycle.LiveData observeForever(@NonNull Observer observer) ϥΠϑϥΠΫϧͷΞΫςΟϒঢ়ଶʹ͔͔ΘΒͣ௨஌Λड͚औΔ CREATED ͷঢ়ଶͰ΋௨஌Λड͚औΕΔ

Slide 22

Slide 22 text

android.arch.lifecycle.LiveData onActive() ΞΫςΟϒঢ়ଶʹ͋ΔΦϒβʔόʔ͕1Ҏ্ʹͳͬͨࡍʹݺ͹ΕΔ onInactive() ΞΫςΟϒঢ়ଶʹ͋ΔΦϒβʔόʔ͕1ະຬʹͳͬͨࡍʹݺ͹ΕΔ getValue() ݱࡏͷ஋Λฦ͢

Slide 23

Slide 23 text

android.arch.lifecycle.Observer onChanged(@Nullable T t) ஋͕มߋ͞Εͨࡍʹݺ͹ΕΔ LiveData ͔Βͷ஋Λड͚औΔγϯϓϧͳΠϯλϑΣʔε

Slide 24

Slide 24 text

android.arch.lifecycle.MutableLiveData ௨ৗͷ LiveData ͸֎෦͔Β஋ΛઃఆͰ͖ͳ͍ MutableLiveData ͸֎෦͔Β஋ΛઃఆՄೳͳϝιουΛެ։͍ͯ͠Δ

Slide 25

Slide 25 text

android.arch.lifecycle.MutableLiveData setValue(T value) ஋Λઃఆ͢ΔʢϝΠϯεϨουͰݺͼग़͢͜ͱʣ postValue(T value) ϝΠϯεϨου֎͔Β஋Λઃఆ͢Δࡍͷศརϝιου

Slide 26

Slide 26 text

android.arch.lifecycle.MediatorLiveData addSource(@NonNull LiveData source, @NonNull Observer onChanged) LiveData Λ௥Ճ͢Δ removeSource(@NonNull LiveData toRemote) LiveData Λ࡟আ͢Δ ෳ਺ͷ LiveData ΛଋͶͯ؅ཧͰ͖ΔΫϥε ܕͷҧ͏ෳ਺ͷLiveDataʹΠϕϯτΛ఻೻ͤ͞Δ͜ͱ͕Ͱ͖Δ

Slide 27

Slide 27 text

android.arch.lifecycle.Transformations static LiveData map(@NonNull LiveData source, @NonNull final Function func) LiveData ʹରͯؔ͠਺(func)Λద༻͠ɺผͷ LiveData ʹΠϕϯτΛ఻೻ͤ͞Δ static LiveData switchMap(@NonNull LiveData trigger, @NonNull final Function> func) mapͱྨࣅͨ͠ϝιου͕ͩؔ਺(func)಺͔Β LiveData Λฦ͢͜ͱ͕Ͱ͖Δ MediatorLiveData Λ࢖͍΍ͨ͘͢͠ϢʔςΟϦςΟ Java͔Β࢖͏ͱͱͯ΋μα͘ͳΔʂKotlinਪ঑

Slide 28

Slide 28 text

՝୊

Slide 29

Slide 29 text

՝୊ 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 Λ࢖ͬͯɺϥΠϑαΠΫϧ มߋ࣌ʹݱࡏͷϥΠϑαΠΫϧͷঢ়ଶΛϩάʹग़ྗ͢ΔΑ͏ʹ͢Δ • Ͱ͖ͨΒɺը໘Λดͨ͡Γɺ։͍ͨΓɺཪʹճͨ͠Γɺը໘Λճసͤͨ͞Γͯ͠ϥΠϑα ΠΫϧͷঢ়ଶ͕ͲͷΑ͏ʹมΘΔ͔Λ֬ೝ͢Δ

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

՝୊ 1 • ݱࡏ࣌ࠁͷ࣌෼ HH:MM Λը໘ʹදࣔ͢Δ࣌ܭΞϓϦΛ࡞Δ ʢϩέʔϧͳͲͷࡉ͔͍͜ͱ͸ؾʹ͠ͳ͍Ͱʣ activity_main.xml ͷ TextView ʹద౰ͳ id Λ͚ͭͯɺͦ͜ʹग़͢ • ·ͣ͸ɺݹ͍ํ๏Ͱ΍ͬͯΈΔ • Ұྫͱͯ͠ɺ࣍ͷϖʔδʹ ClockLegacy ΫϥεΛهࡌ͍ͯ͠·͢ɻ • ͜ͷΫϥεΛίϐϖͯ͠ MainActivity ͔Β࢖ͬͯԼ͍͞ • ࣗ෼Ͱ΍Γ͍ͨਓ͸͜ΕΛ࢖Θͣʹ޷͖ʹ࣮૷ͯ͘͠Εͯ΋͍͍Ͱ͢ɻ

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

՝୊ 2 • ݹ͍ํ๏ ClockLegacy Ϋϥεͷ࣮૷Λ LiveData Ͱॻ͖׵͑ͯΈΔ • ClockLiveData ΫϥεΛ࡞੒͢Δʢ࣍ͷϖʔδʹςϯϓϨ public class ClockLiveData extends LiveData { ... } • MainActivity ͷ onCreate ͷதͰ ClockLiveData ʹ observe ͢Δ ʢClockLegacy Λ࢖͏ͷ͸ࢭΊΔʣ

Slide 35

Slide 35 text

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 { 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

Slide 36

Slide 36 text

՝୊ 2 ͷ 2 • ClockLiveDataͷonActive, onInactive ʹϩάΛૠೖ͠ɺ͍ͭݺ͹Εͯ ͍Δ͔֬ೝ͠·͠ΐ͏ • HomeϘλϯΛԡͯ͠Recent Apps͔Β෮ؼͨ͠ͱ͖ʹɺ࣌෼ͷදࣔ͸Ͳ͏ͳ Δʁ • ͙͢ʹ෮ؼͤͨ͞৔߹͸ʁ਺෼଴͔ͬͯΒ෮ؼͤͨ͞৔߹͸ʁ • observe ϝιουͷ୅ΘΓʹ observeForever ϝιουΛ࢖ͬͨΒʁ • ը໘Λճసͤͨ͞ͱ͖͸ʁ • MainActivity ͔Β ClockLiveData ʹ௚઀ setValue ͠Α͏ͱͨ͠Βʁ

Slide 37

Slide 37 text

՝୊ 3 • ؆୯ͳ ViewModel Λͪΐͬͱ͚ͩ࢖ͬͯΈ·͠ΐ͏ • ClockLiveData ͷ਌Λ MutableLiveData ʹม͑ΔʢViewModel͔ΒΞΫηεͰ͖ΔΑ͏ʹʣ public class ClockLiveData extends MutableLiveData • ClockViewModel ΫϥεΛ৽ͨʹ࡞Δ public class ClockViewModel extends AndroidViewModel { private MutableLiveData clock; public ClockViewModel(@NonNull Application application) { super(application); } public LiveData 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

Slide 38

Slide 38 text

՝୊ 4 • σʔλόΠϯσΟϯάΛ࢖ͬͯ LiveDataͱ TextView Λܨ͛ͯΈ·͠ΐ͏ • build.gradle android { compileSdkVersion 27 dataBinding { enabled = true } ... • ClockLiveData ͸Ұ੾มߋ͠ͳ͍ͰɺܕҾ਺΋ Date ͷ··ͰʢStringʹ͠ͳ͍Ͱʣ΍ͬͯΈ·͠ΐ͏ • ҎԼͷ˚ͷΑ͏ͳํ๏΋͋ΓͰ͕͢ࠓճ͸ͳΔ΂͘ແ͠Ͱ Transformations ͰLiveDataΛม׵ͯ͠Լ͞ ͍ △ ○ ࢀߟɿσʔλόΠϯσΟϯά https://developer.android.com/topic/libraries/data-binding/index.html?hl=ja

Slide 39

Slide 39 text

ώϯτ: activity_main.xml ͷྫ https://gist.github.com/egglang/95fbd6d5748f54960030e51d07eab1e4

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

EOF