Activity起動モード(二)Activityの4種類の起動モード――LaunchMode

10261 ワード

4種類の起動モード


Standard


標準モードでは、Intentリクエストがあるたびに新しいActivityインスタンスが作成されます.
  • Android 5.0より前
  • 同一アプリケーション内
  • 新しく生成されたActivityは,Intent者Taskを送信するスタックトップに入れる.
      ```
    

    TaskRecord{537925a8 #42 A com.zlq.lmt U 0} Run #3: ActivityRecord{538314d0 com.zlq.lmt/.StandardActivity} Run #2: ActivityRecord{5385a7c4 com.zlq.lmt/.StandardActivity} Run #1: ActivityRecord{53760908 com.zlq.lmt/.MainActivity}
    
        2.  
        
         Activity, Intent Task ( , )。
    
          ```
    TaskRecord{537df318 #52 A com.zlq.bbb U 0}
          Run #2: ActivityRecord{537a889c com.zlq.lmt/.StandardActivity}
          Run #1: ActivityRecord{537a4a5c com.zlq.bbb/.MainActivityB}
    

    このとき、タスクマネージャ(最近のタスクボタン)を開きます.最近のタスクの現実的なアプリケーション名はBアプリケーションであり、表示されるインタフェースはTaskスタックの上部にあるため、AアプリケーションのStandardActivityであることがわかります.
    アプリケーション間Standard Activityの起動
  • Android 5.0以降
  • 同じアプリケーション内でAndroid 5.0以前と一致する
  • アプリケーション間で検証済みAndroid 5を起動する.0まで一貫性を保つ.Android6.0でも変わらない.参考資料 Android Activity launchModeの内容は間違っているかもしれません.

  • シーンstandardという起動モードは、メールActivityまたはソーシャルネットワークメッセージを作成してActivityをパブリッシュするのに適しています.各intentにActivity処理を作成したい場合は、standardというモードを使用します.

  • SingleTop


    スタックトップ多重モードSingleTopはStandardとほぼ同じであり、SingleTopのActivityを使用して多くのインスタンスを作成することもできます.唯一の違いは、呼び出されたターゲットActivityがすでに呼び出し元のTaskのスタックの上部にある場合、新しいインスタンスは作成されず、現在のこのActivityインスタンスを使用して、このインスタンスのonNewIntentメソッドを呼び出すことです.
    singleTopというモードでは,このモードを適用したActivityのonCreateとonNewIntentの2つの方法を処理し,論理が正常であることを確保する必要がある.
      TaskRecord{537925a8 #42 A com.zlq.lmt U 0}
          Run #4: ActivityRecord{537e3114 com.zlq.lmt/.SingleTopActivity}
          Run #3: ActivityRecord{537dfe7c com.zlq.lmt/.StandardActivity}
          Run #2: ActivityRecord{53770808 com.zlq.lmt/.SingleTopActivity}
          Run #1: ActivityRecord{53760908 com.zlq.lmt/.MainActivity}
    

    スタックトップはStandardモードのように同僚が2つ存在することはできませんが、Taskリスト全体に複数の間隔が存在することは可能です.

    SingleTask


    スタック内多重モードsingleTask起動モードを使用するActivityは、1つのアプリケーションTaskに1つのインスタンスしか存在しません.このインスタンスがすでに存在する場合、intentはonNewIntentを介してこのActivityに渡されます.つまり、複数回の呼び出しで新しいインスタンスは作成されません.それ以外の場合、新しいActivityインスタンスが作成されます.状況は以下のとおりです.
  • 同一アプリケーション内
  • タスクスタックは存在せず、SingleTaskインスタンスを初めて起動すると、タスクスタックとインスタンスが作成される.GoogleのsingleTaskのドキュメントには、
  • という記述があります.

    The system creates a new task and instantiates the activity at the root of the new task.
       Task, Activity Task 。 , ,singleTask Activity Task, Task:
    
    TaskRecord{5378ff88 #44 A com.zlq.lmt U 0}
          Run #3: ActivityRecord{537e2ff0 com.zlq.lmt/.SingleTaskActivity}
          Run #2: ActivityRecord{537de2ec com.zlq.lmt/.StandardActivity}
          Run #1: ActivityRecord{53788be0 com.zlq.lmt/.MainActivity}
    
     ?  `taskAffinity` singleTask .
    
    ```xml
        
        
        
    ```
    

    このとき、同じ操作を実行し、スタック内の場合:
    TaskRecord{53778428 #45 A com.zlq.new U 0}
          Run #3: ActivityRecord{537db410 com.zlq.lmt/.SingleTaskWithTaskAffinityActivity}
    TaskRecord{5378ff88 #44 A com.zlq.lmt U 0}
          Run #2: ActivityRecord{53760908 com.zlq.lmt/.StandardActivity}
          Run #1: ActivityRecord{53788be0 com.zlq.lmt/.MainActivity}
    
     ,** singleTask,framework activity , , 。** `taskAffinity` Activity , SingleTask ,  Standard . com.zlq.new.
    
  • タスクスタックが存在し、SingleTaskインスタンスが初めて起動し、TaskスタックにsingleTask Activityインスタンスは存在しません.このActivityのインスタンスを作成し、呼び出し元と同じTaskにそのインスタンスを配置してスタックの上部に配置する必要があります.Standardモードと同様である.
  • タスクスタックは同じであり、singleTask Activityインスタンスがすでに存在する場合、SingleTaskインスタンスを再起動すると、Activityフォールバックスタックでは、Activityの上にあるすべてのActivityインスタンスが破棄され(破棄プロセスでActivityライフサイクルコールバックが呼び出される)、singleTask Activityインスタンスがスタックの上にある(clearTopの効果がある).同時に、IntentはonNewIntentを通じてこのSingleTask Activityインスタンスに渡されます.上記の例をクリアするclearTopの効果がある.最終的には、singleTask Activityインスタンスがスタックの上部に配置されます.
  • タスクスタックは異なり、SingleTaskインスタンスを再起動すると、タスクスタックが切り替わり、バックグラウンドがフロントに配置される.
  • アプリケーション間:
  • タスクスタックは存在しません.SingleTaskインスタンスを最初に起動すると、新しいタスクスタックが作成され、SingleTask Activityインスタンスが作成され、新しいTaskに格納されます.Taskは以下のように変化した.
  • から
    TaskRecord{5bf28 #16 A=com.zlq.bbb U=0 sz=1}
            Run #0: ActivityRecord{f4a1b15 u0 com.zlq.bbb/.MainActivityB t16}
    

    次のようになります.
    TaskRecord{5c70a93 #17 A=com.zlq.lmt U=0 sz=1}
            Run #1: ActivityRecord{4cd8b0f u0 com.zlq.lmt/.SingleTaskActivity t17}
    TaskRecord{5bf28 #16 A=com.zlq.bbb U=0 sz=1}
            Run #0: ActivityRecord{f4a1b15 u0 com.zlq.bbb/.MainActivityB t16}
    

    最近のタスクの変更:
    ここに画像の説明を入力します
    次のようになります.
    ここに画像の説明を入力します
  • タスクスタックが存在し、SingleTaskインスタンスが初めて起動し、TaskスタックにsingleTask Activityインスタンスは存在しません.singleTask Activityが存在するアプリケーション・プロセスが存在するが、singleTask Activityインスタンスが存在しない場合、このActivityを別のアプリケーションから起動すると、新しいActivityインスタンスが作成され、所属するプロセスが存在するTaskに格納され、スタックの上部に位置します.
  • から
    Running activities (most recent first):
    TaskRecord{5bf28 #16 A=com.zlq.bbb U=0 sz=1}
            Run #1: ActivityRecord{f4a1b15 u0 com.zlq.bbb/.MainActivityB t16}
    TaskRecord{65dfdf0 #18 A=com.zlq.lmt U=0 sz=1}
            Run #0: ActivityRecord{f0eba63 u0 com.zlq.lmt/.MainActivity t18}
    

    ↓は↓になります.
    Running activities (most recent first):
        TaskRecord{65dfdf0 #18 A=com.zlq.lmt U=0 sz=2}
            Run #2: ActivityRecord{73d091c u0 com.zlq.lmt/.SingleTaskActivity t18}
        TaskRecord{5bf28 #16 A=com.zlq.bbb U=0 sz=1}
            Run #1: ActivityRecord{f4a1b15 u0 com.zlq.bbb/.MainActivityB t16}
        TaskRecord{65dfdf0 #18 A=com.zlq.lmt U=0 sz=2}
            Run #0: ActivityRecord{f0eba63 u0 com.zlq.lmt/.MainActivity t18}
    
  • singleTask Activityインスタンスが存在し、他のプログラムから起動されると、このActivityが存在するTaskは上部に移動され、このTaskではsingleTask Activityインスタンスの上にあるすべてのActivityは正常に破棄されます.戻るキーを押すと、現在のTaskのActivityロールバックスタックが空になるまで、呼び出し元のTaskに戻ります.
  • から
    Running activities (most recent first):
          TaskRecord{5bf28 #16 A=com.zlq.bbb U=0 sz=1}
            Run #4: ActivityRecord{f4a1b15 u0 com.zlq.bbb/.MainActivityB t16}
          TaskRecord{65dfdf0 #18 A=com.zlq.lmt U=0 sz=4}
            Run #3: ActivityRecord{fa7aae9 u0 com.zlq.lmt/.StandardActivity t18}
            Run #2: ActivityRecord{dfd9a3b u0 com.zlq.lmt/.StandardActivity t18}
            Run #1: ActivityRecord{660ce3c u0 com.zlq.lmt/.SingleTaskActivity t18}
            Run #0: ActivityRecord{f0eba63 u0 com.zlq.lmt/.MainActivity t18}
    

    ↓は↓になります.
    Running activities (most recent first):
          TaskRecord{65dfdf0 #18 A=com.zlq.lmt U=0 sz=2}
            Run #2: ActivityRecord{660ce3c u0 com.zlq.lmt/.SingleTaskActivity t18}
          TaskRecord{5bf28 #16 A=com.zlq.bbb U=0 sz=1}
            Run #1: ActivityRecord{f4a1b15 u0 com.zlq.bbb/.MainActivityB t16}
          TaskRecord{65dfdf0 #18 A=com.zlq.lmt U=0 sz=2}
            Run #0: ActivityRecord{f0eba63 u0 com.zlq.lmt/.MainActivity t18}
    

    TASK IDが#18のタスクスタックは、従来の4個から最終的な1+1個に変わったことがわかる.
  • 使用シーン:このモードの使用シーンの多くは、メールクライアントの受信ボックスまたはソーシャルアプリケーションのタイムラインActivityに似ている.上記の2つのシーンは、対応するActivityが1つのインスタンスだけを保持する必要があるが、ユーザが感知せずに他のActivityを破棄することができるため、このモードも慎重に使用しなければならない.

  • SingleInstance


    単一インスタンスモードが起動すると、システムは単独のタスクスタックを作成し、その後使用するたびに、この単一インスタンスを破棄するまで使用し、真の単一インスタンスモードに属する.singleTaskの差は多くありませんが、singleInstance Activityインスタンスを格納するTaskは、このモードのActivityインスタンスを1つしか格納できず、他のActivityインスタンスは存在しません.2つのtaskですが、システムのタスクマネージャには常に1つ、すなわち上部にあるTaskが表示されます.

    関連知識点


    現在のタスクスタックを表示するには、次の手順に従います。

    adb shell dumpsys activity | sed -n -e '/Stack #/p' -e '/Running activities/,/Run #0/p'
    

    出力の結果は次のとおりです.
    Running activities (most recent first):
          TaskRecord{65dfdf0 #18 A=com.zlq.lmt U=0 sz=2}
            Run #2: ActivityRecord{660ce3c u0 com.zlq.lmt/.SingleTaskActivity t18}
          TaskRecord{5bf28 #16 A=com.zlq.bbb U=0 sz=1}
            Run #1: ActivityRecord{f4a1b15 u0 com.zlq.bbb/.MainActivityB t16}
          TaskRecord{65dfdf0 #18 A=com.zlq.lmt U=0 sz=2}
            Run #0: ActivityRecord{f0eba63 u0 com.zlq.lmt/.MainActivity t18}
    
    TaskRecord{65dfdf0 #18 A=com.zlq.lmt U=0 sz=2}を例にとると、TaskRecordの先頭の(例えば)はTaskRecordレコードのセットであり、18はTaskのIDであり、A=パケット名であり、szはこのTaskのActivity数である.Run#で始まるActivityレコード.パッケージ名、クラス名、TASK IDなどの情報も含まれている.
    ここで、Task IDを1つのタスクスタックの一意の識別とし、IDが同じTaskRecordは同じタスクスタックに属する(同一のアプリケーションとして理解できる).

    startActivity ForResultへの影響:


    startActivity ForResultはstartActivityとは異なり、startActivity ForResultを使用する場合、LaunchModeがどのモードに設定されているかにかかわらず、呼び出し元Taskスタックにインスタンスが新規作成され、データが正しく返されます.スタック内の表示形式はStandardと同じです(連続したインスタンスを複数生成できます).
  • SingleTopは、startActivity ForResultを使用する場合、Standard起動モードとまったく同じ
  • を表す.
  • SingleTaskは、taskAffinity属性が定義されていない場合にstartActivity ForResultとStandard起動モードを使用すると、全く同じ表現になります.taskAffinityプロパティを定義すると、次の3番目の表現と一致します.
  • SingleInstanceでは、startActivityによって自分が作成できません(現在どのスタックに属しているかにかかわらず).startActivity ForResultは、現在のスタック(受信者が存在するスタック)にインスタンスを任意に新規作成します.
  •  Running activities (most recent first):
          TaskRecord{ef9f20b #33 A=com.zlq.lmt U=0 sz=4}
            Run #3: ActivityRecord{34f60b1 u0 com.zlq.lmt/.SingleTaskActivity t33} *
            Run #2: ActivityRecord{914547d u0 com.zlq.lmt/.SingleTaskActivity t33} *
            Run #1: ActivityRecord{a1f3e09 u0 com.zlq.lmt/.SingleTaskActivity t33}
            Run #0: ActivityRecord{f7db1c u0 com.zlq.lmt/.MainActivity t33}
    

    上のコードセグメントには、startActivityを使用して確立できないことを示す*が付いており、startActivityForResultを使用して確立されたActivityである.このことから、startActivity ForResultは戻り値を必要とするため、インスタンスが保持する、単例の効果が部分的に上書きされることが分かる.
    注意:4.xバージョンはstartActivity ForResultでsingleTaskを起動し、正常に戻り値を取得できません.参考.5.x以上のバージョンでこの問題を修正し、互換性を考慮してstartActivity ForResultとsingleTaskを推奨しない.

    Demoソース


    以上はいずれも参考資料と自己実践検証の結果である.説明がはっきりしないところがあって、みんなは私のコードをダウンロードして自分で各種の情況を検証することができます:GitHub

    リファレンスリンク


    AndroidのActivity launchMode分析Activityの起動モードAndroidのActivityの4種類の起動モードとtaskAffinityの属性の詳細を詳しく説明します