activity启动模式之singleTask
singleTask 的启动模式,网上的资料说的如下
这种方式启动的Activity总是属于一个任务的根Activity,也就是说,如果这个任务不存在,那么会创建一个新的task,然后创建实例,放到这个task最底层
如果这个实例已经存在,那么它会把这个实例上层的所有其他activity实例去掉,使得它成为这个task的顶层实例。但是,我们看下我们的验证
关键代码如下
1.manifest.xml
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:logo="@drawable/action_mode_search_normal_white_p" android:theme="@style/AppTheme" > <activity android:name=".HeadSetActivity" android:label="@string/app_name" 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=".MyActivity1" android:label="@string/app_name" android:launchMode="singleTask" > <intent-filter> <action android:name="activity_one" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:name=".MyActivity2" android:label="@string/app_name" android:launchMode="standard" > <intent-filter> <action android:name="activity_two" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application>
三个activity
HeadSetActivity.java
package com.example.alert; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class HeadSetActivity extends Activity { private TextView textView; private Button button1; private Button button2; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.tv); button1 = (Button) findViewById(R.id.bt1); button2 = (Button) findViewById(R.id.bt2); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub //启动activity1 Intent intent = new Intent("activity_one"); startActivity(intent); } }); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub //启动activity2 Intent intent = new Intent("activity_two"); startActivity(intent); } }); } }
MyActivity1.java
package com.example.alert; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MyActivity1 extends Activity { private TextView textView; private Button button1; private Button button2; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.tv); textView.setText("i am activity1"); button1 = (Button) findViewById(R.id.bt1); button1.setText("HeadSetActivity"); button2 = (Button) findViewById(R.id.bt2); button2.setText("Activity2"); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub Intent intent = new Intent(); intent.setClass(MyActivity1.this, HeadSetActivity.class); startActivity(intent); } }); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub Intent intent = new Intent("activity_two"); startActivity(intent); } }); } }
MyActivity2.java
package com.example.alert; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MyActivity2 extends Activity { private TextView textView; private Button button1; private Button button2; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.tv); textView.setText("i am activity2"); button1 = (Button) findViewById(R.id.bt1); button1.setText("HeadSetActivity"); button2 = (Button) findViewById(R.id.bt2); button2.setText("Activity1"); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub Intent intent = new Intent(); intent.setClass(MyActivity2.this, HeadSetActivity.class); startActivity(intent); } }); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub Intent intent = new Intent("activity_one"); startActivity(intent); } }); } }
然后我们进行如下顺序的操作
启动HeadSetActivity->MyActivity1->HeadSetActivity
Running activities (most recent first): TaskRecord{42da7550 #15 A=com.example.alert U=0 sz=3} Run #2: ActivityRecord{42f48dc0 u0 com.example.alert/.HeadSetActivity t15} Run #1: ActivityRecord{42e99698 u0 com.example.alert/.MyActivity1 t15} Run #0: ActivityRecord{42502ae0 u0 com.example.alert/.HeadSetActivity t15}
然后我们在上面操作的基础上,再次跳转到MyActivity1
Running activities (most recent first): TaskRecord{42da7550 #15 A=com.example.alert U=0 sz=2} Run #1: ActivityRecord{42e99698 u0 com.example.alert/.MyActivity1 t15} Run #0: ActivityRecord{42502ae0 u0 com.example.alert/.HeadSetActivity t15}
从上面我们可以发现两个问题
1.作为singleTask的MyActivity1,确实在实例已经存在的情况下,再次生成会把它前面的activity消除出栈,自己成为栈顶
2.在创建MyActivit1实例的时候,并没有生成新的task。
调查这个问题,我们在网上找到了原因,参考
http://blog.csdn.net/luoshengyang/article/details/6714543
然后我们仅仅验证下
更改manifest.xml如下
<activity android:name=".MyActivity1" android:label="@string/app_name" android:taskAffinity="com.example.alert.test" android:launchMode="singleTask" > <intent-filter> <action android:name="activity_one" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
我们按照如下顺序启动activity
HeadSetActivity->MyActivity1
Running activities (most recent first): TaskRecord{42e54a78 #19 A=com.example.alert.test U=0 sz=1} Run #1: ActivityRecord{4342b528 u0 com.example.alert/.MyActivity1 t19} TaskRecord{42ccd960 #18 A=com.example.alert U=0 sz=1} Run #0: ActivityRecord{43427768 u0 com.example.alert/.HeadSetActivity t18}
我们发现确实生成了一个新的task
如果我们在上面的基础上,再次跳转到HeadSetActivity 如下
Running activities (most recent first): TaskRecord{42e54a78 #19 A=com.example.alert.test U=0 sz=2} Run #2: ActivityRecord{42502ae0 u0 com.example.alert/.HeadSetActivity t19} Run #1: ActivityRecord{4342b528 u0 com.example.alert/.MyActivity1 t19} TaskRecord{42ccd960 #18 A=com.example.alert U=0 sz=1} Run #0: ActivityRecord{43427768 u0 com.example.alert/.HeadSetActivity t18}
我们会发现,新的实例HeadSetActivity是跟MyActivity1在同一个栈里面的。当我们再次计划MyActivity1的时候,它会移除它上面的activity,自己成为栈顶。这其实就验证了那句话,
拥有singleTask的activity,永远都会作为一个栈的栈底,哪怕他也可作为栈顶,只不过这时候整个栈就它自己而已
如果这个activity销毁了,那么它所在的栈也就被销毁了。
现在总结如下
1.如果一个activity的launchmode被设置为singleTask,这时候创建它的时候,并不会创建新的task,而是把自己放到父activity同一个栈中,而且,当再次启动它的时候,这个栈里面,在它上面的activity就会被移除出栈,它成为栈顶
2.如果你同时设定了launchmode被设置为singleTask跟android:taskAffinity,那么创建它的activity的时候,同时会创建一个新的task,并把它作为栈底,之后它启动的activity,也会放到这个栈中。当再次启动它的时候,它同样会清除栈内其他的activity,把自己作为栈顶跟栈底