Activity的启动模式

来源:互联网 发布:国学软件哪个好啊 编辑:程序博客网 时间:2024/06/05 14:47

Activity的启动模式有4个,分别为standard、singleTop、singleTask、singleInstance。用户可以在AndroidManifest.xml中注册Activity时设置它的启动模式,例如:

  <activity android:name=".A"            android:launchMode="singleTask"/>

下面我们来一起看一下这四种启动模式
一、standard(标准启动模式)
这是Activity的标准启动模式,也是Activity的默认启动模式。在这种模式下,Activity可以被多次实例化,即在同一个任务栈中可以存在多个Activity实例,每个实例都会处理一个Intent对象。如果ActivityA的启动模式为standard。并且已经有一个ActivityA被启动,在该ActivityA中启动一个新的ActivityA实例。那么栈中会有2个ActivityA。
standard
附上测试代码:
A.java

public class A extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_a);        findViewById(R.id.a_btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(A.this,A.class));            }        });    }}

AndroidManifest.xml

  <activity            android:name=".A"            android:taskAffinity="com.simple.myapplication.task1" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>

执行 adb shell dumpsys activity 查看结果:

一开始只有一个ActivityA实例时: Stack #1:   Task id #149     TaskRecord{1a7d0c7e #149 A=com.simple.myapplication.task1 U=0 sz=1}     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000mp=com.simple.myapplication/.A }       Hist #0: ActivityRecord{3933a57 u0 com.simple.myapplication/.A t149}         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x1000000 cmp=com.simple.myapplication/.A }         ProcessRecord{e66022c 13440:com.simple.myapplication/u0a57}   Running activities (most recent first):     TaskRecord{1a7d0c7e #149 A=com.simple.myapplication.task1 U=0 sz=1}       Run #0: ActivityRecord{3933a57 u0 com.simple.myapplication/.A t149}   mResumedActivity: ActivityRecord{3933a57 u0 com.simple.myapplication/.A t149}点击按钮继续启动一个ActiviyA 时: Stack #1:   Task id #149     TaskRecord{1a7d0c7e #149 A=com.simple.myapplication.task1 U=0 sz=2}     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000mp=com.simple.myapplication/.A }       Hist #1: ActivityRecord{102084f5 u0 com.simple.myapplication/.A t149}         Intent { cmp=com.simple.myapplication/.A }         ProcessRecord{e66022c 13440:com.simple.myapplication/u0a57}       Hist #0: ActivityRecord{3933a57 u0 com.simple.myapplication/.A t149}         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x1000000 cmp=com.simple.myapplication/.A }         ProcessRecord{e66022c 13440:com.simple.myapplication/u0a57}   Running activities (most recent first):     TaskRecord{1a7d0c7e #149 A=com.simple.myapplication.task1 U=0 sz=2}       Run #1: ActivityRecord{102084f5 u0 com.simple.myapplication/.A t149}       Run #0: ActivityRecord{3933a57 u0 com.simple.myapplication/.A t149}   mResumedActivity: ActivityRecord{102084f5 u0 com.simple.myapplication/.A t149}

二、singleTop(栈顶复用模式)
如果有一个以singleTop模式启动的Activity的实例已经存在于任务的栈顶,那么在启动这个Activity时,不会创建实例,而是重用位于栈顶的那个实例,并且会调用该实例的OnNewIntent()方法。
singleTop
附上测试代码:
B.java

public class B extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_b);        //启动Activity A        findViewById(R.id.b_btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(B.this,A.class));            }        });    }}

A.java

public class A extends AppCompatActivity {    private static final String TAG = "A";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_a);        //启动Activity A        findViewById(R.id.a_btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(A.this,A.class));            }        });        Log.i(TAG, "onCreate: ");    }    @Override    protected void onNewIntent(Intent intent) {        super.onNewIntent(intent);        Log.i(TAG, "onNewIntent: ");    }}

AndroidManifest.xml

 <activity            android:name=".A"            android:launchMode="singleTop"            android:taskAffinity="com.simple.myapplication.task1" >        </activity>        <activity            android:name=".B"            android:taskAffinity="com.simple.myapplication.task1" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>

测试结果:

