您的位置:首页 > 移动开发 > Android开发

Activity的4种加载模式解析:

2015-08-08 20:08 561 查看
配置Activity的时候我们可以指定android:launchMode属性,该属性用于配置该Activity的加载模式,支持4个属性值:

1.standard:标准模式,系统默认的加载模式就是这个

2.singleTop:Task顶单例模式

3.singleTask:Task内单例模式

4.singleInstance:全局单例模式

Activity的加载模式的作用:android对Activity的管理是通过Task来管理多个activity的,当我们启动一个应用时,android就会位置创建一个task,我们可以把task理解成activity栈,task以栈的形式来管理activity,先启动的activity被放在task栈底,后面启动的放在上面,这也就是我们所的后进先出,activity的加载模式就负责实例化,加载activity的方式,并可以控制activity与task之间的加载关系。

模式一:standard

特性:这种模式不会启动新的task,新Activity将被添加到远来的task中,也就是说我们通过getTaskId()拿到的id号是同一个,但是activity的对象永远是新的一个,因此我们在task中的效果就是:



我们会发现点击三次对象是不断new出来的,因此activity没有复用,而且我们想要返回,是通过点击了4次back才返回的,这是以为启动的时候task中有一个,然后点击了三次,因此必须点击4次task才能清空!并且可以发现taskId是唯一的不变的

**

模式二:singleTop

**

这种模式的启动与standard模式基本相似,

1.只是当将要被启动的目标Activity已经位于Task栈顶时,系统不会重新创建目标Activity的实例

2.当将要被启动的Activity**没有位于Task栈顶时,系统会重新创建新的Activity**并且将它放到task栈顶,此时的特点体现于standard模式完全的相同!

实例演示:



点击了3次button,每次的activity都是一样的,说明我们没new新的出来,并且taskId也是同样的一个,测试的时候我们只需要把AndroidManifest.xml中的

lunchMode 由standard 改成 singleTop即可

<activity
android:name="com.qs.activitylifedemo.StandardTest"
android:label="@string/app_name"
android:launchMode="singleTop"
>


下面给出上面两个例子的测试code:

public class StandardTest extends Activity {
private TextView textView;
private ClickCountUtils utils = ClickCountUtils.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
this.setContentView(layout);
layout.setOrientation(LinearLayout.VERTICAL);
textView = new TextView(this);
textView.setText("当前的Activity是"+this.toString()+"\n 当前使用的taskId="+this.getTaskId()+"\n 你点击了"+utils.getClickCount()+"次");
layout.addView(textView);
Button button = new Button(this);
button.setText("点击跳转到taskId为"+getTaskId()+"的界面");
layout.addView(button);
button.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
utils.addOne();
textView.setText("当前的Activity是"+StandardTest.this.toString()+"\n 当前使用的taskId="+StandardTest.this.getTaskId()+"\n 你点击了"+utils.getClickCount()+"次");
Intent intent = new Intent(StandardTest.this,StandardTest.class);
startActivity(intent);
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
utils.reduceOne();
}

@Override
protected void onDestroy() {
super.onDestroy();
utils.clearClickCount();
}
}


而我们用来统计鼠标点击次数的就是一个简单的单例模式:

public class ClickCountUtils {
private static ClickCountUtils utils;
private static int ClickCount=0;
private ClickCountUtils(){

}
public static synchronized ClickCountUtils getInstance(){
if(utils == null){
utils = new ClickCountUtils();
}
return utils;
}

public void addOne(){
ClickCount++;
System.out.println(ClickCount);
}
public void reduceOne(){
ClickCount--;
if(ClickCount<0)ClickCount=0;
}
public int getClickCount(){
System.out.println("getClickCount="+ClickCount);
return ClickCount;
}
public void clearClickCount(){
ClickCount=0;
}
}


**

模式三:singleTask

**

采用这种加载模式的Activity 在同一个task内只有一个实例,分为三种情况:

1.如果将要启动的activity不存在,new一个并且添加到task栈顶

2.如果将要启动的activity存在且已经位于栈顶了,此时与singleTop模式行为相同

3.如果将要启动的activity存在但是没有位于栈顶,系统将会把它上面的所有的activity全部移除栈然后让其位于栈顶

这个模式的过程就有点复杂了,我们先通过一个图来了解一下怎么操作的



这个上面第一张图片是我们点击了button之后跳到第二个activity之后然后在点击跳回第一个activity的栈的效果,此时和standard模式是一样的因为singleTaskTest模式就是默认模式(standard),我们设置secondActivity模式为singleTask模式,因此点击再次点击singleTaskTest中的button跳到secondActivity的时候我们居然发现了点击事件被重置了,现在显示的是1,因此我们可以大胆的估算是调用了singleTaskTest中的onDestory函数,因为函数的写法是:

@Override
protected void onDestroy() {
System.out.println("SingleTaskTest call onDestory()");
super.onDestroy();
utils.clearClickCount();
}


然后看我们打印的结果:



发现函数被调用了,因此得出了当secondActivity想要显示在栈顶的时候,系统强制把位于它上面的所有的activity全部都移除栈顶了,因此我们点击事件才被重置了!

看一下我们的点击效果:



动画解析:

当我们进入的时候模式是standard模式的singleTaskTest—(显示点击0次)—>SecondActivity_SingleTask—(显示点击1次)—–>singleTaskTest—–(显示点击两次)—>然后在此点击的时候出发了singleTask的特性,也就是我们上面说的情况3,我们会清除singleTaskTest,因此看到了显示点击了1次(由于ui刷新太快,显示出了第一次的帧界面,暂且这样理解,我也不知道什么问题,知道的朋友还请多多指点一下,多谢!)然后立马显示点击0次,说明我们的singleTaskTest出栈了而且我们发现当显示点击两次的时候和显示0次的时候对象不是同一个对象,一个是2d4 一个是3c8然后点击的时候又出现了52c,这正是我们standard的特性,每次都是new一个新的activity,因此这个又在这里得到证实,最后点击back键的时候我们发现点击了一次,直接退出SecondActivity_SingleTask,然后再点击一次之后从singleTaskTest直接退出了app,因此这里我们可以得出task在SecondActivity_SingleTask在栈顶的时候是两个,你会发现最后一个出栈的永远是我们的第一个进栈的2d4,因此在点击2次的时候退栈需要三次,在点击到SecondActivity_SingleTask界面的时候需要两次,因为清除栈顶,只剩下第一次刚进来时候的栈底和自己本身,所以问题证明完毕!

模式四:singleInstance

在这种加载模式下,系统无论从哪个Task中启动Activity,只会创建一个Activity实例,并且会使用一个全新的栈来装载Activity实例,启动分如下两种情况:

1.如果要启动的Activity实例不存在,那么系统会创建一个全新的Task,再创建目标实例,并将它加入到新栈中

2.如果将要启动的目标Activity已经存在,那么无论位于哪个应用程序中,无论它位于哪个Task中,系统会自动的把该Activity所在的Task转到前台,从而使该Activity显示出来

需要指出的是,采用singleInstance模式加载Activity总是位于Task的顶部,采用这个模式加载的Task只包含这个Activity

下面看一下图片演示:



主要观察的是我们的两个taskId,这两个Activity中SecondActivity_SingleInstance 的模式是singleInstance SingleInstanceTest模式是standard,因此我们发现了SecondActivity_SingleInstance 为68 而SingleInstanceTest 为66 这个就是创建一个全新的Task,因此满足了特性1,而特性二我们只需要在创建一个app然后通过intent启动指定action的activity即可做到,这部分将在code中给出,因此不再多说!

效果显示如图:



我们可以发现我们从另一个app中直接跳到了我们app的SecondActivity_SingleInstance ,这里显示的就是我们的特性二

后话:貌似图片显示的很快,有点看不清楚,是因为csdn只限制2m,因此只能少帧了,还望谅解!

代码稍后给出,有什么写的不对的地方,还希望各位大神指出来,让我多多长姿势!

Code下载地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android