Android Activity各启动模式的差异

来源:互联网 发布:国内网络婚纱品牌排行 编辑:程序博客网 时间:2024/05/29 15:10

Activity共有四种启动模式:standard,singleTop,singleTask,singleInstance

 

为了方便描述和理解,布局文件、Manifest文件和各个java文件如下:

Andoirdtanifest文件

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.activitylaunchmode"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="19"        android:targetSdkVersion="21" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:launchMode="standard"            android:screenOrientation="portrait"            android:name=".MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <activity            android:launchMode="singleTop"            android:screenOrientation="portrait"            android:name=".SecondActivity">        </activity>        <activity            android:launchMode="singleTask"            android:screenOrientation="portrait"            android:name=".ThirdActivity">        </activity>        <activity             android:launchMode="singleInstance"            android:screenOrientation="portrait"            android:name=".FourActivity">        </activity>    </application></manifest>

  4个Activity分别对应一种启动模式:

    MainActivity     ---->  standard (默认模式,写不写都可以)

    SecondActivity ---->  singleTop

    ThirdActivty     ---->  singleTask

    FourActivity     ---->  singleInstance

布局文件 activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.activitylaunchmode.MainActivity" >        <TextView         android:id="@+id/mTextView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        />    <Button        android:layout_below="@id/mTextView"        android:id="@+id/buttonOne"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Button1"        />        <Button         android:id="@+id/buttonTwo"        android:text="Button2"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_toRightOf="@id/buttonOne"           android:layout_below="@id/mTextView"        />    <Button         android:id="@+id/buttonThree"        android:text="Button3"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@id/buttonOne"        />    <Button         android:id="@+id/buttonFour"        android:text="Button4"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@id/buttonTwo"        android:layout_toRightOf="@id/buttonThree"        /></RelativeLayout>

MainActivity.java

