为了账号安全,请及时绑定邮箱和手机立即绑定

Android中活动的启动模式

标签:
Android 活动

自从跟某Android群里的小伙伴们说了“本皮卡丘要开始写文章了”之后,有时候皮卡丘在群里愉快得水着水着就有人冒出一句“皮卡丘你怎么还在水,文章呢?”吓得我整个人都玉泉鱼跃了有木有,还能不能愉快地装逼了!
图片描述
好吧,其实皮卡丘并不是在偷懒,只是一直想写一些高大上狂炫酷霸拽的知识来着,然而很多知识虽然自己会用,也看了很多技术文章,可是到了要开始敲的时候却完全不知道能写些啥,果然还是技术功底&文字功底不行啊。所以还是先写一些面向新手的文章吧~~~
那么今天我们来学习的就是Activity的四种启动模式:standard,singleTop,singleTask,singleInstance。

1、standard
这个模式是新手们遇到最最多的一种启动模式。什么?你说你压根就没用过......其实你用或者不用,standard都在那里,不离不弃,因为他就是默认的......你看看你们,一直使用着人家却连他的存在都不知道,难道你们不觉得愧疚吗!所以赶紧来了解一下吧。
学习过Android开发的小伙伴们应该都知道,在Android里面使用频率非常高的一个功能就是“打开一个活动(Activity)”,然后如果我们finish掉新活动的时候就会回退到前一个活动,这是因为Android是通过返回栈来管理活动的,在standard模式下,我们每新建一个活动,就会将他放回返回栈的栈顶,而finish掉一个活动,就会将他从栈里移除(这样,下面的活动就会成为栈顶)。这是比较好理解的,我们可以通过代码来观察一下。
我们新建3个Activity:MainActivity,ActivityOne,ActivityTwo。逻辑很简单,在MainActivity中放置按钮跳转到ActivityOne,ActivityOne中放置按钮跳转到ActivityTwo。ActivityTwo里面暂时不放什么逻辑,然后在每个Activity的onCreate方法里将Activity名称打印出来。OK,运行程序,点击按钮先跳转到ActivityOne,然后跳转到ActivityTwo。查看日志。
图片描述
就是最普通的每一次跳转打开一个Activity,相信小伙伴们都能很好的理解吧。

2、singleTop
好,我们来假设一下这样的场景:如果某个按钮的点击事件,在跳转Activity之前要进行很多操作(比如网络请求),然后才能进行跳转。也就是说,在“点击这个按钮”和“activity的跳转”之间存在一个时间间隔,并且这个间隔足够我们点击第二下甚至很多下。那么会发生什么现象呢?
OK,我们来修改代码,把MainActivity的点击事件进行修改。

case R.id.button1:
            /*Intent intent = new Intent(MainActivity.this, ActivityOne.class);
            startActivity(intent);*/
            new Handler().postDelayed(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    Intent intent = new Intent(MainActivity.this, ActivityOne.class);
                    startActivity(intent);
                }
            }, 2000);
            break;

代码中注释掉是原来的跳转代码,而新的代码则是延迟2000ms之后再跳转,运行程序,快速点击两次按钮,我们来观察日志。
图片描述
我们惊奇得发现,ActivityOne被创建了2次,我们在手机里也可以看到,需要回退2次才能重新回到MainActivity。这在大部分情况下是很不好的用户体验,那么该如何解决这个问题呢?这就涉及到Activity的第二种启动模式:singleTop。
我们先从文学的角度来分析下这一种启动模式:single者,单也;Top者,顶也;故而所谓singleTop,单顶也!(这个逼装的,我给10分!)通俗得说:就是不能有2个相同的活动同时在栈顶,如果某个singleTop模式的活动已经在栈顶了,那么再次跳转到相同的活动时会直接使用原来那个活动而不会另外创建一个。我们通过代码来看一看效果:
修改ActivityOne的启动模式为singleTop:

AndroidManifest.xml

<activity
            android:name=".ActivityOne"
            android:launchMode="singleTop" >
</activity>

然后执行代码,这时候我们以迅雷不及掩耳盗铃叮当响之势快速点击多次按钮,然后来查看日志
图片描述
果然和一开始的结果不一样了,哪怕你以英雄联盟中瑞文光速QA的手速点击按钮,也别想多创建出一个ActivityOne。然后我们点击回退按钮,也只需要一次就能回到MainActivity。

