Activity启动模式

来源:互联网 发布:中文域名转码 源码 编辑:程序博客网 时间:2024/06/06 09:10

一、启动模式简介

  启动模式相当于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 intent06-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 intent06-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 21:21:09.731 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: created.06-13 21:21:09.760 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.06-13 21:21:09.760 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.06-13 21:21:12.204 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: restarted.06-13 21:21:12.204 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: started.06-13 21:21:12.204 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: resumed.06-13 21:21:13.889 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: new intent06-13 21:21:13.889 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: restarted.06-13 21:21:13.890 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.06-13 21:21:13.890 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.

分析:
  从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 intent06-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 intent06-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只能存在于一个任务栈中。

原创粉丝点击