第一步:栈中存在B、A时 Stack #1:   Task id #151     TaskRecord{22b8911f #151 A=com.simple.myapplication.task1 U=0 sz=2}     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000mp=com.simple.myapplication/.B bnds=[556,958][704,1142] (has extras) }       Hist #1: ActivityRecord{2c7a4235 u0 com.simple.myapplication/.A t151}         Intent { cmp=com.simple.myapplication/.A }         ProcessRecord{21c76c6c 25188:com.simple.myapplication/u0a57}       Hist #0: ActivityRecord{826ed5f u0 com.simple.myapplication/.B t151}         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x1000000 cmp=com.simple.myapplication/.B bnds=[556,958][704,1142] (has extras) }         ProcessRecord{21c76c6c 25188:com.simple.myapplication/u0a57}   Running activities (most recent first):     TaskRecord{22b8911f #151 A=com.simple.myapplication.task1 U=0 sz=2}       Run #1: ActivityRecord{2c7a4235 u0 com.simple.myapplication/.A t151}       Run #0: ActivityRecord{826ed5f u0 com.simple.myapplication/.B t151}第二步:点击A中的按钮,继续启动 ActivityA实例。  Stack #1:   Task id #151     TaskRecord{22b8911f #151 A=com.simple.myapplication.task1 U=0 sz=2}     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000mp=com.simple.myapplication/.B bnds=[556,958][704,1142] (has extras) }       Hist #1: ActivityRecord{2c7a4235 u0 com.simple.myapplication/.A t151}         Intent { cmp=com.simple.myapplication/.A }         ProcessRecord{21c76c6c 25188:com.simple.myapplication/u0a57}       Hist #0: ActivityRecord{826ed5f u0 com.simple.myapplication/.B t151}         Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x1000000 cmp=com.simple.myapplication/.B bnds=[556,958][704,1142] (has extras) }         ProcessRecord{21c76c6c 25188:com.simple.myapplication/u0a57}   Running activities (most recent first):     TaskRecord{22b8911f #151 A=com.simple.myapplication.task1 U=0 sz=2}       Run #1: ActivityRecord{2c7a4235 u0 com.simple.myapplication/.A t151}       Run #0: ActivityRecord{826ed5f u0 com.simple.myapplication/.B t151}    可以发现栈中并无变化。    查看log信息:    com.simple.myapplication I/A: onNewIntent:      执行了Activity A 的 OnNewInstance方法

三、singleTask(栈内复用模式)
如果一个Activity设置了该启动模式,那么一个任务栈中只能存在一个该Activity的实例。如果任务栈中存在该activity那么就不会创建新的activity,而是将这个已经存在的activity移至栈顶,并将位于该activity之上的别的activity销毁。并且和singleTop一样,会执行该activity的onNewIntent()函数。

singleTask

附上测试代码:

public class A extends AppCompatActivity {    private static final String TAG = "A";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_a);        //启动Activity B        findViewById(R.id.a_btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(A.this,B.class));            }        });        Log.i(TAG, "onCreate: ");    }    @Override    protected void onNewIntent(Intent intent) {        super.onNewIntent(intent);        Log.i(TAG, "onNewIntent: ");    }}
public class B extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_b);        //启动Activity c        findViewById(R.id.b_btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(B.this,C.class));            }        });    }}
public class B extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_b);        //启动Activity c        findViewById(R.id.b_btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(B.this,C.class));            }        });    }}
public class C extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_c);        findViewById(R.id.c_btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(C.this,A.class));            }        });    }}
        <activity            android:name=".A"            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=".B"            >        </activity>        <activity            android:name=".C"            >        </activity>

测试流程: A启动B,B启动C ,C启动A 导致了BC出栈,最后栈中只剩下A,按返回键会返回桌面。

还有,假设现在存在2个栈,一个前台栈里面包含A,B和一个后台栈C,D
那么在B中启动D。将导致后台栈切换到前台。
这里写图片描述

另外我在测试中发现taskAffinity可以用来设置栈名称,一般情况下只有在启动模式为singleTask或者singleInstance和他配对使用时,启动的activity才会进入一个和这个名字相同的栈中。或者还有一种情况他会进入一个栈名称为taskAffiity设置的那个栈中,就是当启动他的activity的启动模式singleInstane时,他将创建一个栈名为taskAffinity的栈,用来压入新启动的activity。这是因为singleInstance的属性导致的他自身的栈中不能压入其他的Activity,所以会重新创建一个栈名为taskAffinity的栈用来存放启动的activity。

四、singleInstance(单实例模式)
这是一种加强的singleTask模式,它除了具有singleTask模式的属性外,还加强了一点,那就是该模式的Activity只能单独的位于一个任务栈中
singleInstance

附上测试代码:

public class A extends AppCompatActivity {    private static final String TAG = "A";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_a);        findViewById(R.id.a_btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(A.this,B.class));            }        });        Log.i(TAG, "onCreate: ");    }    @Override    protected void onNewIntent(Intent intent) {        super.onNewIntent(intent);        Log.i(TAG, "onNewIntent: ");    }}
public class B extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_b);        findViewById(R.id.b_btn).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(B.this,D.class));            }        });    }}
        <activity            android:name=".A"            android:taskAffinity="com.simple.myapplicaiton.task1"            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=".B"            android:taskAffinity="com.simple.myapplicaiton.task1"            android:launchMode="singleInstance"            >        </activity>

最终导致栈中的信息为:

    Task id #238      TaskRecord{1ae14361 #238 A=com.simple.myapplicaiton.task1 U=0 sz=1}      Intent { flg=0x10000000 cmp=com.simple.myapplication/.B }        Hist #0: ActivityRecord{e8fbd4d u0 com.simple.myapplication/.B t238}          Intent { flg=0x10000000 cmp=com.simple.myapplication/.B }          ProcessRecord{12776e86 300:com.simple.myapplication/u0a57}    Task id #237      TaskRecord{22b1347 #237 A=com.simple.myapplicaiton.task1 U=0 sz=1}      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000cmp=com.simple.myapplication/.A }        Hist #0: ActivityRecord{31785bab u0 com.simple.myapplication/.A t237}          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.simple.myapplication/.A }          ProcessRecord{12776e86 300:com.simple.myapplication/u0a57}可以发现存在2个栈
0 0
原创粉丝点击