美文网首页
Activity启动模式

Activity启动模式

作者: 5b2047171d67 | 来源:发表于2017-06-13 22:17 被阅读0次

    一、启动模式简介

    启动模式相当于Activity的一个属性,不同的启动模式Activity会有不同的行为表现,这里的行为主要体现在Activity的生命周期,特别是系统在启动多个Activity实例的时候,具体差异我们将用实例来说明。

    二、任务栈简介

    要了解Activity的启动模式,就不可避免地涉及到Activity所需的任务栈。什么是任务栈呢?android系统每启动一个新的Activity,都要将该Activity实例放入特定的任务栈,而这个任务栈和一个参数TaskAffinity有关,这个产生标识了Activity所需的任务栈的名字,默认的值为应用的包名。值得注意的是,TaskAffinity属性主要和singleTask启动模式(下面将要介绍)或allowTaskReparenting属性配合使用,在其他情况下没有意义。
      既然叫“栈”,那么就符合“后进先出”的特点,我们每按一下back键,就有一个Activity实例出栈。

    三、Activity启动模式

    1、standard

    标准模式,这是系统的默认模式。每次启动一个Activity都会重新创建一个Activity实例,不管这个Activity的实例是否存在。

    2、singleTop

    栈顶复用模式。在这种模式下,如果有Activity实例位于任务栈顶,那么就不会重新创建Activity实例,同时,Activity的onNewIntent方法会被回调。

    3、singleTask

    栈内复用模式。类似于单例模式,只要任务栈中有一个此Activity的实例,那么重新启动Activity就不会创建新的实例,而且和singleTop一样,onNewIntent方法会被回调

    4、singleInstance

    单实例模式,这是一种加强的singleTask模式,只要有一个任务栈中有Activity的实例,那么新实例就不会被创建。换句话说,singleInstance的Activity实例只能位于一个任务栈中。

    下面我将用运行实例代码结合日志输出来分析各种启动模式的区别

    代码:
    LaunchMode应用:

    package com.android.yanghuaan.launchmode;
    
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    
    public class AActivity extends AppCompatActivity {
    
        private static final String TAG = "Activity_A";
    
        @Override
        protected void onRestart() {
            Log.d(TAG, "restarted.");
            super.onRestart();
        }
    
        @Override
        protected void onStart() {
            Log.d(TAG, "started.");
            super.onStart();
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            Log.d(TAG, "created.");
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_a);
            findViewById(R.id.start_B_button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(getApplicationContext(), BActivity.class);
                    startActivity(intent);
    
                }
            });
            findViewById(R.id.start_A_self_button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(getApplicationContext(), AActivity.class);
                    startActivity(intent);
                }
            });
        }
    
        @Override
        protected void onNewIntent(Intent intent) {
            Log.d(TAG, "new intent");
            super.onNewIntent(intent);
        }
    
        @Override
        protected void onResume() {
            Log.d(TAG, "resumed.");
            super.onResume();
        }
    
        @Override
        protected void onDestroy() {
            Log.d(TAG, "destroyed.");
            super.onDestroy();
        }
    }
    
    package com.android.yanghuaan.launchmode;
    
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    
    public class BActivity extends AppCompatActivity {
    
        private static final String TAG = "Activity_B";
    
        @Override
        protected void onRestart() {
            Log.d(TAG, "restarted.");
            super.onRestart();
        }
    
        @Override
        protected void onStart() {
            Log.d(TAG, "started.");
            super.onStart();
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            Log.d(TAG, "created.");
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_b);
            findViewById(R.id.start_A_button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(getApplicationContext(), AActivity.class);
                    startActivity(intent);
    
                }
            });
            findViewById(R.id.start_B_self_button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(getApplicationContext(), BActivity.class);
                    startActivity(intent);
                }
            });
        }
    
        @Override
        protected void onResume() {
            Log.d(TAG, "resumed.");
            super.onResume();
        }
    
        @Override
        protected void onDestroy() {
            Log.d(TAG, "destroyed.");
            super.onDestroy();
        }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.android.yanghuaan.launchmode">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <!--主要在activity中改变启动模式,不同启动模式下此处代码不同-->
            <activity
                android:name=".AActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
            <activity
                android:name=".BActivity">
            </activity>
        </application>
    </manifest>
    

    LaunchMode应用包含两个Activity--A和B,每个Activity都有两个按钮,一个用来启动自己,另一个用来启动另一个Activity。
    LaunchMode2代码:

    package com.android.yanghuaan.launchmode2;
    
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity {
    
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            findViewById(R.id.start_other_activity_button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent();
                    intent.setClassName("com.android.yanghuaan.launchmode",
                            "com.android.yanghuaan.launchmode.AActivity");
                    startActivity(intent);
                }
            });
        }
    }
    

    LaunchMode2应用包含一个Activity,它可以用来启动LaunchMode应用的一个Activity。只有在singleInstance的例子中才使用到LaunchMode2应用,因此写好只需跑一次、将LaunchMode2安装到安卓手机上即可。

    通过在Activity的生命周期方法中添加输出日志的代码来追踪每个Activity的活动

    standard 模式

    <activity
                android:name=".AActivity"
                android:launchMode="standard">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
            <activity
                android:name=".BActivity">
            </activity>
    

    操作步骤:
      进入LaunchMode应用后点击两次启动自己的按钮
    日志输出:

    06-13 20:25:07.982 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: created.
    06-13 20:25:08.201 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:25:08.201 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:25:11.399 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: created.
    06-13 20:25:11.422 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:25:11.423 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:25:14.589 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: created.
    06-13 20:25:14.614 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:25:14.614 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    

    分析:
      从日志可以看出,onCreate->onStart->onResume被被调用了3次,说明创建了3个AActivity的实例,即Activity实例被重复创建了。此时需要3次按back才能返回桌面

    singleTop 模式

    <activity
                android:name=".AActivity"
                android:launchMode="singleTop">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
            <activity
                android:name=".BActivity"
                android:launchMode="singleTop">
            </activity>
    

    操作步骤:
      进入LaunchMode应用后先按启动BActivity的按钮,此时进入了BActivity;再按启动AActivity的按钮,此时进入了AActivity;再按两次启动自己(AActivity)的按钮
    日志输出:

    06-13 20:35:07.446 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: created.
    06-13 20:35:07.483 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:35:07.483 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:35:10.828 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: created.
    06-13 20:35:10.860 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: started.
    06-13 20:35:10.860 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: resumed.
    06-13 20:35:12.033 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: created.
    06-13 20:35:12.068 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:35:12.068 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:35:16.913 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: new intent
    06-13 20:35:16.913 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:35:19.872 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: new intent
    06-13 20:35:19.873 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:35:24.084 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: restarted.
    06-13 20:35:24.084 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: started.
    06-13 20:35:24.084 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: resumed.
    06-13 20:35:24.394 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: destroyed.
    06-13 20:35:24.951 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: restarted.
    06-13 20:35:24.951 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:35:24.951 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:35:25.252 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: destroyed.
    06-13 20:35:27.292 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: destroyed.
    

    分析:
      从AActivity到BActivity,再启动AActivity,发现onCreate被调用,即表明AActivity实例被重新创建;根据栈的特点可知此时AActivity的实例并没有位于栈顶,所以AActivity实例被重新创建;
      返回AActivity后,再次启动两次AActivity都发现只有onResume和onNewIntent被调用,可知AActivity的实例被重新使用,并没有创建新的实例,这两次创建Activity的过程中AActivity的实例都位于栈顶,所以没有重新创建。
      此时连续按back键的效果是:BActivity->AActivity->桌面;

    singleTask 模式

    <activity
                android:name=".AActivity"
                android:launchMode="singleTask">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
            <activity
                android:name=".BActivity">
            </activity>
    

    操作步骤:
      进入LaunchMode应用,按启动BActivity的按钮启动BActivity,再按启动AActivity的按钮启动AActivity
    日志输出:

    06-13 20:47:26.429 32534-32534/com.android.yanghuaan.launchmode D/Activity_B: started.
    06-13 20:47:26.429 32534-32534/com.android.yanghuaan.launchmode D/Activity_B: resumed.
    06-13 20:47:28.458 32534-32534/com.android.yanghuaan.launchmode D/Activity_A: new intent
    06-13 20:47:28.458 32534-32534/com.android.yanghuaan.launchmode D/Activity_A: restarted.
    06-13 20:47:28.458 32534-32534/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:47:28.459 32534-32534/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:47:28.780 32534-32534/com.android.yanghuaan.launchmode D/Activity_B: destroyed.
    

    分析:
      从BActivity启动AActivity,发现onRestart被调用,同时onNewIntent也被调用,表明AActivity的实例并没有被重新创建;此时只需按一次back键就可以返回桌面,因为在从BActivity创建AActivity的过程中BActivity被出栈了。

    singleInstance 模式

    <activity
                android:name=".AActivity"
                android:launchMode="singleInstance"
                android:allowTaskReparenting="true">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
            <activity
                android:name=".BActivity">
            </activity>
    

    操作步骤:
      先启动应用LuanchMode,再按启动BActivity的按钮启动BActivity;然后通过 home键返回桌面,启动LaunchMode2应用,在里面按启动其他应用Activity的按钮启动AActivity;最后通过 home键返回桌面,启动LaunchMode应用
    日志输出:

    06-13 20:55:40.044 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: created.
    06-13 20:55:40.136 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:55:40.137 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:55:41.046 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: created.
    06-13 20:55:41.079 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: started.
    06-13 20:55:41.079 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: resumed.
    06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: new intent
    06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: restarted.
    06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    06-13 20:56:00.336 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: new intent
    06-13 20:56:00.336 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: restarted.
    06-13 20:56:00.337 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
    06-13 20:56:00.337 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.
    

    分析:
      从LaunchMode2启动AActivity,发现AActivity并没有被重新创建,而是调用了onNewIntent和onRestart,并且重新从桌面进入LaunchMode应用也是如此,看起来就像AActivity从一个任务栈中移动到另一个任务栈中,这充分说明了singleInstance模式的Activity只能存在于一个任务栈中。

    相关文章

      网友评论

          本文标题:Activity启动模式

          本文链接:https://www.haomeiwen.com/subject/nupjqxtx.html