android开发艺术探索 笔记(一)

第一章Activity的启动与生命周期

正常情况下的启动状态
onCreate加载布局,初始化数据
onStart界面可视化,但尚在后台,不可交互。
onRestart从不可见(onStop)到可见(onStart)需要经过onRestart
onResume从后台到前台,Activity变得可以交互。
onPause一般onPause后紧接着onStop,所以不推荐将耗时的操作放在这里。
×当新的Activity为透明时,原先Activity还是可视的,因而不会执行onStop
onStop从不可互动到不可视,如点击home键回到桌面,这是Activity一般还没有被销毁,等待着onRestart->onStart->onResume重新恢复状态
onDestroy销毁Activity,并进行一些回收工作,如关闭数据库等。
一张应该出现过很多遍的图

基于书上说的屏幕的点亮熄灭以及手指的触摸,我个人试了一下

界面一切·从简,就是默认emptyActivity的界面
每个方法写都写一个Log.d("ActivityLife","onXXXX");//XXXX视方法而定

Activity刚启动时: onCreate->onStart->onResume


启动时

点击返回键,关闭程序时:onPause->onStop->onDestroy


退出

点击home键:onPause->onStop
后台

从后台唤醒:onRestart->onStart->onResume


唤醒

一直到这里,都和我们在前面的理论是一样的。
锁屏时,其实和挂到后台是一样的
锁屏

当唤醒屏幕时,如果有密码的话,唤醒之后是要输入密码,这个时候Activity的界面依旧不可见,因此不会调用以上的任何方法,只有解锁后,Activity重新可见时,又会执行之前从后台唤醒相同的步骤
唤醒
从Activity1启动Activity2,会先执行Activity1的onPause,然后创建Activity2(onCreate->onStart->onResume)再执行Activity1的onStop.
一些小细节
关于生命周期的重点在于onStart、onStop控制的是Activity是否可见(在后台),onResume、onPause控制的是Activity是否在前台可供操作。
异常情况下的生命周期

而onSaveInstanceState是系统自行销毁Activity时对数据的保存。重新打开时调用onRestoreInstanceState恢复数据。即异常情况下销毁Activity时,会调用这两个方法恢复数据。而横竖屏就属于这种异常情况。


横竖屏
  • 这里我们可以发现,onSaveInstanceState是在onStop前执行的,而onRestoreInstanceState是在onStart后执行的。
  • 当Activity异常情况下的情况下需要重新创建时,系统会默认我们保存当前Activity的视图结果,并在Activity重启后为我们恢复这些数据,比如文本框用户输入的数据,ListView的滚动位置等
  • 关于保存和恢复View的层次结构,系统的工作流程:首先Activity会调用onSaveInstanceState去保存数据,然后Activity会委托Window去保存数据,接着Window会委托它上面的顶级容器去保存数据,顶层容器一般是DecorView(ViewGroup);最后顶层容器再去一一通知它的子元素保存数据,这样整个数据的保存过程就完成了。
    ×这里还要注意一下,onSaveInstanceState还有一个两个参数的方法,是不会在异常状态中调用的。
资源不足导致的Activity被销毁
Activity的优先级
  • 正在和用户交互的Activity优先级最高: onResume
  • 可见但非前台的Activity优先级次之:onPause
  • 后台Activity优先级最低:onStop
    当系统内存不足时会杀死目标Activity的进程,再用onSaveInstanceState和onRestoreInstanceState进行恢复。
    如果一个进程在后台没有四大组件在运行,很容易被系统回收,因此可以在后台放入一个service提高优先级。
configChanges

当系统配置发生改变时,Activity会重新创建,如果在Activity指定configChanges属性,Activity就会执行configChanges的属性,而不用重新创建了。
如横竖屏切换:

manifests中配置
android:configChanges = "orientation"
//多个属性用|
@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.d("ActivityLife","onConfigChanged:"+newConfig.orientation);
    }

Activity创建后,从竖屏到横屏再到竖屏的过程中


没用调用onSaveInstanceState和onRestoreInstanceState方法,也没有重新创建Activity
configChanges的一些属性

常用的是locale、orientation和keyboardHidden
×android4.0以上orientation要注意配置screensize,不然还是会调用onCreate
使用configChanges:orientation时,就不会使用oSaveInstanceState和onRestoreInstanceState来恢复数据了,因为都没有销毁。。。

Activity的启动模式
Activity的LaunchMode

任务栈是一个“后进先出”的栈结构,每次finish()处于前台的Activity就会出栈,直到栈为空为止,当栈中无任何Activity的时候,系统就会回收这个任务栈。

  • standard
    默认的模式,每次启动都会创建一个新的Activity到任务栈中。Activity A启动Activity B会让B进入A所在的任务栈中,就是这种特性导致,ApplicationContext没有任务栈,context启动standard的Activity时会发生错误。这时候需要在Intent中加入FLAG_ACTIVITY_NEW_TASK,这时实际上是以singleTask启动的。
    Actvity1启动Activity1



    销毁上面的Activity1


  • singleTop
    栈顶复用模式,若该Activity处于任务栈的栈顶,那么就不会重新创建该Activity。
    (Activity1为singleTop)
    Activity1启动Acticity1时:



    只调用onPause->onNewIntent->onResume
    销毁时:



    只有单个Activity在栈中
    Activity1启动Activity2再启动Activity1时:
    捕获.PNG

    会重新创建Activity1
    销毁时:
    销毁最上面的Activity1

    销毁Activity2
  • singleTask
    栈内复用模式。这种模式下,Activity在一个栈中存在,那么多次启动该Activity都不会重新创建实例,和sinleTop一样,系统会回调其onNewIntent。如果启动的Activity没有所需要的任务栈,就会先创建任务栈再创建Activity。singleTask默认具有clearTop的效果,具有该模式的Activity会让其之上的Activity全部出栈。
    Activity1处于栈顶时启动Activity1


    这里和singleTop是一样的

    Activity1启动Activity2再启动Activity1



    注意这里,由于不会生成新的Activity1,所以调用onRestart->onStart->onResume,而Activity2会直接被销毁。
  • singleInstance
    单实例模式。这是一种加强的singleTask模式,除了具备singleTask的特性之外,具有该模式的Activity只能单独位于一个任务栈中;比如Activity A是singleInstance模式的,当A启动后,系统会为它创建一个新的任务栈,后续的启动均不会创建新的Activity,除非这个任务栈被系统销毁了。
    这里可以这么理解,singleInstance会创建一个新的任务栈,这个任务栈中只有自己一个实例,启动其他Activity会重新创建一个任务栈,供其他的Activity使用。此时Activity的销毁顺序与创建顺序无关,和任务栈内Activity的顺序有关。当销毁时处在singleInstance所在的任务栈,那么该任务栈会被销毁,跳转到另一个任务栈的栈顶,再根据这个任务栈Activity的次序进行销毁。而当销毁工作处于另一个任务栈时,会先选择清空这个任务栈的所有实例,在跳转到唯一的singleInstance所在任务栈的实例。
关于四个启动模式的流程图->http://www.jianshu.com/p/7a11ff292423
LaunchMode的使用方法
在manifests中activity下
android:launchMode="singleInstance"
或者在intent中addFlag
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
这里第二种方法的优先级更高,而区别在于第一种方法不能使用FLAG_ACTIVITY_CLEAR_TOP,第二种不能设置singleInstance。

这里书中还提到了TaskAffinity和AllowTaskReparenting两个属性
TaskAffinity标识了Activity所需的任务栈的名字
AllowTaskReparenting="true"时,例子如下:
A启动B的ActivityC,ActivityC刚好是这个属性,此时C会在A的任务栈中。当按下home键再打开应用B时,会直接打开ActivityC,而不是默认的首页面。此时ActivityC会从A的任务栈转移到B的任务栈

adb shell dumpsys activity命令可以详细的了解当前任务栈情况
Activity的Flags
  • FLAG_ACTIVITY_NEW_TASK
    即singleTask
  • FLAG_ACTIVITY_SINGLE_TOP
    即singleTop
  • FLAG_ACTIVITY_CLEAR_TOP
    有此标记的Activity在启动时,在其上的所有Activity都将被销毁,一般会和singleTask一同出现,当被启动的Activity是standard模式时,该Activity及以上的Activity都会出栈,再重新创建新的Activity
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
有该标识的Activity将不会出现在历史Activity列表中,xml中等同于:
android:exculdeFromRecents="true"```
#####IntentFliter的匹配规则
- 显式调用
明确表示启动对象的包名类名
- 隐式调用
需要Intent匹配IntentFliter所设置的过滤信息
- 一个Activity可以有多个IntentFliter,一个IntentFliter可以有多个action、category或是data。
- 其中Intent需要同时匹配一个IntentFliter中的三种(action、category和data)信息。
- 一个Activity中只要匹配一个IntentFliter就可以了。

- #####Action
action系统有预定义的,当然我们也能自己定义,其中intent中action必须与IntentFliter中一个action匹配。(没有就默认不匹配)还有一点就是action区分大小写
- #####Category
category系统有预定义的,当然我们也能自己定义。category与action不同的是:intent中没有category是默认匹配成功的。如果intent定义了category,则要求intent中所有的category都是intentFliter的category中的一个。
- #####data
data的匹配模式与action类似,都需要至少一个匹配。

data的语法
<data android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
android:mimeType="string"/>

data由两部分组成,URI和mimeType。URI指定类似于路径的状态,mimeType指定媒体数据
- URI的结构有mimeType前面的scheme、host、port、path、pathPattern、pathPrefix组成。

<scheme>://<host>:<port>/{<path>|<pathPrefix>|<pathPattern>}
对应:
content://com.example.project:200/folder/subfolder/etc
http://www.baidu.com:80/search/info

- scheme:URI的模式,如http、file、content等,若没有指定scheme,URI是无效的。
- Host:URIde主机名,URI中不能为空
- Port:URI的端口号,scheme和host都指定了才有意义。
- Path、pathPattern、pathPrefix:三个参数表述路径信息。

Path指定完整路径
pathPattern也指定完整路径,但是可以使用通配符"",""表示0或多个字符。由于正则表达式的规范,真实字符串中""要用"\"表示,""要用"\\"表示
pathPrefix表示路径的前缀信息

当没有指定URI时,URI默认为content和file。
Intent添加data信息:

如果要指定完整data信息,需要setDataAndType
intent.setDataAndType(Uri.parse("file://abc"),"image/png");
使用setData和setType会彼此擦除对方的值

这里data比action特殊的还有一点,就是:

<intent-filter...>
<data android:scheme="file" android:host="www.baidu.com"/>
...
</intent-filter>

<intent-filter...>
<data android:scheme="file"/>
<data android:host="www.baidu.com"/>
...
</intent-filter>

上面的两种方法是一样的。
当我们隐式启动一个Activity的时候,可以做一下判断,看是否能匹配到我们的隐式Intent,如果不做判断没找到对应的Activity系统就会抛出android.content.ActivityNotFoundException异常。
采用PackageManager的resolveActivity方法或者Intent的resolveActivity方法,如果找不到匹配的Activity就会返回null,我们通过判断返回值就可以规避上述错误了。
######接收隐式意图的Activity必须有<category android:name="android.intent.category.DEFAULT"/>,这个category的作用在于上述两个方法只要不返回null,就能启动Activity。
######有一类action和category的共同作用是标明这是一个入口Activity,并且会出现在系统的应用列表中,少一个都没有任何意义,也不会出现在系统的应用列表中。

<action android:name="android.intent.action.MAIN" />
//最先启动的activity
<category android:name="android.intent.category.LAUNCHER" />
//桌面的图标,显示在程序列表中


####知识点总结的比较全,难听点就是笔记太啰嗦了吧,感觉都有点重要,整章的内容都快要都写进来了。
####这一章的内容不是特别多,但我还是写的有些杂乱,或许写多了,就好了吧
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容