3、singleTask
不知道细心的小伙伴们有没有注意到上一节中的描述“就是不能有2个相同的活动同时在栈顶 ”,那如果两个活动并不是同时在栈顶呢?同时,我们来思考一下这样一种场景:我们从首页去注册账号(虽然一般有专门的登录注册页面,不过这里简单起见就把这个入口放在首页),然后填写了一大堆资料之后注册成功跳转回首页。那么这里有个问题,如果这时候我点了回退键,我们应不应该按照正常的Activity回退顺序回退到注册填写页面呢?答案很显然是否定的,毕竟,我都注册完了,怎么还能回退到注册填写页面呢?好哒,我们先用singleTop来试试。
我们先将ActivityOne的延时代码换回正常的跳转代码,然后在ActivityTwo中添加一个按钮,点击事件是跳转到ActivityOne,现在的跳转逻辑就变成了:MainActivity->ActivityOne->ActivityTwo->ActivityOne。运行程序,我们来看看结果:
图片描述
从日志中我们看出来,ActivityOne被创建了两次。然后我们点回退键,好吧一切就跟默认模式一样,先回到ActivityTwo,再回到ActivityOne,最后回到MainActivity。看来面对这样的需求,就算使用了singleTop也并没有什么卵用啊。那该怎么办?!这个时候就该轮到singleTask出场啦。
如果一个活动的模式是singleTask,那么每次创建这个活动的时候,系统都会去检查整个活动栈中是否已经有这个活动,如果没有就新建,如果已经有了就直接使用已经存在的活动,并将这个活动之上的所有其他活动统统关闭掉。我们用代码来实验一下看看效果。
我们把ActivityOne的启动模式修改为singleTask,并且重写ActivityTwo的onDestroy方法

AndroidManifest.xml

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

ActivityTwo

@Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        Log.d("ActivityTwo", "ActivityTwo_finish");
        super.onDestroy();
    }

运行代码,查看日志
图片描述
从日志中我们可以看出来,已经存在的ActivityOne不再重新创建,而且位于ActivityOne之上的ActivityTwo也确实被关闭掉了。

4、singleInstance
若要说启动模式里面最复杂的,那就莫过于singleInstance了。singleInstance其实和singleTask有点类似,都是系统中只会存在一个相同的活动(如果不存在就新建,已经存在就使用原来那个),但是他们有一个最大的区别就是:singleTask模式的活动是在原有的栈中创建的,而singleInstance模式的活动则会新建一个栈并且该栈中只有他自己一个活动。说句实话,我个人觉得这种模式其实使用得蛮少的,一般用在某个活动和主程序的关联很小的场景,比如说打电话时候出来的电话界面。我们可以通过实际使用来看看。
新建一个ActivityThree,把ActivityOne的启动模式改回默认,把ActivityTwo的模式改为singleTask。然后再ActivityTwo中增加一个按钮,点击事件是跳转到ActivityThree。然后我们在所有的ActivityOne、ActivityTwo、ActivityThree中都加入日志打印活动名称和栈的id。

ActivityOne、ActivityTwo、ActivityThree

@Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        Log.d("Activity", "Activity name = " + this.toString() + ", Task id = " + getTaskId());

        ......
    }

AndroidManifest.xml

<activity android:name=".ActivityOne" >
        </activity>
        <activity
            android:name=".ActivityTwo"
            android:launchMode="singleInstance" >
        </activity>
        <activity android:name=".ActivityThree" >
        </activity>

我们运行程序,然后按下面的流程进行点击:MainActivity->ActivityOne->ActivityTwo->ActivityThree,查看日志
图片描述
从日志中我们可以看到,ActivityOne和ActivityThree共用了一个返回栈,而singleInstance模式的ActivityTwo则单独使用了一个返回栈。这个时候我们开始点击回退键,ActivityThree居然直接跳回了ActivityOne,然后才跳回MainActivity,最后才回到ActivityTwo。很神奇是不是?其实仔细想一下也很简单,因为返回键的作用是将栈顶的活动(ActivityThree)移除,那么ActivityOne自然就成了新的栈顶,只有该栈里面所有的活动都被清空了才会显示下面的栈(ActivityTwo所在的栈),最后如果所有栈中的所有活动都被清空了就会退出程序。
当然,这里的例子只是为了讲解需要。实际使用中,
singleInstance模式的活动不能是中间界面!
singleInstance模式的活动不能是中间界面!
singleInstance模式的活动不能是中间界面!
重要的事情说三遍。
至于原因......这么奇葩的回退逻辑你真的能hold住吗?

好啦,到这里我们已经把Activity的启动模式简单地学习了一遍。以后也请大家跟皮卡丘一起继续学习新的知识,为了成为神奇编程大师而努力吧!
图片描述

点击查看更多内容
18人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消