十步杀一人、Activity前世今生

先说一下取这个名字的意义,十步杀一人,近来临近找实习,而Android岗位市场渐渐饱和,对于应聘人的要求也就越来越高,筛选的条件也越来越高。而正是一些基础的问题会把很多人筛选掉,十步杀一人的不是那些看似炫酷的东西,而是这些我们平时容易忽视的原理。
笔者不才,只是浏览过源码,打算今天开始复习一下这些知识,不能被杀啊。。
今天给大家总结一下Activity的相关知识,会涉及到一些源码相关的知识,Activity并不像你想象的那么简单。我会尽可能的详细,也是一个帮自己梳理的过程。
这里写图片描述

今生

一般情况下一个Activity的正常生命周期是
1. onCreate
2. onStart
3. onResume
4. onPause
5. onStop
6. onDestroy
从整个生命周期来说:onCreate和onDestroy、onStart和onStop、onResume和onPause是配对的。但是我在看完它们各自的功能之后,发现onStart和onResume、onPause和onStop的功能描述类似,事实上这两对表示着不同的回调意义:onStart和onStop是从Activity是否可见来看的,而onPause和onResume是从是否位于前台来看的。
可见生命周期
一个Activity可见生命周期,存在于onStart()和onStop()调用之间。在此期间,用户可以看到屏幕上的activity并与之交互。当一个其他的Activity启动,并且这个Activity完全不可见的时候,onStop()方法就会被调用。在这两个方法,你可以保持该Activity需要展示给用户的资源。例如,您可以在onStart()方法里注册一个BroadcastReceiver来监控你的UI的变化,并在onStop()方法里注销它。在整个生命周期的活动中,系统可能会调用onStart()和onStop()多次,因为活动之间交替进行隐藏或显示给用户。
前台生命周期
一个Activity前台生命周期,存在于onResume()和onPause()调用之间。在这段时间里,这个Activity在其他所有Activity的前面,拥有用户输入焦点。一个Activity可以经常在前台状态发生转换—比如,当设备休眠或者弹出了个对话框。因为经常会发生转换,所以在这两个方法之间的代码应该是轻量级的,防止导致其他转换变慢使得用户需要等待。
可以写一个简单的demo证明一下

@Override
    protected void onStart(){
        LogUtil.log(TAG,"onStart");
        super.onStart();
    }
    @Override
    protected void onResume(){
        LogUtil.log(TAG,"onResume");
        super.onResume();
    }
    @Override
    protected void onPause(){
        LogUtil.log(TAG,"onPause");
        super.onPause();
    }
    @Override
    protected void onStop(){
        LogUtil.log(TAG,"onStop");
        super.onStop();
    }
    @Override
    protected void onRestart(){
        LogUtil.log(TAG,"onRestart");
        super.onRestart();
    }
    @Override
    protected void onDestroy(){
        LogUtil.log(TAG,"onDestroy");
        super.onDestroy();
    }

通过验证后会发现下面几点:

  • 第一次启动,create->start->resume
  • home键返回桌面,pause->stop。(此时还会回调onSavedInstaceState)
  • 回到原Activity,restart->start->resume
  • 按下back返回,pause->stop->destroy
  • 锁屏,pause->stop(此时还会回调onSavedInstaceState)
    这里既然提到了savedInstanceState也就顺便讲一下,这个想要发挥作用是和RestoreInstanceState配合使用的,望文生义。savedInstanceState一般是在activity被销毁的时候回调的,但是有些特殊的是,正常销毁比如back返回是不会触发的,只有该activity被销毁且有机会重新显示的情况才会去调用比如旋转屏幕导致的activity销毁重建。(home键回到桌面也会调用)。
    当然如果我们不想在这些情况下重新启动activity,比如旋转屏幕的时候也是可疑的。这里就要用到configChanges了。
android:configChanges="orientation|screenSize"

在不想重新创建的activity下添加configchanges属性就可以了。
在以前的版本中只要在AndroidManifest.xml文件中对activity指定android:configChanges=”orientation”属性,转屏的时候就会不再重新调用OnCreate()函数,而是调用onConfigurationChanged()。
但是在自从android3.2以后,再这样设置的话,会发现转屏后仍然会调用OnCreate(),而不是onConfigurationChanged();跟踪framework层代码,就会发现问题所在,是由于google在android3.2中添加了screensize改变的通知,在转屏的时候,不仅是orientation发生了改变,screensize同样也发生了改变。

谈完了Activity的今生,就来谈谈他的前世,说说他的启动模式

Activity的四种启动模式如下:
standard、singleTop、singleTask、singleInstance :
假设本来的任务栈为ABC

standard-默认模式

这个模式是默认的启动模式,即标准模式,在不指定启动模式的前提下,系统默认使用该模式启动Activity,每次启动一个Activity都会重写创建一个新的实例,不管这个实例存不存在,这种模式下,谁启动了该模式的Activity,该Activity就属于启动它的Activity的任务栈中。这个Activity它的onCreate(),onStart(),onResume()方法都会被调用。启动D,则任务栈为ABCD。

singleTop-栈顶复用模式

这个模式下,如果新的activity已经位于栈顶,那么这个Activity不会被重写创建,同时它的onNewIntent方法会被调用,通过此方法的参数我们可以去除当前请求的信息。如果栈顶不存在该Activity的实例,则情况与standard模式相同。需要注意的是这个Activity它的onCreate(),onStart()方法不会被调用,因为它并没有发生改变。启动D则为ABCD,再启动D还是ABCD。

singleTask-栈内复用模式

这个模式十分复杂,有各式各样的组合。在这个模式下,如果栈中存在这个Activity的实例就会复用这个Activity,不管它是否位于栈顶,复用时,会将它上面的Activity全部出栈,并且会回调该实例的onNewIntent方法。其实这个过程还存在一个任务栈的匹配,因为这个模式启动时,会在自己需要的任务栈中寻找实例,这个任务栈的名字就是通过taskAffinity属性指定。如果这个任务栈不存在,则会创建这个任务栈。启动D则为ABCD,再启动D还是ABCD,再启动B,则为AB,默认具有clearTop效果。 可以和TaskAffinity配合使用,这个参数标志了Activity任务栈的名字。

singleInstance-全局唯一模式(单实例模式)

该模式具备singleTask模式的所有特性外,与它的区别就是,这种模式下的Activity会单独占用一个Task栈,具有全局唯一性,即整个系统中就这么一个实例,由于栈内复用的特性,后续的请求均不会创建新的Activity实例,除非这个特殊的任务栈被销毁了。以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。

接下来再来谈谈标志位吧,也就是Flags。
Flag有很多,不是一次就能说完的,这里就说几个比较常用的吧。
FLAG_ACTIVITY_New_TASK

这个标记位的作用是为Activity制定“singleTask”启动模式,
效果和在XML中指定相同。

FLAG_ACTIVITY_SINGLE_TOP

这个标记位的作用是为Activity制定“singleTop”启动模式,
效果和在XML中指定相同。

FLAG_ACTIVITY_CLEAR_TOP

具有此标记位的Activity,当它启动时,在同一个任务栈的位于它上面的Activity都要出栈。
SingleTask默认有这个效果。

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具有这个标记的Activity不会出现在历史Activity的列表中。
等同于在XML中指定android:excludeFromRecents="true"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值