Activity系列讲解---Activity的四大启动模式

   开发者有时会问:为什么要为Activity指定加载模式?加载模式有什么作用?在这里,我简单的介绍以下,鄙人的理解:

Android中主要采用Task来管理Activity,当我们启动一个应用时,Android就会为之创建一个Task;然而Android中并没有为Task提供API,我们可以把Task理解为Activity栈,Task以栈的形式管理Activity.

  1.在AndroidManifest.xml中配置Activity时,可以指定android:launchModel属性,该属性用于配置Activity的加载模式。

  • standard:标准模式,也是默认的加载模式。用此模式启动一个Activity时,Android会为Activity创建一个新的实例,添加到当前的Task中。
  • singleTop:这种模式基本与standard模式相同,不同之处在于--->当要启动的的Activity已经位于Task的顶部时,系统不会重新创建Activity实例,而是复用当前Activity实例
  • singleTask:A(如果要启动的Activity不存在,系统会创建一个Activity实例,并将其加入到Task栈顶),B(若存在,并且位于Task栈顶,此时与singleTop模式的行为一致),C(若存在,不位于Task栈顶,系统会将此Activity上的所有Activity实例移出Task,从而使得此Activity位于栈顶)
  • singleInstance:A(如果要启动的Activity不存在,系统会创建一个新的Task,并创建一个Activity实例,并将其加入到Task栈顶),B(若存在,无论它位于哪个应用程序,哪个栈中,系统会将此Activity所在的Task栈转到前台,从而使得此Activity显示出来)

四大启动模式,只有singleInstance可能会重新创建一个全新的Task,拥有两个Task栈;其余的三种模式只有一个Task栈

2.启动模式可以在代码中启动,也可以在清单文件中设置

(1)代码中启动(借助Intent的flag属性)

  

(2)清单文件中配置

  

3.下面我写了一个Demo,两个Avrivity(A与B),每一个Activity里有一个TextView,两个Button

  (1)AActivity.class

/**
 * Activity的四种启动方式:
 * standard:默认的模式,每次启动startActivity()方法都会新建一个Activity对象
 * singTop:在当前任务栈中,判断栈顶是否为当前的Activity,如果是,直接使用;如果不是,再创建新的Activity,放入栈顶
 * singleTask:在当前任务栈中,判断栈里是否存在Activity,如果不存在,创建一个新的Activity入栈;如果存在,会把该Activity之上的所有Activity清除出栈,显示当前Activity
 * singleInstance:新创建一个任务栈,放入新创建的Activity,该任务栈只允许存在一个Activity实例,如果已存在,那么切换到该任务栈。
 *
 */
public class AActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
    }

    //启动AActivity
    public void buttonOneClick(View view){
        Intent intent = new Intent(this,AActivity.class);
        startActivity(intent);
    }

    //启动BActivity
    public void buttonTwoClick(View view){
        Intent intent = new Intent(this,BActivity.class);
        startActivity(intent);
    }

}

  

  (2)BActivity.class

public class BActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);
    }

    //启动AActivity
    public void buttonOneClick(View view){
        Intent intent = new Intent(this,AActivity.class);
        startActivity(intent);
    }

    //启动BActivity
    public void buttonTwoClick(View view){
        Intent intent = new Intent(this,BActivity.class);
        startActivity(intent);
    }
}

  

  (3)activity_a.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_a"
    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.langdon.taiyang.androidtest.Intent.AActivity">

    <TextView
        android:id="@+id/tv_activity_one"
        android:text="A-->Activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/bt_activity_one"
        android:layout_below="@+id/tv_activity_one"
        android:text="A--Activity"
        android:onClick="buttonOneClick"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/bt_activity_two"
        android:layout_below="@+id/bt_activity_one"
        android:text="B--Activity"
        android:onClick="buttonTwoClick"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>

  

  (4)activity_b.xml   

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_b"
    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.langdon.taiyang.androidtest.Intent.BActivity">

    <TextView
        android:id="@+id/tv_activity_two"
        android:text="B-->Activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/bt_activity_three"
        android:layout_below="@+id/tv_activity_two"
        android:text="A--Activity"
        android:onClick="buttonOneClick"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/bt_activity_four"
        android:layout_below="@+id/bt_activity_three"
        android:text="B--Activity"
        android:onClick="buttonTwoClick"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>

 

4.运行结果以及四种启动模式分析

从配置文件中可以看出AActivity没有设置launchMode属性,默认会启用standard启动模式,下面我们以图1分析启动模式

      图1

(1)android:launchMode="standard"

  当应用程序开启时,A(AActivity)入栈,在AActivity中点击B--Activity按钮,会重新创建BActivity实例,B(BActivity)入栈,同时跳转到BActivity中;

然后在BActivity中点击A--Activity按钮,A(AActivity)入栈,同时跳转到AActivity中.Task栈中的情况如图1所示。

(2)android:launchMode="singleTop"

  当应用程序开启时,A(AActivity)入栈,在AActivity中点击B--Activity按钮,会重新创建BActivity实例,B(BActivity)入栈,同时跳转到BActivity中;

然后在BActivity中点击B--Activity按钮,此时BActivity实例位于Task栈顶,不会重新创建BActivity实例,B也不会入栈(即使点击多次B--Activity按钮);

然后在BActivity中点击A--Activity按钮,A(AActivity)入栈,同时跳转到AActivity中.Task栈中的情况如图1所示。

        图2

------------------------------>

        图3  

(3)android:launchMode="singleTask"

  当应用程序开启时,A(AActivity)入栈,在AActivity中点击A--Activity按钮,会重新创建AActivity实例,A(AActivity)入栈,

然后在AActivity中点击B--Activity按钮,会重新创建BActivity实例,B(BActivity)入栈,

然后在BActivity中点击A--Activity按钮,A(AActivity)入栈,同时跳转到AActivity中.Task栈中的情况如图2所示。

再在AActivity中点击B--Activity按钮,系统会在Task栈中查找B,B存在且不在栈顶,系统会将B上的A移出Task栈,使得B位于栈的顶部。Task栈中的情况如图3所示,点击3次退出按钮,此程序会退出。

             图4--A栈

-------->

              图5--B栈

---->

              图6

         图6

------------>

                                     图 7

--->

 

      图8

(4)android:launchMode="singleInstance"-------A栈只能存放AActivity的实例,B栈只能存放BActivity的实例

  当应用程序开启时,A(AActivity)入栈,在AActivity中点击A--Activity按钮,会重新创建AActivity实例,A(AActivity)入栈,如图4所示。

然后在AActivity中点击B--Activity按钮,会创建一个全新的Task栈,同时创建BActivity实例,B(BActivity)入B栈,此时B栈在前面,A栈在后边。如图6所示

然后在BActivity中点击A--Activity按钮,A(AActivity)入A栈,此时A栈在前面,B栈在后边,同时跳转到AActivity中.Task栈中的情况如图7所示。

再在AActivity中点击3次退出按钮,A会退出,如图8所示。在B栈中点击1次退出按钮,此程序会退出。

原文地址:https://www.cnblogs.com/langdon/p/6266052.html