Android Activity的4种启动模式详解(示例)
转截请标明出處:http://hovertree.com/
先详细介绍下Android对Activity的管理方法,Android选用Task来管理方法好几个Activity,在我们运行一个运用时,Android便会为此建立一个Task,随后运行这一运用的通道Activity(即<intent-filter…/>中配备为 MAIN和LAUNCHER的Activity)。
由于Android并沒有为Task出示API,因而我们无法真实去浏览Task,只有启用Activity的getTaskId()方式来获得它所属的Task的ID。实际上我们可以把Task了解成Activity栈,Task以栈的方式来管理方法Activity:先运行的Activity被放到Task栈底,后运行的Activity被放到Task栈顶。
那麼Activity的载入方式,就部门管理实例化、载入Activity的方法、并能够操纵Activity与Task中间的关联。
Activity有4中运行方式,各自为:standard,singleTop,singleTask,singleInstance。假如要应用这四种运行方式,务必在manifest文档中<activity>标识中的launchMode特性配备,如:
<activity
android:name=”.MainActivity”
android:label=”@string/app_name”
android:launchMode=”standard”
>
</activity>
standard
规范运行方式,也是Android的默认设置运行方式。在这类方式下运行的activity能够被数次实例化,即在一个每日任务中能够存有好几个activity案例,每一个案例都是会解决一个Intent目标。假如Activity A的运行方式为standard,而且A早已运行,在A中再度运行Activity A,即启用startActivity(new Intent(this,A.class)),会在A的上边再度运行一个A的案例,即当今的栈中的情况为A–>A。
singleTop
假如一个以singleTop方式运行的activity的案例早已存有于每日任务栈的栈顶,那麼再度运行这一activity时,不容易建立新的案例,只是器重坐落于栈顶的那一个案例,而且会启用该案例的onNewIntent()方式将Intent目标传送到这一案例中。举例来说,假如A的运行方式为singleTop,而且A的一个案例早已存有于栈顶中,那麼再启用startActivity(new Intent(this,A.class))运行A时,不容易再建立A的案例,只是器重原先的案例,而且启用原先案例的onNewIntent()方式。这时候每日任务栈中還是有一个A的案例。
假如以singleTop方式运行的activity的一个案例早已存有于每日任务栈中,可是没有栈顶,那麼它的个人行为和standard方式同样,也会建立好几个案例。
singleTask
官方网文本文档上称,假如一个activity的运行方式为singleTask,那麼系统软件总是会在一个新的每日任务的最底端(root)运行这一activity,而且被这一activity运行的其他activity会和该activity另外存有于这一新每日任务中。假如系统软件中早已存有一个那样的activity则会器重这一案例,而且启用它的onNewIntent()方式。即,那样的一个activity在系统软件中总是存有一个案例。
可是这类叫法并不精确,选用singleTask运行总体目标Activity时,可分三种状况:
1、假如即将打开的总体目标Activity不会有,系统软件可能建立总体目标Activity案例,并将它放进Task栈顶。
2、假如即将运行的总体目标Activity早已坐落于Task栈顶,这时与singleTop方式的个人行为同样。
3、假如即将运行的总体目标Activity早已存有、但沒有坐落于Task栈顶,系统软件可能把坐落于该Activity上边的全部Activity移除Task栈,进而促使总体目标Activity转到栈顶。
下边根据案例表明:
2个Activity,FirstActivity表明输入框和按键,该按键用以运行SecondActivity;SecondActivity表明输入框和按键,该按键用以运行FirstActivity。
public class FirstActivity extends Activity { TextView tv; Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView) findViewById(R.id.tv); tv.setText("Activity为:" this.toString() ",Task ID为:" this.getTaskId()); btn=(Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(FirstActivity.this, SecondActivity.class); startActivity(intent); } }); } }
public class SecondActivity extends Activity { TextView tv; Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); tv=(TextView) findViewById(R.id.tv); tv.setText("Activity为:" this.toString() ",Task ID为:" this.getTaskId()); btn=(Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(SecondActivity.this, FirstActivity.class); startActivity(intent); } }); } }
运作该案例,系统软件默认设置运行FirstActivity,点一下该页面按键,系统软件以singgleTask方式开启SecondActivity ,这时Task栈中有两个Activity(从底向上):FirstActivity–>SecondActivity.
点一下SecondActivity页面按键,系统软件以标准模式再度运行FirstActivity,这时Task栈中有三个Activity(从底向上):FirstActivity–>SecondActivity–>FirstActivity.
在FirstActivity中再度点一下按键,系统软件以singleTask方式再度开启SecondActivity,系统软件会将坐落于SecondActivity上边的全部Activity移除,促使SecondActivity进到栈顶,这时Task栈中仅有2个Activity(从底向上):FirstActivity–>SecondActivity.
设计效果图(先后):
singleInstance
一直在新的每日任务中打开,而且这一新的每日任务中有且只有这一个案例,换句话说被该案例运行的别的activity会自启动于另一个每日任务中。当再度运行该activity的案例时,会器重已存有的每日任务和案例。而且会启用这一案例的onNewIntent()方式,将Intent案例传送到该案例中。和singleTask同样,同一時刻在系统软件中总是存有一个那样的Activity案例。
表明:
这类载入方式下,系统软件确保不管从哪一个Task中运行总体目标Activity,总是建立一个总体目标Activity案例,并会应用一个全新升级的Task栈来装车该Activity案例。
当用singleInstance运行总体目标Activity时,分二种状况:
1、当即将运行的总体目标Activity不会有,系统软件会先建立一个全新升级的Task、再建立总体目标Activity的案例,并将它添加新的Task的栈顶。
2、假如即将运行的总体目标Activity早已存有,不管它坐落于哪一个应用软件中,不管它坐落于哪一个Task中,系统软件可能把该Activity所属的Task转至前台接待,进而应用该Activity表明出去。
选用该方式载入的Activity一直坐落于Task栈顶,所属Task只包括该Activity.
举例子:
点一下FirstActivity中按键,运行SecondActivity。SecondActivity配备成singleInstance载入方式,export特性配备成true—说明该Activity可被其他运用运行。
public class FirstActivity extends Activity { TextView tv; Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView) findViewById(R.id.tv); tv.setText("Activity为:" this.toString() ",Task ID为:" this.getTaskId()); btn=(Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(FirstActivity.this, SecondActivity.class); startActivity(intent); } }); } }
<activity android:name=".SecondActivity" android:launchMode="singleInstance" android:exported="true" > <intent-filter> <!--了解该Activity能回应Action为特定字符串数组的Intent --> <action android:name="joanna.yan.action.TEST_ACTION" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
开机启动新的Task并且用新的Task载入新创建的SecondActivity案例,SecondActivity一直坐落于栈顶。
设计效果图:
另一个实例选用隐式Intent再度运行该SecondActivity。
编码:
public class OtherActivity extends Activity { TextView tv; Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); tv=(TextView) findViewById(R.id.tv); tv.setText("Activity为:" this.toString() ",Task ID为:" this.getTaskId()); btn=(Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(); intent.setAction("joanna.yan.action.TEST_ACTION"); startActivity(intent); } }); } }
点击OtherActivity中的按键隐式运行singleInstance方式的SecondActivity,假如前边一个实例还未撤出,不管SecondActivity所属Task是不是坐落于前台接待,系统软件将再度把SecondActivity所属Task转到前台接待,进而将SecondActivity表明出去。
设计效果图: