之前断断续续地学了一些 Android 开发基础,也写过几个简单的 app,但都是特别简单的那种,还有很多知识学完了没有用过,现在已经忘得差不多了。最近找到一本书叫 Android 开发艺术探索(作者叫任玉刚,据说是百度的大牛),2015 年出版的,看完第一章后感觉不错,很适合我这种有点基础的人看,于是决定写个读书笔记,记录自己从书中学习到的知识。
第一章
本章主要介绍了 Activity 相关的一些内容。
1.1 Activity 的生命周期
正常情况下 Activity 的生命周期如下:
// 1.表示 Activity 正在被创建
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// 2.表示 Activity 正在重新启动,当用户切换已经打开过的 Activity 时才会调用这个方法
@Override
protected void onRestart() {
super.onRestart();
}
// 3.表示 Activity 正在被启动
@Override
protected void onStart() {
super.onStart();
}
// 4.表示 Activity 已经可见
@Override
protected void onResume() {
super.onResume();
}
// 5.表示 Activity 正在暂停
@Override
protected void onPause() {
super.onPause();
}
// 6.表示 Activity 正在停止
@Override
protected void onStop() {
super.onStop();
}
// 7.表示 Activity 正在销毁
@Override
protected void onDestroy() {
super.onDestroy();
}
在某些特殊情况下,Activity 的生命周期可能会发生变化,比如屏幕旋转、内存不足等等,此时 Activity 会被销毁并重新创建,这种情况下会多出两个方法:
// 在 onStop() 方法之前被调用
// 用来保存相关数据
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("test", 123);
}
// 在 onStart() 方法后被调用
// 用来恢复数据,也可以在 onCreate() 方法中恢复,但要判断 savedInstanceState 是否为 null,这里就不需要
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int value = savedInstanceState.getInt("test");
}
如果我们不想系统重新创建 Activity,可以在 AndroidManifest.xml 中为 Activity 配置 configChanges 属性,此属性可以指定多个值:
<activity
android:name=".MainActivity"
android:configChanges="orientation|locale|keyboard|keyboardHidden|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
常用的就这么几个,分别表示屏幕旋转、本地设置改变(如切换语言)、键盘改变(如外接键盘)、键盘可访问性改变(显示或隐藏键盘)、屏幕尺寸改变(通常是因为屏幕旋转)。
同时,如果指定了 configChanges 属性,当相关事件发生时,系统会调用 Activity 的如下生命周期方法:
// 表示配置改变,可以根据需要做一些特殊处理
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d("TEST", "onConfigurationChanged: " + newConfig.orientation);
}
1.2 Activity 的启动模式
Android 系统有一个 Activity 任务栈的概念,栈是一种后进先出的数据结构,那么任务栈中存放的 Activity 自然也是后进先出的。任务栈是 Android 系统管理 Activity 的方式,至于它的工作原理,这里暂时不做说明,我们主要关注的是 Activity 的启动模式。
Activity 有四种启动模式,分别为:
standard:标准模式,也是系统默认的启动模式,每次启动 Activity 都会创建一个实例,并执行相应的生命周期方法,每个 Activity 也都会被放入任务栈中;
singleTop:栈顶复用模式,如果要启动的 Activity 已经位于栈顶,则复用它,此时就不会调用 onCreate() 和 onStart() 方法,取而代之的是调用 onNewIntent() 方法;
singleTask:栈内复用模式,如果要启动的 Activity 在栈中存在,则复用它,生命周期方法同上,但此时系统会清空在任务栈中此 Activity 上面的所有其他 Activity(重点,拿小本本记下来);
singleInstance:单一实例模式,此种情况下,系统会为 Activity 创建一个单独的、独享的任务栈,如果要启动的 Activity 已经存在,则复用它,生命周期方法同上。
说了这么多,那么如何为 Activity 指定启动模式呢?
作者说了,有两种方法,第一种方法是在 AndroidManifest.xml 中配置:
<activity
android:name=".MainActivity"
android:configChanges="orientation|locale|keyboard|keyboardHidden|screenSize"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
第二种方法是通过代码指定:
private void testLaunchMode()
{
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
两种方法都可以指定 Activity 的启动模式,不过第一种方法不能设置 FLAG_ACTIVITY_CLEAR_TOP 标识,第二种方法不能指定 singleInstance 模式,但第二种方式的优先级要高于第一种,实际使用中应该根据需要灵活选择。
上面的代码中提到了 FLAG_ACTIVITY_SINGLE_TOP 和 FLAG_ACTIVITY_CLEAR_TOP,这是 Android 系统预定义的两个常量,是 Activity 的 Flags。系统预定义了很多这样的标识位常量,下面介绍几个常用的标识位:
FLAG_ACTIVITY_NEW_TASK:为 Activity 指定 singleTask 模式,效果和在 AndroidManifest.xml 中指定该模式相同;
FLAG_ACTIVITY_SINGLE_TOP:为 Activity 指定 singleTop 模式,除此之外同上;
FLAG_ACTIVITY_CLEAR_TOP:启动具有此标识位的 Activity,系统会清除与此 Activity 在同一栈中,且在其上面的所有 Activity,通常与 FLAG_ACTIVITY_NEW_TASK 配合使用;
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:表示要启动的 Activity 不在系统的最近任务列表中显示,效果同在 AndroidManifest.xml 中指定 android:excludeFromRecents="true"。
1.3 节主要讲的是 IntentFilter 的匹配规则,内容也不少,下次再写吧。