package com.example.activitylaunchmode;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener{    private static final String TAG = "MainActivity";    TextView tv;    Button ButtonOne;    Button ButtonTwo;    Button ButtonThree;    Button ButtonFour;        @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv = (TextView) findViewById(R.id.mTextView);        tv.setText("MainActivity");        ButtonOne = (Button) findViewById(R.id.buttonOne);        ButtonOne.setOnClickListener(this);        ButtonTwo = (Button) findViewById(R.id.buttonTwo);        ButtonTwo.setOnClickListener(this);        ButtonThree = (Button) findViewById(R.id.buttonThree);        ButtonThree.setOnClickListener(this);        ButtonFour = (Button) findViewById(R.id.buttonFour);        ButtonFour.setOnClickListener(this);    }        @Override    protected void onNewIntent(Intent intent) {        // TODO Auto-generated method stub        super.onNewIntent(intent);        Log.d(TAG, "onNewIntent");    }    @Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch (v.getId()) {        case R.id.buttonOne:            Intent mainIntent = new Intent(this,MainActivity.class);            startActivity(mainIntent);            break;        case R.id.buttonTwo:            Intent secondIntent = new Intent(this,SecondActivity.class);            startActivity(secondIntent);            break;        case R.id.buttonThree:            Intent ThirdIntent = new Intent(this,ThirdActivity.class);            startActivity(ThirdIntent);            break;        case R.id.buttonFour:            Intent FourIntent = new Intent(this,FourActivity.class);            startActivity(FourIntent);            break;        }    }}

SecondActivity.java

package com.example.activitylaunchmode;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class SecondActivity extends Activity implements OnClickListener {        private static final String TAG = "SecondActivity";    TextView tv;    Button ButtonOne;    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv = (TextView) findViewById(R.id.mTextView);        tv.setText("SecondActivity");        ButtonOne = (Button) findViewById(R.id.buttonOne);        ButtonOne.setOnClickListener(this);    }    @Override    protected void onNewIntent(Intent intent) {        // TODO Auto-generated method stub        super.onNewIntent(intent);        Log.d(TAG, "onNewIntent");    }    @Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch (v.getId()) {        case R.id.buttonOne:            Intent secondIntent = new Intent(this,SecondActivity.class);            startActivity(secondIntent);            break;        }    }}

ThirdActivity.java

package com.example.activitylaunchmode;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class ThirdActivity extends Activity implements OnClickListener {    private static final String TAG = "ThirdActivity";    TextView tv;    Button ButtonOne;    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv = (TextView) findViewById(R.id.mTextView);        tv.setText("ThirdActivity");        ButtonOne = (Button) findViewById(R.id.buttonOne);        ButtonOne.setOnClickListener(this);    }        @Override    protected void onNewIntent(Intent intent) {        // TODO Auto-generated method stub        super.onNewIntent(intent);        Log.d(TAG, "onNewIntent");    }    @Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch (v.getId()) {        case R.id.buttonOne:            Intent mainIntent = new Intent(this,MainActivity.class);            startActivity(mainIntent);            break;        default:            break;        }    }    }

FourActivity.java

package com.example.activitylaunchmode;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class FourActivity extends Activity implements OnClickListener {    private static final String TAG = "FourActivity";    TextView tv;    Button ButtonOne;    Button ButtonTwo;    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv = (TextView) findViewById(R.id.mTextView);        tv.setText("FourActivity");        ButtonOne = (Button) findViewById(R.id.buttonOne);        ButtonOne.setOnClickListener(this);    }        @Override    protected void onNewIntent(Intent intent) {        // TODO Auto-generated method stub        super.onNewIntent(intent);        Log.d(TAG, "onNewIntent");    }    @Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch (v.getId()) {        case R.id.buttonOne:            Intent MainIntent = new Intent(this,MainActivity.class);            startActivity(MainIntent);            break;        case R.id.buttonFour:            Intent FourIntent = new Intent(this,FourActivity.class);            startActivity(FourIntent);        default:            break;        }    }    }

 各个启动模式差异探究:

  1)standard:  默认模式,每启动一个activity都会在Task中创建一个,back键会依次从栈中退出

    MainActivity的启动模式是standard, 点击Button1,会再启动一个MainActivity.

    通过adb shell dumpsys activity命令, 我们能看到在Task中存在两个MainActivity.

    Task id #48      TaskRecord{2cfa2efd #48 A=com.example.activitylaunchmode U=0 sz=2}      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }        Hist #1: ActivityRecord{37783c3a u0 com.example.activitylaunchmode/.MainActivity t48}          Intent { cmp=com.example.activitylaunchmode/.MainActivity }          ProcessRecord{358547f2 29163:com.example.activitylaunchmode/u0a134}        Hist #0: ActivityRecord{363c8000 u0 com.example.activitylaunchmode/.MainActivity t48}          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }          ProcessRecord{358547f2 29163:com.example.activitylaunchmode/u0a134}    Running activities (most recent first):      TaskRecord{2cfa2efd #48 A=com.example.activitylaunchmode U=0 sz=2}        Run #1: ActivityRecord{37783c3a u0 com.example.activitylaunchmode/.MainActivity t48}        Run #0: ActivityRecord{363c8000 u0 com.example.activitylaunchmode/.MainActivity t48}

  

  2)singleTop:如果要启动的Activity在栈顶,则不会重新创建

     SecondActivity的启动模式是singleTop, 点击MainActivity中的Button2,会创建一个SecondActivity,再点击SecondActivity中的Button1,会重新启动 SecondActivity.

    通过adb命令,我们可以看到,Task中只有MainActivity和SecondActivity两个Activity,第二次点击并没有重新创建。从log中,我们可以看到,第二次点击启动SecondActivity,只是调用了前一个SecondActivity的onNewIntent方法。

    Task id #51      TaskRecord{fb41e01 #51 A=com.example.activitylaunchmode U=0 sz=2}      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }        Hist #1: ActivityRecord{1ea62f6c u0 com.example.activitylaunchmode/.SecondActivity t51}          Intent { cmp=com.example.activitylaunchmode/.SecondActivity }          ProcessRecord{69b44a6 30061:com.example.activitylaunchmode/u0a134}        Hist #0: ActivityRecord{27f7bb0a u0 com.example.activitylaunchmode/.MainActivity t51}          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }          ProcessRecord{69b44a6 30061:com.example.activitylaunchmode/u0a134}    Running activities (most recent first):      TaskRecord{fb41e01 #51 A=com.example.activitylaunchmode U=0 sz=2}        Run #1: ActivityRecord{1ea62f6c u0 com.example.activitylaunchmode/.SecondActivity t51}        Run #0: ActivityRecord{27f7bb0a u0 com.example.activitylaunchmode/.MainActivity t51}

  

  3)singleTask: 任务栈中没有这个Activity,则会在任务栈中创建一个实例,如果任务栈中已经存在,则会将任务栈中的此activity之上的activity全部出栈

    ThirdActivity的启动模式是singleTask, 点击MainActivity中的Button3,启动ThirdActivity,再点击ThirdActivity中的Button1,启动MainActivity,此时的Activity的堆栈信息如下:

    Task id #52      TaskRecord{147eed75 #52 A=com.example.activitylaunchmode U=0 sz=3}      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }        Hist #2: ActivityRecord{2bf26a69 u0 com.example.activitylaunchmode/.MainActivity t52}          Intent { cmp=com.example.activitylaunchmode/.MainActivity }          ProcessRecord{3e2f10a 30540:com.example.activitylaunchmode/u0a134}        Hist #1: ActivityRecord{147e2631 u0 com.example.activitylaunchmode/.ThirdActivity t52}          Intent { flg=0x10000000 cmp=com.example.activitylaunchmode/.ThirdActivity }          ProcessRecord{3e2f10a 30540:com.example.activitylaunchmode/u0a134}        Hist #0: ActivityRecord{4e87389 u0 com.example.activitylaunchmode/.MainActivity t52}          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }          ProcessRecord{3e2f10a 30540:com.example.activitylaunchmode/u0a134}    Running activities (most recent first):      TaskRecord{147eed75 #52 A=com.example.activitylaunchmode U=0 sz=3}        Run #2: ActivityRecord{2bf26a69 u0 com.example.activitylaunchmode/.MainActivity t52}        Run #1: ActivityRecord{147e2631 u0 com.example.activitylaunchmode/.ThirdActivity t52}        Run #0: ActivityRecord{4e87389 u0 com.example.activitylaunchmode/.MainActivity t52}

    这个也说明了standard启动模式会重新创建一个Activity.

    然后再点击MainActivity中的Button3,启动ThirdActivity,通过adb命令看到的如下: 

    Task id #53      TaskRecord{2553d3b2 #53 A=com.example.activitylaunchmode U=0 sz=2}      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }        Hist #1: ActivityRecord{33f3f7cd u0 com.example.activitylaunchmode/.ThirdActivity t53}          Intent { flg=0x10000000 cmp=com.example.activitylaunchmode/.ThirdActivity }          ProcessRecord{1cdd8f03 30924:com.example.activitylaunchmode/u0a134}        Hist #0: ActivityRecord{e5f9ea5 u0 com.example.activitylaunchmode/.MainActivity t53}          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }          ProcessRecord{1cdd8f03 30924:com.example.activitylaunchmode/u0a134}    Running activities (most recent first):      TaskRecord{2553d3b2 #53 A=com.example.activitylaunchmode U=0 sz=2}        Run #1: ActivityRecord{33f3f7cd u0 com.example.activitylaunchmode/.ThirdActivity t53}        Run #0: ActivityRecord{e5f9ea5 u0 com.example.activitylaunchmode/.MainActivity t53}

      能看到Task中现在只有两个Activity,ThirdActivity并没有重新创建,靠后的一个MainActivity也被弹出栈,从log也能看出调用了onNewIntent方法,

  

  4)singleInstance: 只有一个实例,运行于独立的task,启动此Activity的时候如果已经创建,则不会重新创建

    FourActivity的启动模式是singleInstance,点击MainActivity中的Button4,会启动FourActivity

    通过adb shell dumpsys activity命令,我们能看到两个Activity在不同的Task中,    

    Task id #55      TaskRecord{11be8b0d #55 A=com.example.activitylaunchmode U=0 sz=1}      Intent { flg=0x10000000 cmp=com.example.activitylaunchmode/.FourActivity }        Hist #0: ActivityRecord{1cd2b9e5 u0 com.example.activitylaunchmode/.FourActivity t55}          Intent { flg=0x10000000 cmp=com.example.activitylaunchmode/.FourActivity }          ProcessRecord{358d5ac2 31514:com.example.activitylaunchmode/u0a134}    Task id #54      TaskRecord{12e2f0d3 #54 A=com.example.activitylaunchmode U=0 sz=1}      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }        Hist #0: ActivityRecord{374dcd03 u0 com.example.activitylaunchmode/.MainActivity t54}          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }          ProcessRecord{358d5ac2 31514:com.example.activitylaunchmode/u0a134}    Running activities (most recent first):      TaskRecord{11be8b0d #55 A=com.example.activitylaunchmode U=0 sz=1}        Run #1: ActivityRecord{1cd2b9e5 u0 com.example.activitylaunchmode/.FourActivity t55}      TaskRecord{12e2f0d3 #54 A=com.example.activitylaunchmode U=0 sz=1}        Run #0: ActivityRecord{374dcd03 u0 com.example.activitylaunchmode/.MainActivity t54}

     如果再点击FourActivity中的Button4,也不会重新创建,从log可以看出,会调用onNewIntent方法,这里就不在贴activity的信息。

 

     adb shell dumpsys activity activities  也可以看到Task中各个activity的 launchMode.


0 0