1.Activity的生命周期
生命周期这个事情,是android工程师最基础的知识,所以今天要讲的是一些不一样的东西。
1.1 OnStart,OnResume,OnPause,OnStop 他们的区别是什么?
OnStart & OnStop, 这一对发生的时候,页面已经显示,但是处于backgroud的状态,所以用户无法看到。
OnResume & OnPause,发生在用户可以看到页面,也就是从后台到前台。
OnPause->OnStop,如果下个页面是透明的,OnStop不会被呼叫。
1.2 OnCreate 怎么区分第一次加载还是Activity重启后,再次加载?
但activity被回收以后,会在onSaveInstance的回调里面写入bundle的值,
所以被回收的activity,在页面重启以后,会在onCreate里面把bundle的值带回来。
通过demo可以证实1)Activity会创建新的实例 2)局部变量需要保存才能恢复,但static的变量
是保存在进程里面,所以不需要保存,一直存在。
里有一个新问题,app的进程有没有被杀掉?也就是applicaiton是否也存在这种case。
当系统的内存不足的时候,按照优先级排序,app的可能会被系统回收,然后再次启动的时候,
系统会创建一个新application,然后启动刚才的activity,这样用户就会感觉app没有被杀掉一样,
crash时候,有些app会重启,也是一样的道理。
1.3 setContentView 做了那些操作
1)AppConpantActivity的code:setConentView会由ApplicationDelegate作为代理进行管理
然后,会在ApplicationDelegateimplV9的版本中实现setConentView的方法。这个方法有2个核心View
subDecor & mDecorContentView, 这2个就是一般来说activity布局的外壳,或者说window里面包含的内容。
subDecor >> titlebar+mDecortentView >> customLayout
2)Activity,普通的activity是最早的一个实现,其实1)的applicationDeleage的方式就是参考老的实现(普通activity的方式)
phonewindow >> mDecor>>titlebar+mContentParentView >>customlayout
1.4 OnPause,onStop,OnDestory的资源回收的动作,有什么注意的地方?
OnPause 执行后,B页面的OnCreate->OnStart->OnResume才会被执行,然后是A页面的OnStop
所以这里在OnPause里面执行了很多耗时的操作是为导致下个页面加载时间过长。
OnPause:停止动画,sersor等消耗CPU资源的操作。释放camera是合适的地方,应为下个页面可能也会使用这个设备。(同理其他设备类的资源也需要释放)。
broadcastreceiver y而是一个合适的地方,释放监听。
不能做的事情:耗时的操作比如文件读写,以及数据库的保存等。
OnStop:执行一些保存的动作等,比如数据库的操作
OnDestory:最终的资源,内存的释放。主要处理会发生内存泄露的地方。but,这个方法在activity直接被系统kill的时候不会回调。
2.Activity的launchmode & Flags
2.1 基本知识
4大启动模式,也是最基本的知识,。
只有activity可以启动其他的
application 启动activity,由于没有历史栈,需要加flag:FLAG_ACTIVITY_NEW_TASK
这样这个activity会存在一个新task
FLAG_ACTIVITY_NEW_TASK:这个标志同singtask launchmode的效果一样。
FLAG_ACTIVITY_SINGLE_TOP:这个标志同singletop 效果一样。
FLAG_ACTIVITY_CLEAR_TOP: 会把在task 栈上面的activity,出栈。
2.2 为什么有2种启动模式?
2种启动模式是相互弥补的形式。Launchmode:singleInstance是在manifiest里面定义特有的属性,flag无法做到。
Falg的作用,就是在目标activity 的launchmode不明确的情况下(比如隐式启动),我可以给目标Activity一个明确的启动方式,从而控制外部activity的行为。
2.3这2种启动模式各有什么优缺点
Launchmode:固定,结果明确,缺少灵活
Flags:控制非本APP的Activity行为,不好控制
2.4 优先级那个高
Flags优先级高,原因还是start到其他app的activity的时候,我怎么规范这个非本app的activity的行为。或者说flag是通过一种可控的方式,去开启其他app的activity
2.5 startActivities的作用和使用方式
同单个activity行为类似。Intent[3] = {A,B,C}假设是这3个页面的intent。
最终的结果是,会启动Cactivity,but A & B没有被启动。
但是当back返回的时候,B会被onCreate,然后再返回,A会被create
2.6 Launchmode的使用场景
Standard:AlarmClock,页面可以多次使用,每个都是独立的。
SingleTop:书签页面,主要是书签页面可以有多个,但是在返回的时候,不应该看到多个。因为它的内容是一个,但是它也不能是singletask,这样会把browser页面清除掉。
SingleTask:主页面,一般来说就是首页,首页不需要回到历史页面。
SingleInstance:只有单一页面,不如闹钟起来页面。有且只允许存在一个页面
3.intentFilter
我们的代码,在startactivity的时候,要传intent,但是一般我们都是
Intent(Context packageContext, Class<?> cls) 使用这个定义。这个就是我们所谓的显示调用。
intentFilter是用于隐式调用的,显示调用&隐式调用同时存在,将以显示调用为准
intentFilter有三个部分组成:action,category,& data
一个activity可以有几组intentFilter,只要匹配一个,就可以启动activity
但是必须同时瞒住action,category & data的匹配,才能保证activity被启动。
同一个intentFilter可以有几个action,只要满足一个就可以,同理category & data也是。
Action:action的字串,必须完全一致,才能算作匹配。
Category:category可以有多个,但是每一个都必须同 intentFilter的某一个匹配。Category也可以为空,这样系统会默认为我们加上action.intent.category.DEFAULT 这样就要求每个支持隐式调用的activity,都必须有action.intent.category.DEFAULT
Data:data的匹配规则跟action相似。只要匹配一个元素,但是必须使用setdataandType 方法来设定。Setdata & setType这2个方法是互斥的。
当我们在使用隐式启动activity的时候,可以先使用PackageManager的resolveActivity 或者Intent的resolveActivity,在查询的时候,需要加flag:MATCH_DEFAULT_ONLY
还有一个特殊的页面:action = android.intent.action.MAIN category=android.intent.category.LAUNCH缺一不可
1.显示匹配
两种方式,简单来说就是
setClassName(@NonNull Context packageContext,@NonNull String className)
setClassName(@NonNull String packageName, @NonNull String className)
这2个方法其实本质上是一个方法,第一个方法的参数content可以getpackage,所以本质上还是packagename+classname的方式唯一定位activity的注册位置。
这个就是显示调用。
显示调用 > 隐式调用
2. 隐式调用
既然有显示调用,对应隐式调用。使用场景:
Case 1:比如UC浏览器,一般手机厂商都会有默认的浏览器,但是我怎么让用户在点击链接的时候可以选择UC浏览器。这个时候就是intentfilter匹配的时候。
同样这个场景,一个用户装了QQ浏览器,百度浏览器等等,需要让用户自己选择使用那个浏览器。
Case 2:用户需要打开camera,but,camera的应用一般厂商都会做定制,所以activity的名字根本不确定,但是打开camera的服务,一般应用只需要唤起camera activity就可以,这个适合通过action+category的方式更适合。
Intent的6大属性,Component,Action,Data,Category,Extras,Flags
Component:用于显示调用,上节已经说明了
Extras,用于传递参数
Flags,定义启动模式,之前章节也已经讲述。
Action,Data,Category就是我们要讲的IntentFilter
Action:
Action |
描述 |
备注 |
ACTION_MAIN |
launcher使用,一般app不应该有这个action |
TV盒子,沙发桌面 |
ACTION_VIEW |
最常用的action,一般activity使用这个,传递data |
|
ACTION_EDIT |
显示可编辑的数据 |
|
ACTION_PICK |
选择数据 |
|
ACTION_CHOOSER |
显示一个Activity选择器 |
|
ACTION_DIAL |
显示拨号界面(号码放在data里面) |
|
ACITON_CALL |
直接打电话 |
|
ACTION_SEND |
直接发短信 |
|
ACTION_SEARCH |
搜索本地 |
|
ACTION_WEB_SEARCH |
Web搜索 |
上面是基本的Action的内容,基本aciton是和data一起使用
Data:一般数据类型是2种,Uri & mimetype,这2个要同时设置需要调用
注意:若要同时设置 URI 和 MIME 类型,请勿调用 setData() 和 setType(),因为它们会互相抵消彼此的值。请始终使用 setDataAndType() 同时设置 URI 和 MIME 类型。
Uri一般表示数据,尤其表示数据库地址,这个最合适
Mime-type:Content-Type: text/HTML
这Uri 和MIME Type 和套路都是从浏览器的概念里面来的。Why?
Google是搞搜索起家的,所以它骨子里就是要搞web,浏览器等东西,或者说概念才是最符合它的思维方式。
Category:是附件信息,所以一般的类型不需要这个东西(默认default)android.intent.category.DEFAULT