决定把读的每一本书都做一下读书笔记或者感悟,技术的或者非技术的,一方面方便以后复习查阅,另一方面也能记录自己进步的脚印,2016了,大家要继续努力哈!这本是一本Android开发比较进阶的书籍,建议有一定Android开发基础知识后再进行阅读。
正常情况下的生命周期
onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy
当从其他Activity切换到已经存在的Activity时,就会调用
onRestart -> onStart -> onResume
应该避免在onPause和onStop中做耗时操作,因为执行完onPause之后新的Activity才能执行onStop和onResume,耗时操作会拖慢进入下一个Activity的速度。
当Activity从A调用startActivity启动B的时候,生命周期会有重叠的现象,通过源码分析执行顺序是这样的:
Activity | Action |
---|---|
A | onPause |
B | onCreate |
B | onStart |
B | onResume |
A | onStop (当A不可见的情况下) |
如果您必须在第一个 Activity 停止时向数据库写入数据,以便下一个 Activity 能够读取该数据,则应在 onPause() 而不是 onStop() 执行期间向数据库写入数据。尽量避免在onPause里做CPU密集型的任务,会导致进入第二个Activity的速度变慢。
系统的配置发生改变(如屏幕旋转,系统语言改变),当前运行的Activity会重建,所以会相应的执行
onPause -> onStop -> onDestroy
由于是异常情况,所有系统会调用onSaveInstanceState来保存我们需要的状态,只需把需要保存的内容存入Bundle即可,重建完成之后,我们可以通过onCreate或者onRestoreInstanceState的回调参数获取之前保存的数据,官方推荐使用onRestoreInstanceState(一般在onStart之后),因为onCreate中正常情况下的回调参数为空。
除此之外系统会为我们保存Activity的视图结构,例如TextView中的数据,ListView的滚动位置,因为在View中同样有onSaveInstanceState和onRestoreInstanceState这两个方法。Activity会委托Window从顶级视图遍历子视图,执行onSaveInstanceState和onRestoreInstanceState来保存和恢复数据。
我们可以有办法使Activity在不重建的情况下,在AndroidManifest.xml的Activity标签android:configChanges配置选项,常用的有locale、orientation、keyboarHidden ,多个的情况下使用”|” 来连接。更多的配置项可以参考官方文档。配置之后,当我们配置的系统配置发生改变的时候,Activity就不会重建,也就不会执行onSaveInstanceState和onRestoreInstanceState,而是执行onConfigurationChanged, 所以我们可以在这个回调方法里面做相应的操作。
calling startactivity() from outside of an activity context requires the flag_activity_new_task flag
因为非Activity的Context里面并没有保存所谓的任务栈的相关信息,需要加上FLAG_ACTIVITY_NEW_TASK_FLAG的标志位,这时候实际上是以singleTask的模式来启动的。
singleTask 栈内复用模式
栈内单实例,顾名思义就是一个栈里面只能存在一个该实例,而且有clearTop的功能(当栈中存在此元素的时候,会向上清空此Activity上面的所有Activity,也会相应地执行onDestory方法)。
singleInstance 单实例模式
可看作是singleTask的增强版,此种模式的Activity只能单独的位于一个任务栈里面,且只有一个实例。
AndroidManifest.xml中的TaskAffinity标识了一个Activity任务栈的名称,默认是包名,单独使用没有意义,任务栈分为前台任务栈和后台任务栈,任务栈的表现形式为长按菜单键出现的Activity列表。
TaskAffinity主要与singleTask或allowTaskReparenting配合使用
与sigleTask:它是具有该模式的Activity的目前任务栈的名字,待启动的Activity(前提是没有明确知名任务栈不同 配置singleTask 且TaskAffinity不同)会运行在名字和TaskAffiniy相同的任务栈中。
与allowTaskReparenting:当一个应用A启动了应用B的某个Activity后,如果这个Activity的allowTaskReparenting为true,那么当应用B被启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈中。
一个例子:
A,B,C三个Activity,A的启动模式为standard,B和C的为SingleTask,A与B的TaskAffinity不同,B与C的TaskAffinity相同,A启动B,B启动C,此时有两个任务栈,当从C启动A的时候,因为A是Stardard模式,所以系统会创建一个新的实例并添加到启动他的那个Activity任务栈中,所以此时的此时任务栈的情况是A BCA,然后再从A中启动B,SingleTask模式的Activity切换到栈顶会导致它之上的栈内Activity出栈,所以此时的任务栈情况是 A B。
启动模式和TaskAffinity更详细的实例可以参考这篇博文
就是通过给Intent设置标志位,这种方法的优先级高于在AndroidManifest.xml中设置。
第一种方式无法设置FLAG_CLEAR_TOP的效果,第二种方式无法设置SingleInstance:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_EXECLUDE_FROM_RECENTS:不会出现在历史Activity列表里面,等同于在AndroidManifest.xml里设置Activity的这个属性android:excudeFromRecents=”true”
用于过滤隐式的Intent,过滤的内容有action,category,data
data的属性:scheme,host,port,path,pathPattern,pathPrefix
URI结构:
<scheme>://<host>:<port>/[<paht>|<pathPrefix>|<pathPattern>]
<intent-filter>
<data android:mimeType="image/*" />
</intent-filter>
匹配规则为所有图片类型,虽然没有指定URI,但是有默认值content 、file
intent.setDataAndType(Uri.parse(“file://abc”),”image/png”);
另外,如果Intent要指定完整的Intent的时候,不能单独调用setData或者setType ,查看源码可以发现这两个方法都会互相清空data的某些属性。
如果我们匹配不了隐式Intent,那么调用startActivity的时候就会报错,我们可以使用PackageManager或者Intent中的的resolveActivity(Intent intent,int flag)方法,匹配最佳的Intent,如果匹配不了就会返回null
flags:The most important is MATCH_DEFAULT_ONLY, to limit the resolution to only those activities that support the CATEGORY_DEFAULT.
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />