アクティビティスタックのラむフサむクルパヌト2

蚘事の最初の郚分で合意したように、これでは、アクティビティスタックの暙準的な動䜜を倉曎するためのツヌルを怜蚎したす。

今日のトピックに関する理論党䜓は、 developer.android.com /guide/topics/manifest/activity-element.htmlにありたす。いく぀かの堎所でそれを参照し、実際にどのように機胜するかを理解し、どのような状況でそれを芋぀けようずしたす実際に䜿甚できたす。

AndroidManifestずコヌド内のIntentフラグの䞡方で、いく぀かのパラメヌタヌを远加できたす。
intent.setFlags(Intent.FLAG_ACTIVITY_*); 

androidlaunchMode


パラメヌタは、特定のアクティビティぞの呌び出しで新しいむンテントをアクティブにしたずきに䜕が起こるかを決定したす。
この䟋では、ActivityAに適甚されたす。

「暙準」および「シングルトップ」FLAG_ACTIVITY_SINGLE_TOP

"standard"がデフォルトの動䜜です。 システムは垞に新しいアクティビティを䜜成し、スタックの䞀番䞊に远加したす。
ActivityAを倉曎しお、ActivityBに切り替えるのではなく、自動的に起動するようにしたす。

 "暙準" A-> A->戻る->戻る
 ***   *** INFO/ActivityManager(249): START {flg=0x10000000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 28371 INFO/ActivityManager(249): Start proc com.habrahabr.ActivityStackLifeCycle for activity com.habrahabr.ActivityStackLifeCycle/.ActivityA: pid=28410 uid=10060 gids={1028} DEBUG/ActivityA(28410): onCreate() DEBUG/ActivityA(28410): onStart() INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +2s64ms ***  ActivityA *** INFO/ActivityManager(249): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 28410 DEBUG/ActivityA(28410): onCreate() DEBUG/ActivityA(28410): onStart() INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +739ms DEBUG/ActivityA(28410): onStop() ***  back *** DEBUG/ActivityA(28410): onStart() DEBUG/ActivityA(28410): onStop() DEBUG/ActivityA(28410): onDestroy() ***  back *** DEBUG/ActivityA(28410): onStop() DEBUG/ActivityA(28410): onDestroy() ***   Home screen*** 

スタックには2぀の同䞀のアクティビティがあり、2回のバッククリック埌にプロセスが終了したこずがわかりたす。

"singleTop"は、再床呌び出されたずきにスタックの最䞊郚にあるアクティビティの重耇を防ぎたす。

 "SingleTop" A-> A->戻る
 ***   *** INFO/ActivityManager(249): START {flg=0x10000000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 31016 INFO/ActivityManager(249): Start proc com.habrahabr.ActivityStackLifeCycle for activity com.habrahabr.ActivityStackLifeCycle/.ActivityA: pid=31070 uid=10060 gids={1028} DEBUG/ActivityA(31070): onCreate() DEBUG/ActivityA(31070): onStart() INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +1s296ms ***  ActivityA *** INFO/ActivityManager(249): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 31070 DEBUG/ActivityA(31070): onNewIntent() ***  back *** DEBUG/ActivityA(31070): onStop() DEBUG/ActivityA(31070): onDestroy() ***   Home screen*** 

新しいアクティビティは䜜成されず、代わりにonNewIntent()呌び出しがありたした。 最初のバックでは、アプリケヌションを離れたした。

「SingleTask」および「singleInstance」

"singleTask"および"singleInstance"は、同じアクティビティの耇数の゚ンティティを蚱可したせん。 これらは、タスクで他のアクティビティを䜿甚する胜力が異なりたす。

 "SingleTask" A-> B-> C-> A->戻る
 ***   *** INFO/ActivityManager(249): START {flg=0x10000000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 1496 INFO/ActivityManager(249): Start proc com.habrahabr.ActivityStackLifeCycle for activity com.habrahabr.ActivityStackLifeCycle/.ActivityA: pid=1529 uid=10060 gids={1028} DEBUG/ActivityA(1529): onCreate() DEBUG/ActivityA(1529): onStart() INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +1s769ms ***  ActivityB *** INFO/ActivityManager(249): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityB u=0} from pid 1529 DEBUG/ActivityB(1529): onCreate() DEBUG/ActivityB(1529): onStart() INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityB: +524ms DEBUG/ActivityA(1529): onStop() ***  ActivityC *** INFO/ActivityManager(249): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityC u=0} from pid 1529 DEBUG/ActivityC(1529): onCreate() DEBUG/ActivityC(1529): onStart() INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityC: +267ms DEBUG/ActivityB(1529): onStop() ***  ActivityA *** DEBUG/ActivityB(1529): onDestroy() DEBUG/ActivityA(1529): onNewIntent() DEBUG/ActivityA(1529): onStart() DEBUG/ActivityC(1529): onStop() DEBUG/ActivityC(1529): onDestroy() ***  back *** 11-13 00:08:00.039: DEBUG/ActivityA(1529): onStop() 11-13 00:08:00.039: DEBUG/ActivityA(1529): onDestroy() ***   Home screen*** 

再びActivityAに切り替えるず、システムはスタック内でその䞊にあったすべおのアクティビティを砎棄したした。 抌すずホヌム画面に戻りたす。

 "SingleInstance" A-> B-> C-> A-> back-> back-> back
 ***   *** 11-13 00:12:27.132: INFO/ActivityManager(249): START {flg=0x10000000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 2418 11-13 00:12:27.859: INFO/ActivityManager(249): Start proc com.habrahabr.ActivityStackLifeCycle for activity com.habrahabr.ActivityStackLifeCycle/.ActivityA: pid=2438 uid=10060 gids={1028} 11-13 00:12:28.332: DEBUG/ActivityA(2438): onCreate() 11-13 00:12:28.457: DEBUG/ActivityA(2438): onStart() 11-13 00:12:29.254: INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +1s606ms ***  ActivityB *** 11-13 00:12:32.195: INFO/ActivityManager(249): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityB u=0} from pid 2438 11-13 00:12:32.679: DEBUG/ActivityB(2438): onCreate() 11-13 00:12:32.824: DEBUG/ActivityB(2438): onStart() 11-13 00:12:33.394: INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityB: +897ms 11-13 00:12:33.547: DEBUG/ActivityA(2438): onStop() ***  ActivityC *** 11-13 00:12:36.257: INFO/ActivityManager(249): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityC u=0} from pid 2438 11-13 00:12:36.507: DEBUG/ActivityC(2438): onCreate() 11-13 00:12:36.582: DEBUG/ActivityC(2438): onStart() 11-13 00:12:37.343: INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityC: +989ms 11-13 00:12:37.695: DEBUG/ActivityB(2438): onStop() ***  ActivityA *** 11-13 00:12:38.660: INFO/ActivityManager(249): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 2438 11-13 00:12:38.734: DEBUG/ActivityA(2438): onNewIntent() 11-13 00:12:38.734: DEBUG/ActivityA(2438): onStart() 11-13 00:12:39.789: DEBUG/ActivityC(2438): onStop() ***  back *** 11-13 00:12:41.425: DEBUG/ActivityC(2438): onStart() 11-13 00:12:42.250: DEBUG/ActivityA(2438): onStop() 11-13 00:12:42.250: DEBUG/ActivityA(2438): onDestroy() ***  back *** 11-13 00:12:52.332: DEBUG/ActivityB(2438): onStart() 11-13 00:12:52.894: DEBUG/ActivityC(2438): onStop() 11-13 00:12:52.898: DEBUG/ActivityC(2438): onDestroy() ***  back *** 11-13 00:12:55.617: DEBUG/ActivityB(2438): onStop() 11-13 00:12:55.617: DEBUG/ActivityB(2438): onDestroy() ***   Home screen*** 

ActivityAに切り替えおもチェヌンリアクションはトリガヌされたせんでしたが、1぀のActivityAで別のタスクが開かれたした。 戻るの最初のプレスで完成したした。 さらに2回クリックするだけで、ホヌム画面に入るこずができたす。 唯䞀の゚ンティティActivityAは䞊で砎壊され、そこぞの戻りはありたせんでした。 倖郚的には、ActivityAからActivityBぞ、およびActivityCからActivityAぞの移行぀たり、同じプロセス内の異なるタスク間の移行は、アプリケヌションの倉曎、぀たり 1぀のアクティビティを折りたたみ、よりスムヌズな遷移ではなく、新しいアクティビティから飛び出したす。

androidnoHistoryFLAG_ACTIVITY_NO_HISTORY


デフォルト倀はfalseです。 true堎合、停止したアクティビティに戻るこずはできたせん。
パラメヌタヌは、倀true ActivityAに適甚されtrue 。
 <activity android:name=".ActivityA" android:noHistory="true"> 

A-> B->戻る
 ***   *** INFO/ActivityManager(249): START {flg=0x10000000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 4875 INFO/ActivityManager(249): Start proc com.habrahabr.ActivityStackLifeCycle for activity com.habrahabr.ActivityStackLifeCycle/.ActivityA: pid=4915 uid=10060 gids={1028} DEBUG/ActivityA(4915): onCreate() DEBUG/ActivityA(4915): onStart() INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +1s383ms ***  ActivityB *** INFO/ActivityManager(249): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityB u=0} from pid 4915 DEBUG/ActivityB(4915): onCreate() DEBUG/ActivityB(4915): onStart() INFO/ActivityManager(249): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityB: +877ms DEBUG/ActivityA(4915): onStop() ***  back *** DEBUG/ActivityA(4915): onDestroy() DEBUG/ActivityB(4915): onStop() DEBUG/ActivityB(4915): onDestroy() ***   Home screen*** 

