Slide 1

Slide 1 text

CA.apk #3 Google I/O 2017 ใࠂձ @CyberAgent Masaki Ogata ArchitectureComponents Lifecycle library :)

Slide 2

Slide 2 text

ࣗݾ঺հ Masaki Ogata CyberAgent, Inc. / AbemaTV, Inc. ogaclejapan @ogaclejapan New

Slide 3

Slide 3 text

͍ͭʹ… ॳ౰બ͠·ͨ͠

Slide 4

Slide 4 text

ॳI/O ŝŦŝŦŝŦŝŦᴸᴸᴸ ƅ㱼ƅ㲇 ƅ㱼ƅ㲇ƅ㱼ƅ)㲇ƅ㱼ƅ)ᴸᴸᴸᴸ!!

Slide 5

Slide 5 text

Google Keynote

Slide 6

Slide 6 text

Google Keynote

Slide 7

Slide 7 text

What’s new for Android TV

Slide 8

Slide 8 text

Single Codebase, Two Apps with Flutter and Firebase

Slide 9

Slide 9 text

Google Play Awards

Slide 10

Slide 10 text

Google Play Awards

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

allprojects { repositories { jcenter() maven { url 'https://maven.google.com' } } } dependencies { compile "android.arch.lifecycle:runtime:1.0.0-alpha1" compile "android.arch.lifecycle:extensions:1.0.0-alpha1" annotationProcessor "android.arch.lifecycle:compiler: 1.0.0-alpha1" } 1. Add the Google Maven repository 2. Add Architecture Components - Lifecycle

Slide 14

Slide 14 text

Handling Lifecycles

Slide 15

Slide 15 text

ϥΠϑαΠΫϧΛ΋ͭ͜ͱΛࣔ͢ΠϯλϑΣʔε • LifecycleOwner public interface LifecycleOwner { Lifecycle getLifecycle(); } • LifecycleRegistryOwner (※Temporary) public interface LifecycleRegistryOwner extends LifecycleOwner { @Override LifecycleRegistry getLifecycle(); }

Slide 16

Slide 16 text

ݱঢ়Ͱ͸LifecycleActivity, LifecycleFragment, LifecycleServiceΫϥε͕ϥΠϒϥϦ಺ʹ༻ҙ͞Ε͍ͯΔ public class LifecycleActivity extends FragmentActivity implements LifecycleRegistryOwner { private final LifecycleRegistry mRegistry = new LifecycleRegistry(this); @Override public LifecycleRegistry getLifecycle() { return mRegistry; } } ※Alpha൛ͩͱAppCompatActivity൛͸࣮૷͍ͯ͠ͳ͍

Slide 17

Slide 17 text

AppCompatActivityͰLifecycleΛࢼ͍ͨ͠ਓ͸ࣗલͰ public class LifecycleCompatActivity extends AppCompatActivity implements LifecycleRegistryOwner { private final LifecycleRegistry mRegistry = new LifecycleRegistry(this); @Override public LifecycleRegistry getLifecycle() { return mRegistry; } } Ϋϥε಺ͷ࣮૷ίʔυ͸LifecycleActivityͱશ͘ಉ͡ɻ
 ͜Ε͚ͩͰࣗಈతʹϥΠϑαΠΫϧʹԠͯͪ͡ΌΜͱಈ͘

Slide 18

Slide 18 text

ϥΠϑαΠΫϧΛ؍ଌ͢ΔͨΊͷΠϯλϑΣʔε • LifecycleObserver public interface LifecycleObserver { }

Slide 19

Slide 19 text

ϥΠϑαΠΫϧΛ؍ଌ͢ΔͨΊͷΠϯλϑΣʔε • LifecycleObserver public interface LifecycleObserver { } public class FooObserver implements LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_START) void start() { /* Start something. */ } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) void stop() { /* Stop something. */ } }

Slide 20

Slide 20 text

