诠释Android中Activity启动模式

诠释AndroidActivity启动模式

前言:

在我前一篇文章中曾介绍了Activity的生命周期(地址点击),以及ActivityActivity任务栈的介绍;在默认模式下每一个被创建的Activity都会生成一个实例并加按照生成顺序加入到Activity的任务栈中,除非主动调用了finish()方法该实例则会直接从任务栈中移除,或者按下Back按键主动的从当前任务栈顶的中Activity弹出移除。为了对Activity任务栈中进行优化Google允许开发者对App中的Activity的启动模式进行修改已达到最优化的启动方式。

四大模式的配置方法以及含义介绍

四大模式的启动方式都可以在Android中的AndroidMainfest.xml文件中进行配置,在这个配置文件中每一个Activity配置中配置例如:

<activity

android:launchMode="开发中需求的启动模式"

></activity>

四大模式主要有(以下图解)


代码示例:

首先创建一个MainActivity类:用于Log打印每一次Activity创建的或者调用Activity的相应信息,其次让每一个用于测试的详解Activity启动模式的Activity继承于MainActivity

MainActivity的代码如下:

public class MainActivity extends Activity{

   
@Override
    protected void
onCreate(BundlesavedInstanceState) {
       
super.onCreate(savedInstanceState);
        setContentView(
R.layout.activity_main);
        ShowMessagle("OnCreate
——Activity创建");
    }

   
@Override
    protected void
onDestroy() {
       
super.onDestroy();
        ShowMessagle("onDestroy");
    }

   
@Override
    public void
finish() {
       
super.finish();
        ShowMessagle("finish");
    }

   
@Override
    protected void
onNewIntent(Intentintent) {
       
super.onNewIntent(intent);
        ShowMessagle("onNewIntent");
    }

   
protected voidShowMessagle(StringvalueName) {
       
Log.i("易庞宙", valueName);
       
Log.i(
                "
易庞宙",
                "ClassName
" + getClass().getSimpleName()+ "" +
                        "GetThisTaskId:"+ getTaskId() + "
" +
                        "HasCode:"+ hashCode()
        );
       
try {
           
ActivityInfo info=this.getPackageManager().getActivityInfo(getComponentName(),PackageManager.GET_META_DATA);
           
/*Log.i("易庞宙","taskAffinity:"+info.taskAffinity);*/
       
} catch(Exceptione) {
           
Log.i("易庞宙", e.getMessage());
        }
    }

   
protected voidstratActivity(Classc) {
        startActivity(
newIntent(this,c));
    }
}

 

其余Activity如下其命名很好的代表了各个所代表的启动模式如下图:

Standrand默认模式:

先回顾下默认模式的含义:在一个Activity栈中每一个需要跳转的Activity都会被创建成一个实例并加入同一个Activity栈中。即每一个Activity就都会变成一个实例占用栈内存除非从栈中移除;接下来看看我的演示步骤吧:

首先不难看出第一Activity已经被创建了这时我们点击默认模式又会触发Log打印

然后在点击跳回默认页面:

这时不难看出每一个Activity都是以一个实例并加载进入到同一个栈中并且他们的HasCode值都是不一样说明他们每一个都是一个实例,此时我按下回退键呢回到第一次跳转的页面呢?看接下来的Log打印会很清楚的告诉你发生了什么。

这时很清楚的看到了通过了先调用了finish这个方法通知栈移除这个实例然后在调用onDestroy这个方法销毁这个实例此时这个实例是完全从Activity栈中销毁也就是从栈中移除该实例减少栈中内存。

SingTask模式:

首先我们先回顾一下这个模式的含义吧:Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。如果是在别的应用程序中启动它,则会新建一个task,并在该task中启动这个ActivitysingleTask允许别的Activity与其在一个task中共存,也就是说,如果我在这个singleTask的实例中再打开新的Activity,这个新的Activity还是会在singleTask的实例的task中。

首先重新启动App再次从默认界面启动然后启动Task模式下的第一个Activity,然后在启动一次Task模式下的另外一个Activity,然后重启该模式下第一次被启动的Activity,看看Log打印会告诉些什么信息给我们。

不难看出:他们统一加入了默认模式下的一个Activity栈队列中,启动顺序由:StandrandModeSingTaskMode再到SingTaskMode2最终再一次到达SingTaskMode的这样一个顺序中。在进行最后一次跳转中SingTaskMode2处于栈顶然而却被SingTaskMode弹出栈顶而且并没有重新创建SingTaskMode这个Activity而是走了onNewIntent这个方法然后在调用了SingTaskMode2中的onDestroy这个方法销毁Activity并从ActivityTask中移除了(通俗来说就是被前者SingTaskMode上位干掉了)

SingTop模式:

首先我们回顾一下SingTop的含义:如果Activity在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法接下来我们看看:默认模式下的起始界面到Top模式下第一个Activity然后在启动其本身之后启动Top模式下第二个Activity然后启动其本身然后在启动回Top模式下第一个Activity看看log会告诉我们什么?

首先StandradMode2跳转到Top模式下第一个SingleTopMode然后在跳转到SingTopMode然后跳转到下一个SingleTopMode2然后再跳到SingleTopMode2再到SingTopMode中可以看出第一次Top模式下没有该实例所以SingTopMode创建了然后在复用自己当跳转到SingTopMode2SingTopMode2创建了之后复用,之后Mode2跳到Mode中时SingTopMode又重新创建了所以可以总结为三点:

1当前栈中已有该Activity的实例并且该实例位于栈顶时,不会新建实例,而是复用栈顶的实例,并且会将Intent对象传入,回调onNewIntent方法

2当前栈中已有该Activity的实例但是该实例不在栈顶时,其行为和standard启动模式一样,依然会创建一个新的实例

3当前栈中不存在该Activity的实例时,其行为同standard启动模式

StandradSingleTop的区别: standardsingleTop启动模式都是在原任务栈中新建Activity实例,不会启动新的Task,即使你指定了taskAffinity属性。

taskAffinity属性解释:可以简单的理解为任务相关性。

这个参数标识了一个Activity所需任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名

我们可以单独指定每一个ActivitytaskAffinity属性覆盖默认值

一个任务的affinity决定于这个任务的根activity(root activity)的taskAffinity;在概念上,具有相同的affinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务;为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task很重要的一点taskAffinity属性不对standard和singleTop模式有任何影响,即时你指定了该属性为其他不同的值,这两种启动模式下不会创建新的task(如果不指定即默认值,即包名)

SingleInstance模式

首先老规矩了我们也回顾下什么含义(文章较长每次回顾下会对读者阅读的记忆会加深):该模式具备singleTask模式的所有特性外,与它的区别就是,这种模式下的Activity会单独占用一个Task栈,具有全局唯一性,即整个系统中就这么一个实例,由于栈内复用的特性,后续的请求均不会创建新的Activity实例,除非这个特殊的任务栈被销毁了。以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。

先启动默认模式下的Activity其次分别跳转SingleInstance下第一个Activity然后是第二个Activity然后默认界面然后第一个到第二个看看Log会告诉我什么?

log中不难看出只有StandrandMode2创建了两次实例并属于同一个栈,而单列模式下两个Activity分别属于不同的栈,而且这些单列栈只有唯一一个单列模式的Activity存在于栈中,只要该Activity创建为实体没有销毁出栈,以后反复回去调用时并不需要重新创建。因此可以认为该模式下的Activity对整个App具有全局唯一性。

四大模式总结:默认模式使用需牢记及时使用调用finish方法移除出栈保证栈内存的合理使用;Task模式:对一些可反复使用的Activity可设置为SingleTask减少实例的创建可需注意调用后在它之上的栈元素会全部弹出也就是销毁,此时更该考虑哪些销毁的Activity是否需要保存其里面一些对数据操作的对象是否及时释放或者是及时保存数据避免回调使用时数据有可能会没有保存好导致程序出现不可预现象;Top模式与默认模式虽然多了一点好处是:栈顶可复用减少实例的创建可是必须得把握好使用的方式避免会出现冗余的现状;SingleInstance模式下:最好使用经常要回调使用的Activity设置此模式,可是全局唯一性会对App内存有消耗较大的情况出现,应注意需考虑好要此Activity的启动模式应该是那些Activity避免过多Activity采用此模式,从而减少对一些实例对象的创建达到减少内存消耗的规划,如若过多使用而会占用App没有申请大内存的情况下时候或者手机内存不足时则会导致App可能会出现卡顿式的情况,开发人员不止要考虑App的功能是否实现更要考虑App运行的流畅性让用户对App流畅度的评价是极为优秀的评价。


  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值