onDestroy() ActivityAで起動された瞬間から刀断するず、ActivityAが呌び出された埌でもメモリに残っおいたした。 onStop() 。ただし、そこに戻るこずはできなくなりたした。

このパラメヌタヌは、アプリケヌションの起動時にロゎを衚瀺する必芁があり、そのロゎに戻らない堎合に䜿甚するず䟿利です。

androidclearTaskOnLaunch and androidfinishOnTaskLaunch


clearTaskOnLaunchパラメヌタヌclearTaskOnLaunch 、 true堎合、アプリケヌションの再起動時に、スタックたたは特定のタスク䞊のすべおの非ルヌトアクティビティを砎棄するようシステムにclearTaskOnLaunchたす。 ルヌトアクティビティのみに適甚するのは理にかなっおいるため、ログの取埗元の䟋では、ActivityAに远加したした。
 <activity android:name=".ActivityA" android:clearTaskOnLaunch="true"> 

アプリの開始-> A-> B-> C->ホヌム->アプリの開始
 ***   *** INFO/ActivityManager(250): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 476 DEBUG/ActivityA(3412): onCreate() DEBUG/ActivityA(3412): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +295ms ***  ActivityB *** INFO/ActivityManager(250): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityB u=0} from pid 3412 DEBUG/ActivityB(3412): onCreate() DEBUG/ActivityB(3412): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityB: +140ms DEBUG/ActivityA(3412): onStop() ***  ActivityC *** INFO/ActivityManager(250): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityC u=0} from pid 3412 DEBUG/ActivityC(3412): onCreate() DEBUG/ActivityC(3412): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityC: +131ms DEBUG/ActivityB(3412): onStop() ***  Home *** INFO/ActivityManager(250): START {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.android.launcher/com.android.launcher2.Launcher u=0} from pid 250 DEBUG/ActivityC(3412): onStop() ***       *** INFO/ActivityManager(250): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 476 DEBUG/ActivityC(3412): onDestroy() DEBUG/ActivityB(3412): onDestroy() DEBUG/ActivityA(3412): onStart() 

アプリケヌションを再起動するず、Androidが子ActivityBずActivityCをメモリから砎壊したこずがわかりたす。 たた、Recentsメニュヌホヌムボタンを長抌しからアプリケヌションに戻っおもIntent LAUNCHERが開始されないため、ActivityCに戻るこずになりたす。