͋ͱ͸LifecycleOwnerͷLifecycleΫϥεʹadd͢Δ͚ͩ public class FooActivity extends LifecycleActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... getLifecycle().addObserver(new FooObserver()); } }

Slide 21

Slide 21 text

͋ͱ͸LifecycleOwnerͷLifecycleΫϥεʹadd͢Δ͚ͩ public class FooActivity extends LifecycleActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... getLifecycle().addObserver(new FooObserver()); } } FooActivity: ⇠ onStart [0ms] FooObserver: Start something. FooActivity: ⇢ onResume() ... FooActivity: ⇠ onPause [0ms] FooObserver: Stop something. FooActivity: ⇢ onStop() ActivityͷϥΠϑαΠΫϧʹϩά Λ࢓ࠐΜͰ࣮ߦͯ͠ΈΔͱ…

Slide 22

Slide 22 text

“Lifecycle-aware components” public class FooObserver implements LifecycleObserver { public FooObserver(Lifecycle lifecycle) { ... this.lifecycle.addObserver(this); } @OnLifecycleEvent(Lifecycle.Event.ON_START) void start() { /* Start something. */ } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) void stop() { /* "Stop something." */ } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) void cleanup() { lifecycle.removeObserver(this); } }

Slide 23

Slide 23 text

LifecycleΫϥε public abstract class Lifecycle { public abstract void addObserver(LifecycleObserver observer); public abstract void removeObserver(LifecycleObserver observer); public abstract State getCurrentState(); public enum Event { ON_CREATE, ON_START, ...ON_ANY } public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; public boolean isAtLeast(State state) { return compareTo(state) >= 0; } } }

Slide 24

Slide 24 text

LifecycleΫϥε public abstract class Lifecycle { public abstract void addObserver(LifecycleObserver observer); public abstract void removeObserver(LifecycleObserver observer); public abstract State getCurrentState(); public enum Event { ON_CREATE, ON_START, ...ON_ANY } public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; public boolean isAtLeast(State state) { return compareTo(state) >= 0; } } }

Slide 25

Slide 25 text

https://developer.android.com/topic/libraries/architecture/lifecycle.html class MyLocationListener implements LifecycleObserver { public void enable() { enabled = true; if (lifecycle.getState().isAtLeast(STARTED)) { // connect if not connected } }

Slide 26

Slide 26 text

Deep dive into Lifecycles

Slide 27

Slide 27 text

1. LifecycleObserverͷ಺෦࣮૷͸ʁ

Slide 28

Slide 28 text

AnnotationProcessorʹΑΓࣗಈੜ੒͞ΕͨFooObserver public class FooObserver_LifecycleAdapter implements GenericLifecycleObserver { final FooObserver mReceiver; ... @Override public void onStateChanged(LifecycleOwner owner, Lifecycle.Event event) { if (event == Lifecycle.Event.ON_START) { mReceiver.start(); } if (event == Lifecycle.Event.ON_STOP) { mReceiver.stop(); } } } ※GenericLifecycleObserver͸@hideͳΫϥε

Slide 29

Slide 29 text

