
2017幎11æ6æ¥ãGoogleã¯å®å®ããŒãžã§ã³ã®çºè¡šã«é¢ããæ
å ±ãå
¬éããŸãã
建ç¯ã³ã³ããŒãã³ã ã Googleéçºè
ã¯ã
ã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ã«é¢ããã¬ã€ãã³ã¹ãæäŸããçµã¿èŸŒã¿ã¢ãŒããã¯ãã£ã䜿çšããã¢ããªã±ãŒã·ã§ã³ã®äœæãç°¡çŽ åãããããžã§ã¯ããžã®æ°ããããã°ã©ããŒã®åå ã容æã«ããAndroidã·ã¹ãã ã®ããã°ã©ãã³ã°ãå§ããã°ããã®äººã
ã®æ人éçºã®äžçã«å
¥ãããã®ãããå€ãåæžããå€ãã®ã¯ã©ã¹ãšã€ã³ã¿ãŒãã§ã€ã¹ãå°å
¥ããŸããã
Androidã®ã©ã€ããµã€ã¯ã«ãæäœããããã«æ瀺ãããã³ã³ããŒãã³ãã¯ãç®ã«èŠããªãæèšä»æããšæ¯èŒã§ããŸãã ã»ãã®æ°è¡ã®ã³ãŒããšãã¹ãŠãæ©èœããŸãã ãããããã¹ãŠãã©ã®ããã«é
眮ãããŠããŸããïŒ ãšã«ãããèªå®
ã®ãããžã§ã¯ãã§ããããã¯æ°åäžã®ã¢ã¯ãã£ããªã€ã³ã¹ããŒã«ããããããžã§ã¯ãã§ããã建ç¯ã³ã³ããŒãã³ãã䜿çšãã䟡å€ã¯ãããŸããïŒ
å
責äºé
Kotlinéçºèšèªã§æäŸãããéçºè
ã³ãŒãã Googleã®ãœãŒã¹ã³ãŒãã®æç²ã¯Javaã§æäŸãããŠããŸãã æç²ã§ã¯ãã³ãŒãã®äžéšãçç¥ã§ããŸãã
ã©ã€ããµã€ã¯ã«ãã©ã€ããµã€ã¯ã«ãæèããã³ã³ããŒãã³ãããã³ã¢ã¯ãã£ããã£
ã©ã€ããµã€ã¯ã«ã¯ãAndroidéçºã®äžçã§éåžžã«éèŠãªãã€ã³ãã§ãããå€ãã®å Žåãååãªæ³šç®ãéããŠããŸããã ãã®ãããã¢ããªã±ãŒã·ã§ã³ã§ãšã©ãŒãçºçããå ŽåããããŸãã ããšãã°ãé»è©±ãããããšãã¢ããªã±ãŒã·ã§ã³ãé倧ãªãšã©ãŒã§çµäºããå ŽåããããŸãã ããã¯ãã¢ã¯ãã£ããã£ã®åäœæãšæªå å·¥ã®ç¶æ
ã®ä¿åã«ãããã®ã§ãã
éšåçã«ã¯ãã¢ã¯ãã£ããã£ã®åäœæã®åé¡ãåé¿ã§ããŸãã ããšãã°ãåäœæãçŠæ¢ããã«ã¯ããããã§ã¹ãã®
ã¢ã¯ãã£ããŒã·ã§ã³èšå®ã
androidïŒscreenOrientation = "portrait"ã«èšå®ããŸãã ãã ããããã¯ãæ§æã®å€æŽïŒããšãã°ãç»é¢ã®åãã®å€æŽïŒäžã«ã¢ã¯ãã£ããã£ãåã¢ã¯ãã£ãåããåé¡ã®ã¿ã解決ããŸãã ããæç¹ã§ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãã¡ã¢ãªäžè¶³ã«ãªããå®è¡å¯èœãªã¢ã¯ãã£ããã£ã§ããã»ã¹ãç Žå£ããããšããåé¡ã¯ããã®æ¹æ³ã解決ããŸããã ã¢ããªã±ãŒã·ã§ã³ã®æäœã«æ»ããšããŠãŒã¶ãŒãæåã«ç®ã«ããã®ã¯é倧ãªãšã©ãŒã§ãã
ãããã«ããŠããéçºè
ã¯ã©ã€ããµã€ã¯ã«ã®ç¶æ
ãåŠçããå¿
èŠããããŸãã ã©ã€ããµã€ã¯ã«å¯Ÿå¿ã®ã³ã³ããŒãã³ããå©ãã«ãªããŸãã ã¢ãŒããã¯ãã£ã³ã³ããŒãã³ãã«ã¯å®å®ããããŒãžã§ã³1.0ããããã¢ããªã±ãŒã·ã§ã³ã®è£œåéçºã§äœ¿çšã§ããŸãã
ã©ã€ããµã€ã¯ã«å¯Ÿå¿ã³ã³ããŒãã³ãã䜿çšããé·æãšçæ
ã³ã³ããŒãã³ãã䜿çšããå®éçãªé·æãšçæãèæ
®ããŠãã ããã
ééããªãããå€ãã®ãã©ã¹ããããŸã
- æ°ããåŸæ¥å¡ãã¢ããªã±ãŒã·ã§ã³éçºããŒã ã«æ¥ç¶ããŸãã ãã¹ãŠã®Androidéçºè
ã¯ãGoogleã®å
¬åŒã©ã€ãã©ãªãç¥ã£ãŠããã䜿çšããããšãã§ããŸãã ã¢ãŒããã¯ãã£ãç¶æããããã«ããŒã«ã«ãœãªã¥ãŒã·ã§ã³ã®åŠç¿ã«æéãè²»ããå¿
èŠã¯ãããŸããã
- æ©èœãéçºããéã®ã³ãŒããå°ãªããªããŸãã
- ã³ã³ããŒãã³ãã®å®å®æ§;
- ã³ã³ããŒãã³ãã®å®è£
åŸã®ã¢ããªã±ãŒã·ã§ã³ã®å®å®æ§ã®åäžã
çæ
- ã³ã³ããŒãã³ãã«ç²Ÿéãããããžã§ã¯ãã«è¿œå ããæéã
- æ°ããé¢æ°ãéçºãããšãã«ã¢ãŒããã¯ãã£ã«ä»éããã³ãŒããè¿œå ãããŸãããããã®ãã€ãã¹ã¯ã³ãŒãçæã«ãã£ãŠç°¡åã«è§£æ±ºãããŸãã ãã®ãããã¯ã«é¢ããè¯ãèšäºã¯ãã¡ããšãã¡ã ã
ã©ã€ããµã€ã¯ã«å¯Ÿå¿ã³ã³ããŒãã³ãã䜿çšããæ¹æ³
ãµããŒãã©ã€ãã©ãªããŒãžã§ã³26.1.0以éããã©ã°ã¡ã³ããšã¢ã¯ãã£ããã£ã¯ãã®ãŸãŸã§LifecycleOwnerã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããŸãã ãã®ã€ã³ã¿ãŒãã§ãŒã¹ã«ã¯ã
getLifecycleïŒïŒãšãã 1ã€ã®ã¡ãœãããããããŸããã
ã©ã€ããµã€ã¯ã«ã€ãã³ãã«ãªãã¶ãŒããŒãè¿œå ããã«ã¯ããªãã¶ãŒããŒã¯ã©ã¹ã«LifecycleObserverã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããã¢ã¯ãã£ããã£/ãã©ã°ã¡ã³ããèšè¿°ããã ãã§ååã§ãã
private fun addLifecycleObserver() { lifecycle.addObserver(observer) }
ããã ãã§ããïŒ ã¯ããéçºè
ã«ãšã£ãŠäœæ¥ã¯ããã§çµäºããŸãã ãªãã¶ãŒããŒã³ãŒãã§ã¯ãå¿
èŠãªã¡ãœããã«æ³šéãä»ããã©ã€ããµã€ã¯ã«ã€ãã³ãã«å¿çããã ãã§ååã§ãã
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun init(){}
èå³æ·±ãäºå®ã¯ãããã€ãã®ã¡ãœããã«åã泚éãä»ããããšãã§ããã©ã€ããµã€ã¯ã«ã®ç¶æ
ãå€åãããšããããã¹ãŠãåŒã³åºãããããšã§ãã
ããã€ãã®ç·ã®åŸãã«é ãããŠãããã®ããã¹ãŠãã©ã®ããã«æ©èœãããããã¥ã¢ã³ã¹ã¯äœã§ããïŒ
ãµã³ãã«ã®ãã©ã°ã¡ã³ãã䜿çšããŠã以äžã®è³ªåã«å¯ŸããåçãèŠã€ããŸãã
getLifecycleïŒïŒã¡ãœããã«LifecycleOwnerã€ã³ã¿ãŒãã§ãŒã¹ãå®è£
ãããšããã©ã°ã¡ã³ãã¯äœãè¿ããŸããïŒ äž»ãªæ¹æ³ã®èª¬æ
ãã®ãã©ã°ã¡ã³ãã¯ãLifecycleOwnerã€ã³ã¿ãŒãã§ãŒã¹ãå®è£
ãã
getLifecycleïŒïŒïŒLifecycleã¡ãœãããå®è£
ããŸãã
ã©ã€ããµã€ã¯ã«ã¯ãAndroidã©ã€ããµã€ã¯ã«ãæã€ãªããžã§ã¯ããšããŠãªããžã§ã¯ããå®çŸ©ããæœè±¡ã¯ã©ã¹ã§ãã
ãã®ã¯ã©ã¹LifecycleRegistryã®å®è£
ã¯ãè¿œå ã®å¶åŸ¡ããªãã¶ãŒããŒã®åé€ãã©ã€ããµã€ã¯ã«ã€ãã³ãã®åŠçãã©ã€ããµã€ã¯ã«ã®å€æŽããã¹ãŠã®ãªãã¶ãŒããŒã«å ±åãããã¹ãŠã®äœæ¥ãåŒãåããŸãã
ãªãã¶ãŒããŒãè¿œå ããŸãã
@MainThread public abstract void addObserver(@NonNull LifecycleObserver observer);
éèŠãªãã¥ã¢ã³ã¹ã¯ãLifecycleObserverããªãã¶ãŒããŒã®ãªã¹ãã«è¿œå ããããšããªãã¶ãŒããŒã¯çŸåšã®ç¶æ
ã«å
è¡ãããã¹ãŠã®ç¶æ
ã®å€æŽã«é¢ããã€ãã³ããåãåãããšã§ãã
ã€ãŸãã
LifecycleObserverãè¿œå ãããšãã«
LifecycleOwnerãLifecycle.State.STARTEDç¶æ
ã«ããå ŽåãåŸè
ã¯2ã€ã®
Lifecycle.Event.ON_CREATEããã³
Lifecycle.Event.ON_STARTã€ãã³ããåãåããŸãã
ããã¯ããªãã¶ãŒããŒãåæåã®ãã¹ãŠã®æ®µéãçµãŠãã©ã€ããµã€ã¯ã«ã®ã€ãã³ãã«äŸåããæ§æã®ã©ã®æ®µéãèŠéããªãããšãä¿èšŒããŠããããšãæå³ããŸãã
ãªãã¶ãŒããŒãªã¹ããããªãã¶ãŒããŒãåé€ãããšãã¡ãœããã§çºçããŸãã
@MainThread public abstract void removeObserver(@NonNull LifecycleObserver observer);
ã©ã€ããµã€ã¯ã«ã®ç¶æ
ã®å€æŽäžã«ãªãã¶ãŒããŒã®åé€ãçºçããåé€åŸã«ç¶æ
å€æŽã«é¢ããã€ãã³ãã®éä¿¡ãåŒã³åºãããå Žåããªãã¶ãŒããŒã¯ãã®ã€ãã³ããåä¿¡ããŸããã
ãªãã¶ãŒããŒå
ã®è€æ°ã®ã¡ãœããã1ã€ã®ã€ãã³ããäºæãããªãã¶ãŒããŒã®ãªã¹ããããªãã¶ãŒããŒãåé€ãããšãã«å°ãªããšã1ã€ã®ã¡ãœãããåŒã³åºãããå Žåãä»ã®ãã¹ãŠã®ã¡ãœãããåŒã³åºããããããåé€ãããŸãã
ãªã¯ãšã¹ãã«å¿ããŠçŸåšã®ã¹ããŒã¿ã¹ãè¿ããŸãã
@MainThread public abstract State getCurrentState();
ãã€ã§ããã©ã€ããµã€ã¯ã«ã®çŸåšã®ç¶æ
ãèŠæ±ãããã®çãã«åºã¥ããŠä»»æã®ã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãã ãã®ã¡ãœããã¯ãStateåæã®ã€ã³ã¹ã¿ã³ã¹ãè¿ããŸãã
次ã®ã¿ã€ãã®ç¶æ
INITIALIZED-ãã®ç¶æ
ã¯ãLifecycleOwnerã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ãããšã³ãã£ãã£ãäœæãããããonCreateïŒïŒã¡ãœããããŸã åŒã³åºãããŠããªãæéã«å¯Ÿå¿ããŸãã
CREATED-ãã®ç¶æ
ã¯ãonCreateïŒïŒãåŒã³åºããåŸãonStopïŒïŒãåŒã³åºãåã«ã¢ã¯ãã£ãã§ãã
STARTED-ãã®ç¶æ
ã¯ãonStartïŒïŒã¡ãœãããåŒã³åºããåŸãonPauseïŒïŒãåŒã³åºãåã«ã¢ã¯ãã£ãã«ãªããŸãã
RESUMED-ãã®ç¶æ
ã¯ãonResumeïŒïŒã¡ãœãããåŒã³åºãããåŸã«çºçããŸãã
DESTROYED-ãã®ç¶æ
ã¯ãonDestroyïŒïŒåŒã³åºãã®çŽåã«çºçããŸãã ãã®ç¶æ
ãçºçãããšãLifecycleOwnerã¯ç¶æ
å€æŽã€ãã³ããéä¿¡ããªããªããŸãã
ãªãã¶ãŒããŒããªãã¶ãŒããŒãªã¹ãã«è¿œå ããããšã©ããªããŸããïŒ
@Override public void addObserver(@NonNull LifecycleObserver observer) { State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; ObserverWithState statefulObserver = new ObserverWithState(observer, initialState); <...> }
lifecycle.addObserverïŒãªãã¶ãŒããŒïŒã¡ãœãããåŒã³åºããããšããªãã¶ãŒããŒã¯ObserverWithStateã©ãããŒã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«é
眮ãããŸãã ã¯ã©ã¹åã瀺ãããã«ããã®ã¯ã©ã¹ã«ã¯ã©ã€ããµã€ã¯ã«ã®æåŸã«åŠçãããç¶æ
ãæã€ãªãã¶ãŒããŒãæ ŒçŽãããŸãã æåã«ãç¶æ
ãDESTROYEDãŸãã¯INITIALIZEDã«èšå®ããŸãã
@Override public void addObserver(@NonNull LifecycleObserver observer) { <...> ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver); if (previous != null) { return; } LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); if (lifecycleOwner == null) {
ã©ã€ããµã€ã¯ã«ã®æåŸã«åŠçãããç¶æ
ã§ãªãã¶ãŒããŒã®ã€ã³ã¹ã¿ã³ã¹ãäœæããåŸãputIfAbsentïŒïŒã¡ãœããã䜿çšããŠãªãã¶ãŒããŒãFastSafeIterableMapã³ã¬ã¯ã·ã§ã³ã«è¿œå ããããšããŸãã
@Override public V putIfAbsent(@NonNull K key, @NonNull V v) { Entry<K, V> current = get(key); if (current != null) { return current.mValue; } mHashMap.put(key, put(key, v)); return null; }
ã¡ãœãããèŠçŽ ãè¿ãå Žåããã®èŠçŽ ã¯æ¢ã«ã³ã¬ã¯ã·ã§ã³ã«ååšããŠããã®ã§ãå床远å ããå¿
èŠã¯ãããŸããã ããã¯ã³ãŒãã®åŸåã§çºçããŸãã ãªã¹ãã«ãªãã¶ãŒããŒãããå Žåã
addObserverïŒïŒã¡ãœããã®äœæ¥ã¯
åæ¢ããŸãã ãŸãã
lifecycleOwner == nullã®å Žåãäœæ¥ã¯çµäºã
ãŸã ã
@Override public void addObserver(@NonNull LifecycleObserver observer) { <...> State targetState = calculateTargetState(observer); mAddingObserverCounter++; while ((statefulObserver.mState.compareTo(targetState) < 0 && mObserverMap.contains(observer))) { pushParentState(statefulObserver.mState); statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState)); popParentState();
ã©ã€ããµã€ã¯ã«ã®çŸåšã®ç¶æ
ãèšç®ããããªãã¶ãŒããŒã«ä¿åãããŠããç¶æ
ãçŸåšã®ç¶æ
ãããå°ãããªããŸã§ã€ãã³ãã®éä¿¡ãéå§ãããŸãã
upEventïŒç¶æ
ïŒç¶æ
ïŒãšã¯äœã§ããïŒ ãŸããdownEventïŒç¶æ
ïŒç¶æ
ïŒãããããšã«æ³šæããŠãã ããã çŸåšã®ç¶æ
ã«åºã¥ããŠãã©ã€ããµã€ã¯ã«ã§äœãèµ·ãã£ãŠãããã«å¿ããŠãã©ã®ã€ãã³ãããªãã¶ãŒããŒã«éä¿¡ãããã決å®ã§ããŸãã
ã¡ãœããã®æ¬äœãšäžã®å³ãèŠããšãããã«å¯ŸåŠããã®ã¯ç°¡åã§ãã

private static Event downEvent(State state) { switch (state) { case INITIALIZED: throw new IllegalArgumentException(); case CREATED: return ON_DESTROY; case STARTED: return ON_STOP; case RESUMED: return ON_PAUSE; case DESTROYED: throw new IllegalArgumentException(); } throw new IllegalArgumentException("Unexpected state value " + state); } private static Event upEvent(State state) { switch (state) { case INITIALIZED: case DESTROYED: return ON_CREATE; case CREATED: return ON_START; case STARTED: return ON_RESUME; case RESUMED: throw new IllegalArgumentException(); } throw new IllegalArgumentException("Unexpected state value " + state); }
LifecycleOwnerã¯ããã©ã°ã¡ã³ãã©ã€ããµã€ã¯ã«ã§çºçããã€ãã³ããLifecycleObserverã«ã©ã®ããã«éç¥ããŸããïŒ
LifecycleOwnerã€ã³ã¿ãŒãã§ãŒã¹ãå®è£
ãããã©ã°ã¡ã³ãã«ã¯ã
performCreateïŒsavedInstanceStateïŒBundleïŒ ã
performStartïŒïŒ ã
performStopïŒïŒãªã©ãã©ã€ããµã€ã¯ã«ã€ãã³ãã«å¯Ÿå¿ããåŒã³åºãã«äœ¿çšã§ããã¡ãœãããå€æ°å«ãŸããŠããŸãã
FragmentManagerImplã¯ã©ã¹ã¯ãããã®ã¡ãœãããåŒã³åºãã察å¿ããonStartãonStopãããã³ãã®ä»ã®ã¡ãœããããã©ã°ã¡ã³ãã§åŒã³åºãããŸãã ãŸããLifecycleRegistryã¯ã©ã¹ã®ã¡ãœãããåŒã³åºããŸãã
void performStart() { <...> onStart(); mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START); }
LifecycleRegistryã¯ã©ã¹ã¯ãåä¿¡ããã€ãã³ãã«åºã¥ããŠã次ã®ã€ãã³ãã®éä¿¡ã«é¢ããç¶æ
ãèšç®ããŸãã
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) { State next = getStateAfter(event); moveToState(next); }
ãã®åŸããªãã¶ãŒããŒã«éä¿¡ããã€ãã³ãã®ã¿ã€ã-upEventïŒç¶æ
ïŒç¶æ
ïŒãŸãã¯downEventïŒç¶æ
ïŒç¶æ
ïŒãèšç®ãããŸã
void dispatchEvent(LifecycleOwner owner, Event event) { State newState = getStateAfter(event); mState = min(mState, newState); mLifecycleObserver.onStateChanged(owner, event); mState = newState; }
ãããã«
å®éãGoogleãäœæããã¯ã©ã¹ãšã€ã³ã¿ãŒãã§ãŒã¹ã®äžéšã®ã¿ã説æãããŠããŸãã ãããããã¹ãŠãã©ã®ããã«çºçããæ°è¡ã®ã³ãŒãã®èåŸã«ãããã®ãæ³åããã«ã¯ãããã§ååã§ãã
Googleéçºè
ã¯ãã¢ãŒããã¯ãã£ããµããŒãããã¢ããªã±ãŒã·ã§ã³ãéçºããããã®çã«åŒ·åãªããŒã«ãæäŸããŠããŸãã éçºè
ã¯ãä»ã®ã³ã³ããŒãã³ããšäžç·ã«ãä¿¡é Œã§ããã¢ããªã±ãŒã·ã§ã³ãéçºããç¬èªã®ãå¿
ãããçæ³çãªãœãªã¥ãŒã·ã§ã³ãšã¯éããŸããã