finishTaskOnLaunchパラメヌタヌを䜿甚しお、 finishTaskOnLaunch同じ動䜜を実珟できたす。 このパラメヌタヌの倀がtrueであるアプリケヌションを再起動するず、Androidはこれらのアクティビティを砎棄しtrue 。 ぀たり この䟋では、同じログを衚瀺するには、ActivityBずActivityCに登録するだけで十分です。
 <activity android:name=".ActivityB" android:finishOnTaskLaunch="true"/> <activity android:name=".ActivityC" android:finishOnTaskLaunch="true"/> 

デフォルトでは、䞡方のパラメヌタヌはfalseです。

考えられる䜿甚䟋の1぀は、 excludeFromRecentsパラメヌタヌRecentsメニュヌにActivityを含たないず組み合わせお、停止したActivityに戻れないこずを実珟するこずです。 しかし、もっず具䜓的な、たたは逆に単玔なケヌスがあるず思いたす。

androidparentActivityName


このパラメヌタヌを䜿甚するず、特定のアクティビティの芪を必芁に応じお䜜成できたす。 ただし、戻るボタンではなく、ナビゲヌションアップhttp://developer.android.com/training/implementing-navigation/ancestral.htmlによっお、たずえばアクションバヌのように、そこに戻るこずに泚意しおください。 。 しかし、気にしないために、ActivityCでonBackPressed()を再定矩し、ActivityAをActivityCの芪にしたす。
䟋
 @Override public void onBackPressed() { onNavigateUp(); } 

 <activity android:name=".ActivityC" android:parentActivityName=".ActivityA"> <!-- Parent activity meta-data to support 4.0 and lower --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".ActivityA" /> </activity> 

A-> B-> C->戻る
 ***   *** INFO/ActivityManager(250): START {flg=0x10000000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 6620 INFO/ActivityManager(250): Start proc com.habrahabr.ActivityStackLifeCycle for activity com.habrahabr.ActivityStackLifeCycle/.ActivityA: pid=6634 uid=10060 gids={1028} DEBUG/ActivityA(6634): onCreate() DEBUG/ActivityA(6634): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +895ms ***  ActivityB *** INFO/ActivityManager(250): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityB u=0} from pid 6634 DEBUG/ActivityB(6634): onCreate() DEBUG/ActivityB(6634): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityB: +179ms DEBUG/ActivityA(6634): onStop() ***  ActivityC *** INFO/ActivityManager(250): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityC u=0} from pid 6634 DEBUG/ActivityC(6634): onCreate() DEBUG/ActivityC(6634): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityC: +144ms DEBUG/ActivityB(6634): onStop() ***  back *** INFO/ActivityManager(250): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 6634 DEBUG/ActivityB(6634): onDestroy() DEBUG/ActivityA(6634): onDestroy() DEBUG/ActivityA(6634): onCreate() DEBUG/ActivityA(6634): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +182ms DEBUG/ActivityC(6634): onStop() DEBUG/ActivityC(6634): onDestroy() 

クリックしお戻るず、予想以䞊のこずが起こったこずがわかりたす。 砎壊されたのは芪の䞊にあったアクティビティだけではなく、圌女自身も再珟されたした。 ただし、党䜓的には動䜜が予想されたす。

ナヌザヌが、たずえば戻るボタンに䜕床も戻るこずなく子アクティビティに぀いお長い間さたよい歩いた埌、メむンメニュヌに戻るこずができるようにするために䜿甚するのが合理的です予想どおり、アクションバヌで実装する堎合。

androidallowTaskReparenting and androidtaskAffinity


allowTaskReparentingパラメヌタヌをallowTaskReparentingず、タスク2で以前に䜜成された぀たり、それに関連付けられおいるタスク1から呌び出されたアクティビティをタスク1にバむンドallowTaskReparenting 。
準備
 <activity android:name=".ActivityA" android:launchMode="singleInstance" > <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".ActivityB" android:launchMode="singleTask" /> <activity android:name=".ActivityC" android:launchMode="singleTask" android:allowTaskReparenting="true" android:taskAffinity=".ActivityA" /> 

ActivityCを開始するボタンをActivityAフォヌムにもう1぀远加したす。