LifecycleRegistryΫϥε public class LifecycleRegistry extends Lifecycle { @Override public void addObserver(LifecycleObserver observer) { ObserverWithState observerWithState = new ObserverWithState(observer); mObserverSet.putIfAbsent(observer, observerWithState); observerWithState.sync(); } ... class ObserverWithState { private State mObserverCurrentState = INITIALIZED; private GenericLifecycleObserver mCallback; ObserverWithState(LifecycleObserver observer) { mCallback = Lifecycling.getCallback(observer); } }

Slide 30

Slide 30 text

LifecycleRegistryΫϥε public class LifecycleRegistry extends Lifecycle { @Override public void addObserver(LifecycleObserver observer) { ObserverWithState observerWithState = new ObserverWithState(observer); mObserverSet.putIfAbsent(observer, observerWithState); observerWithState.sync(); } ... class ObserverWithState { private State mObserverCurrentState = INITIALIZED; private GenericLifecycleObserver mCallback; ObserverWithState(LifecycleObserver observer) { mCallback = Lifecycling.getCallback(observer); } }

Slide 31

Slide 31 text

LifecyclingΫϥε class Lifecycling { static GenericLifecycleObserver getCallback(Object object) { ... final Class> klass = object.getClass(); ... cachedConstructor = getGeneratedAdapterConstructor(klass); ... return new ReflectiveGenericLifecycleObserver(object); ... static String getAdapterName(String className) { return className.replace(".", "_") + "_LifecycleAdapter"; }

Slide 32

Slide 32 text

2. Lifecycle.Eventͷൃ৴͸ҰମͲ͔͜Βʁ

Slide 33

Slide 33 text

AndroidManifest (packaged)ʹո͛͠ͳprovider͕… ... (*´ŋωŋ`)̾̌˓( ͤΊͯެࣜυΩϡϝϯτʹॻ͍ͯ͘ΕΑ͒͒ɻɻɻ)

Slide 34

Slide 34 text

LifecycleRuntimeTrojanProviderΫϥε public class LifecycleRuntimeTrojanProvider extends ContentProvider { @Override public boolean onCreate() { LifecycleDispatcher.init(getContext()); ProcessLifecycleOwner.init(getContext()); return true; } ... Firebase͕ར༻͍ͯ͠ΔContentProviderΛར༻ͨ͠ॳظԽHack ʢ҉໧తʹApplicationͷonCreateΑΓ΋ઌʹॳظԽΛ࣮ߦͰ͖Δʣ ʮHow does Firebase initialize on Android?ʯ https://firebase.googleblog.com/2016/12/how-does-firebase-initialize-on-android.html

Slide 35

Slide 35 text

LifecycleDispatcherΫϥεͰ΍͍ͬͯΔ͜ͱʢͬ͘͟Γʣ • initॲཧͰActivityLifecycleCallbacks΁ίʔϧόοΫొ࿥ • onActivityCreatedͰ”ReportFragment”ͷ௥Ճͱ FragmentLifecycleCallbacks΁ίʔϧόοΫొ࿥ • onFragmentCreatedͰFragment͕ LifecycleRegistryOwnerΛ࣮૷͍ͯ͠Ε ͹”DestructionReportFragment”Λ௥Ճ • ֤LifecycleCallbacks಺ͰLifecycleRegistryOwnerΛ࣮૷ ͍ͯ͠Ε͹LifecycleRegistryʹରͯ͠”markState()” ͱ”handleLifecycleEvent()”ͷߋ৽ΛҰ෦୲͏

Slide 36

Slide 36 text

LifecycleDispatcherΫϥεͰ΍͍ͬͯΔ͜ͱʢͬ͘͟Γʣ • initॲཧͰActivityLifecycleCallbacks΁ίʔϧόοΫొ࿥ • onActivityCreatedͰ”ReportFragment”ͷ௥Ճͱ FragmentLifecycleCallbacks΁ίʔϧόοΫొ࿥ • onFragmentCreatedͰFragment͕ LifecycleRegistryOwnerΛ࣮૷͍ͯ͠Ε ͹”DestructionReportFragment”Λ௥Ճ • ֤LifecycleCallbacks಺ͰLifecycleRegistryOwnerΛ࣮૷ ͍ͯ͠Ε͹LifecycleRegistryʹରͯ͠”markState()” ͱ”handleLifecycleEvent()”ͷߋ৽ΛҰ෦୲͏

Slide 37

Slide 37 text

LifecycleDispatcherΫϥεͰ΍͍ͬͯΔ͜ͱʢͬ͘͟Γʣ • initॲཧͰActivityLifecycleCallbacks΁ίʔϧόοΫొ࿥ • onActivityCreatedͰ”ReportFragment”ͷ௥Ճͱ FragmentLifecycleCallbacks΁ίʔϧόοΫొ࿥ • onFragmentCreatedͰFragment͕ LifecycleRegistryOwnerΛ࣮૷͍ͯ͠Ε ͹”DestructionReportFragment”Λ௥Ճ • ֤LifecycleCallbacks಺ͰLifecycleRegistryOwnerΛ࣮૷ ͍ͯ͠Ε͹LifecycleRegistryʹରͯ͠”markState()” ͱ”handleLifecycleEvent()”ͷߋ৽ΛҰ෦୲͏

Slide 38

Slide 38 text

LifecycleDispatcherΫϥεͰ΍͍ͬͯΔ͜ͱʢͬ͘͟Γʣ • initॲཧͰActivityLifecycleCallbacks΁ίʔϧόοΫొ࿥ • onActivityCreatedͰ”ReportFragment”ͷ௥Ճͱ FragmentLifecycleCallbacks΁ίʔϧόοΫొ࿥ • onFragmentCreatedͰFragment͕ LifecycleRegistryOwnerΛ࣮૷͍ͯ͠Ε ͹”DestructionReportFragment”Λ௥Ճ • ֤LifecycleCallbacks಺ͰLifecycleRegistryOwnerΛ࣮૷ ͍ͯ͠Ε͹LifecycleRegistryʹରͯ͠”markState()” ͱ”handleLifecycleEvent()”ͷߋ৽ΛҰ෦୲͏

Slide 39

Slide 39 text

ReportFragmentΫϥε public class ReportFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { ... dispatch(Lifecycle.Event.ON_CREATE); } ... private void dispatch(Lifecycle.Event event) { if (getActivity() instanceof LifecycleRegistryOwner) { ((LifecycleRegistryOwner) getActivity()).getLifecycle().handleLifecycleEvent(event); } } LifecycleRegistryOwnerΛ࣮૷ͨ͠Activity΁ͷϥΠϑαΠΫϧมߋ Πϕϯτ͸͢΂ͯReportFragment಺Ͱݺ͹Ε͍ͯΔ

Slide 40

Slide 40 text

͏ʔΜɺ૝૾Ҏ্ʹཪͰ৭ʑ΍ͬͯͨɻɻ

Slide 41

Slide 41 text

LiveData

Slide 42

Slide 42 text

LiveDataΫϥε • ஋ͷߋ৽Λ҆શʹObserver΁௨஌Մೳ
 -> LifecycleOwnerͷState͕STARTED or RESUMED࣌ͷΈ௨஌ • Lifecycle-aware components. 
 -> LifecycleOwnerͷState͕DESTROYED࣌͸observerΛࣗಈղআ public abstract class LiveData { @MainThread public void observe(LifecycleOwner owner, Observer observer) { ... } protected void postValue(T value) { ... } @MainThread protected void setValue(T value) { ... } public T getValue() { ... } ... }

Slide 43

Slide 43 text

LiveDataͷ࢓૊Έ State: STARTED or RESUMED State: CREATED Observer LiveData setValue(“Foo”) : version = 0 observe() onChange(“Foo”) setValue(“Bar”) : version = 1 pending onChange(“Bar”) lastVersion = 0 lastVersion = 1 setValue(“CA”) : version = 2 lastVersion = -1 initial : version = -1 setValue(“apk”) : version = 3 onChange(“apk”) lastVersion = 3 pending ※version͕ಉ͡ͳͷͰ௨஌͠ͳ͍

Slide 44

Slide 44 text

MutableLiveDataΫϥε public class MutableLiveData extends LiveData { @Override public void postValue(T value) { super.postValue(value); } @Override public void setValue(T value) { super.setValue(value); } } • postValue() / setValue()Λpublicείʔϓ΁มߋ
 -> ObservableField΍BehaviorSubjectΈ͍ͨͳ஋ͷมߋݕ஌͕Ͱ ͖ΔϓϩύςΟͱͯ͠࢖͑ͦ͏

Slide 45

Slide 45 text

TimerLiveDataΫϥε (Custom) public class TimerLiveData extends LiveData { private final Runnable TimeUpdater = new Runnable() { @Override public void run() { setValue(elapsedTime += 1000L); handler.postDelayed(TimeUpdater, 1000L); } }; private final Handler handler = new Handler(); private long elapsedTime = 0L; @Override protected void onActive() { handler.postDelayed(TimeUpdater, 1000L); } @Override protected void onInactive() { handler.removeCallbacks(TimeUpdater); } }

Slide 46

Slide 46 text

TimerLiveDataΫϥε (Custom) public class TimerLiveData extends LiveData { private final Runnable TimeUpdater = new Runnable() { @Override public void run() { setValue(elapsedTime += 1000L); handler.postDelayed(TimeUpdater, 1000L); } }; private final Handler handler = new Handler(); private long elapsedTime = 0L; @Override protected void onActive() { handler.postDelayed(TimeUpdater, 1000L); } @Override protected void onInactive() { handler.removeCallbacks(TimeUpdater); } }

Slide 47

Slide 47 text

LiveData userName = Transformations.map(userLiveData, user -> { user.name + " " + user.lastName }); Transformations MediatorLiveData https://developer.android.com/reference/android/arch/lifecycle/MediatorLiveData.html https://developer.android.com/reference/android/arch/lifecycle/Transformations.html -> ಠࣗͳTransformationsΛ৽ͨʹఆٛ͢Δͱ͖ʹ࢖͑Δ -> LiveDataͷ஋ΛՃ޻͢Δ (ݱঢ়͸map, switchMapͷΈ)

Slide 48

Slide 48 text

ViewModel

Slide 49

Slide 49 text

ViewModelΫϥε public abstract class ViewModel { protected void onCleared() { } } ViewModelProviders.of(activity) .get(FooViewModel.class) ViewModelStores.of(activity) HolderFragmentੜ੒
 -> setRetainInstance(true)

Slide 50

Slide 50 text

https://speakerdeck.com/ogaclejapan/how-to-keep-data-between-orientation-changes

Slide 51

Slide 51 text

ViewModelΫϥεར༻࣌ͷ஫ҙ఺ • Activity࠶ੜ੒Λލ͍Ͱσʔλ͕อ࣋͞ΕΔͷͰɺActivity΍ ViewɺResourceͳͲΛอ࣋͢ΔͱϝϞϦϦʔΫ͢Δ :( Ͳ͏ͯ͠΋ViewModel಺ͰContextΛ࢖͍͍ͨͱ͖ʹ͸Application ΫϥεΛอ࣋͢ΔAndroidViewModelΛ࢖͍·͠ΐ͏ public class AndroidViewModel extends ViewModel { private Application mApplication; public AndroidViewModel(Application application) { mApplication = application; } public T getApplication() { return (T) mApplication; } }

Slide 52

Slide 52 text

Architecture componentsͰਪ঑͞ΕΔΞʔΩςΫνϟ https://developer.android.com/topic/libraries/architecture/guide.html#the_final_architecture

Slide 53

Slide 53 text

ࢀߟࢿྉ

Slide 54

Slide 54 text

• ެࣜΨΠυ https://developer.android.com/topic/libraries/architecture/index.html • ެࣜαϯϓϧ https://github.com/googlesamples/android-architecture-components Architecture Components ࢀߟϦϯΫ • I/O ηογϣϯಈը Architecture Components - Introduction
 https://www.youtube.com/watch?v=FrteWKKVyzI Architecture Components - Solving the Lifecycle Problem
 https://www.youtube.com/watch?v=bEKNi1JOrNs

Slide 55

Slide 55 text

ࠓޙʹظ଴ʂʂ