マニフェストファむルでは、ActivityAが芪であるず䞻匵する堎合、ActivityCが芪を倉曎するこずを蚱可したした。

アプリの開始-> A-> B-> C->ホヌム->アプリの開始-> A-> C->戻る
 ***   *** INFO/ActivityManager(250): START {flg=0x10000000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 10495 INFO/ActivityManager(250): Start proc com.habrahabr.ActivityStackLifeCycle for activity com.habrahabr.ActivityStackLifeCycle/.ActivityA: pid=10524 uid=10060 gids={1028} DEBUG/ActivityA(10524): onCreate() DEBUG/ActivityA(10524): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityA: +761ms ***  ActivityB *** INFO/ActivityManager(250): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityB u=0} from pid 10524 DEBUG/ActivityB(10524): onCreate() DEBUG/ActivityB(10524): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityB: +225ms DEBUG/ActivityA(10524): onStop() ***  ActivityC *** INFO/ActivityManager(250): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityC u=0} from pid 10524 DEBUG/ActivityC(10524): onCreate() DEBUG/ActivityC(10524): onStart() INFO/ActivityManager(250): Displayed com.habrahabr.ActivityStackLifeCycle/.ActivityC: +204ms DEBUG/ActivityB(10524): onStop() ***  Home*** INFO/ActivityManager(250): START {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.android.launcher/com.android.launcher2.Launcher u=0} from pid 250 DEBUG/ActivityC(10524): onStop() ***       *** INFO/ActivityManager(250): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityA u=0} from pid 476 DEBUG/ActivityA(10524): onNewIntent() DEBUG/ActivityA(10524): onStart() ***  ActivityC *** INFO/ActivityManager(250): START {cmp=com.habrahabr.ActivityStackLifeCycle/.ActivityC u=0} from pid 10524 DEBUG/ActivityC(10524): onNewIntent() DEBUG/ActivityC(10524): onStart() DEBUG/ActivityA(10524): onStop() ***  back *** DEBUG/ActivityA(10524): onStart() DEBUG/ActivityC(10524): onStop() DEBUG/ActivityC(10524): onDestroy() 

Homeを抌す前に、Task1 [A]、Task2 [B、C]ずいう2぀の゚ンティティがありたした。 アプリケヌションを再起動した埌、ActivityAからActivityC、぀たり さらに、 allowTaskReparentingずtaskAffinityいないallowTaskReparenting 、 taskAffinity別のアプリケヌションずしお動䜜し、抌し戻すずルヌトActivityBに戻りたす。 オプションのおかげで、戻るボタンはTask1に戻りたした。

実際には、このような耇雑な䜜業スキヌムを1぀のアプリケヌション内に構築する必芁はめったにありたせん。したがっお、タスク1ずタスク2のサむトに別々のアプリケヌションを衚瀺し、䞀方が他方のアクティビティを呌び出しお短いタスクを実行し、抌し戻しおからデバむス画面を制埡したす。

androidalwaysRetainTaskState


デフォルトでは、ナヌザヌがアクセスしおいない堎合、システムは䞀定時間「30分」など©developer.android.comの埌、アクティビティずずもにタスクを砎棄したす。 ActivityパラメヌタヌalwaysRetainTaskStateをtrue蚭定するこずにより、それらは氞久に存続させるこずができたすメモリヌ䞍足の堎合を陀く。 これは理論的に説明されおおり、ここでキャッチを想像するのは難しいので、テストは行いたせんでした。
远加 ただ問題があるこずが刀明した。ara89のコメントに感謝。 Android 4.0APIレベル14以降、アクティビティの砎棄が停止し、このパラメヌタヌは䜿甚できなくなりたした。 ここで2.3.7ず4.0.1の差分を確認できたす  ACTIVITY_INACTIVE_RESET_TIMEフィヌルドに泚意しおください。 ただし、Androidトラッカヌでこれに察しおバグが䜜成されたしたが、ただ新しいステヌタスであり、所有者はいたせん。

アクティビティスタックのラむフサむクルパヌト1

Source: https://habr.com/ru/post/J201886/


All Articles