Activity总结,看这个就够了
2016-09-03 12:21
239 查看
Activity 是 Android 开发里最常见也是最常用,占比重最大的一个点,这篇文章给大家总结一些有用的 Activity
学习笔记。
. onCreate()
表示 Activity 正在被创建,这是生命周期的第一个方法,一般在这个方法里做一些初始化的工作。
. onRestart()
表示 Activity 正在重新启动,从可见状态下变为不可见状态,这个方法会被调用,比如用户按 home 键切换到桌面,再切换回来,这个方法就会被调用。
. onStart()
回调这个方法的时候,Activity 已经可见,但是还和用户无法交互,这个方法和 onStop() 方法对应
. onResume()
回调这个方法的时候,Activity 已经可以和用户交互,这个方法和 onPause() 方法对应。
. onPause()
表示 Activity 正在停止,这个方法调用完毕之后,新的 Activity 的 onResume() 方法才会被调用。
所以不建议在这个方法里做耗时的操作,这个方法和 onResume() 方法对应。
. onStop()
表示 Activity 即将停止,同样不建议在这个方法里进行耗时的操作,这个方法和 onStart() 方法对应。
但是需要在 onPause() 和 onStop() 中选择的话,选择 onStop 进行操作,这是因为 onStop() 调用的时候,新的 Activity 已经出现在前台并且可以与用户交互了。
. onDestory()
表示 Activity 即将被销毁,这个方法里可以做一些资源回收和释放的操作,如解除绑定 Service,反注册 BroadCaseReceiver 等。
. onSaveInstanceState()
在系统配置发生改变之后,或者内存吃紧,系统回收 Activity 的时候,Activity 会调用这个方法,以保存当前 Activity 的状态。
从这个方法追踪源码到 PhoneWindow#saveHierarchyState() 方法中,可以看到
Activity 的默认实现是保存界面当前的焦点,以及调用了 View#onSaveInstanceState() 方法 来保存界面上所有
View 的状态。
贴一段 PhoneWindow#saveHierarchyState() 的代码
public BundlesaveHierarchyState() {
// ...
// 当前焦点
ViewfocusedView = mContentParent.findFocus();
if (focusedView != null)
{
if (focusedView.getId() != View.NO_ID) {
outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
} else {
if (false)
{
Log.d(TAG, "couldn't save which view has focus because the focused view "
+ focusedView + " has no id.");
}
}
}
// view 的状态保存
SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();
savePanelState(panelStates);
if (panelStates.size() > 0)
{
outState.putSparseParcelableArray(PANELS_TAG, panelStates);
}
// ActionBar 的状态保存
if (mDecorContentParent != null)
{
SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();
mDecorContentParent.saveToolbarHierarchyState(actionBarStates);
outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);
}
return outState;
}
. onCreate(Bundle savedInstanceState)
Activity 重新创建的时候,也会调用这个方法,正常状态下,savedInstanceState 为空,重新创建的时候,则包含之前保存的数据。
Activity 的默认实现与 onSaveInstanceState() 方法相对应,对之前保存的焦点和调用了
View 的 onRestoreInstanceState() 方法,对 View 的状态进行了恢复。
贴一段 PhoneWindow#onRestoreInstanceState 的代码
public void restoreHierarchyState(BundlesavedInstanceState)
{
// ...
// 恢复当前的焦点
int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID);
if (focusedViewId != View.NO_ID) {
ViewneedsFocus = mContentParent.findViewById(focusedViewId);
if (needsFocus != null)
{
needsFocus.requestFocus();
} else {
Log.w(TAG,
"Previously focused view reported id " + focusedViewId
+ " during save, but can't be found during restore.");
}
}
// 恢复 View 的状态
SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);
if (panelStates != null)
{
restorePanelState(panelStates);
}
// 恢复 ActionBar 的状态
if (mDecorContentParent != null)
{
SparseArray<Parcelable> actionBarStates =
savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
if (actionBarStates != null)
{
doPendingInvalidatePanelMenu();
mDecorContentParent.restoreToolbarHierarchyState(actionBarStates);
} else {
Log.w(TAG, "Missing saved instance states for action bar views! " +
"State will not be restored.");
}
}
}
. onRestoreInstanceState()
在 Activity 重新创建的时候,会回调这个方法,将之前 onSaveInstanceState()方法保存的数据进行恢复,需要恢复数据,这个方法和 onCreate()
选用一个方法即可。
不同之处是如果 onSaveInstanceState() 方法如果被调用,那么代表
Activity 一定被重新创建了,参数中的 savedInstanceState 一定不为空,而在 onCreate() 则需要做出判断。
android.content.res.Configuration 中的许多成员变量,都属于系统配置的 item, 比如屏幕方向,系统语言等。如果不想因为某项内容改变而引起
Activity 重新创建的话,可以在清单文件里指定。
<!-- 不希望 Activity 在屏幕方向改变的时候重新创建 --><activity
android:name=".MainActivity"
android:configChanges="orientation" />
.
singleTask只是让系统判定为“可以单task启动”,而不是直接开启新的task启动,需要加上taskAffinity属性,值不同于当前的taskAffinity(一般默认的taskAffinity的value为包名
taskAffinity属性设置为相同,可以让不同应用的Activity跑在同一个task中。
按下多任务键,就能看到task的数量。
同一个task中,按下返回键起弹栈的作用。
为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task
下图是同一个Application中,存在两个task,按下多任务键的情况
Intent 分为两种,显式 intent 和 隐式的 intent,显式 intent 指定了包名和类名,而隐式 intent 没有。
对于需要接受隐式 intent 的组件,我们需要指定过滤的规则,用 IntentFilter 对象来包裹过滤的信息。
IntentFilter 的过滤信息有 action, category, data
一个过滤规则中可以含有多个 action,只要 intent 中的 action 的任意一个 和过滤规则中的 action
的任意一个 匹配, 即为匹配成功。
一个过滤规则中可以含有多个 category,要求 intent 中的所有 category 和 过滤规则中的 部分/所有
category 匹配, 即为匹配成功。
与 action 类似,如果在过滤规则中定义了 action,那么 Intent 中必须也要有匹配的 data。
data 包含有以下的数据
. mimeType 媒体类型
. URI
. Scheme URI
的模式,这里我理解为协议
. Host 主机名
. Port 端口号
. Path 完整的路径
. PathPattern 使用正则表达式匹配路径
. PathPrefix 路径前缀
如
<intent-filter>
<dataandroid:mimeType="image/*" />
<!-- moreattrs --></intent-filter>
为了匹配这个规则,我们这样子写
intent.serDataAndType(Uri.parse("file:url"), "image/png");
另外, setData() 方法和 setType() 方法是互斥的,设置了
uri 会把 mimeType 清除,反之亦然,要设置完整的 uri 和 mimeType,调用 setDataAndType(Uri data, String type) 方法.
以 activity 为例, PackageManager 提供了以下方法,
这两个方法都返回 能够接收到这个隐式 intent 的 activity 集合或者信息。
其他的组件也有类似的方法。
. queryIntentActivities
/*
* @see #MATCH_DEFAULT_ONLY
*/public abstract List<ResolveInfo>
queryIntentActivities(Intentintent, int flags);
. resolveActivity
/**
* @see #GET_RESOLVED_FILTER
*/public abstract ResolveInforesolveActivity(Intentintent, int flags);
我们看常量 MATCH_DEFAULT_ONLY 的定义:
/**
* Resolution and querying flag: if set, only filters that support the
* {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for
* matching. This is a synonym for including the CATEGORY_DEFAULT in your
* supplied Intent.
*/public static final int MATCH_DEFAULT_ONLY = 0x00010000;
也就是说,需要保证不出错,建议将 flags 参数设置为 MATCH_DEFAULT_ONLY ,
以排除无法接收隐式 intent 的 activity (也就是 category 中不包含 android.intent.category.DEFAULT 的
activity ),这样子,如果这个方法能返回不为空的数据,则 startActivity() 方法一定会调用成功。
文章来自:技术学习小组
学习笔记。
生命周期
正常情况下的生命周期
. onCreate()表示 Activity 正在被创建,这是生命周期的第一个方法,一般在这个方法里做一些初始化的工作。
. onRestart()
表示 Activity 正在重新启动,从可见状态下变为不可见状态,这个方法会被调用,比如用户按 home 键切换到桌面,再切换回来,这个方法就会被调用。
. onStart()
回调这个方法的时候,Activity 已经可见,但是还和用户无法交互,这个方法和 onStop() 方法对应
. onResume()
回调这个方法的时候,Activity 已经可以和用户交互,这个方法和 onPause() 方法对应。
. onPause()
表示 Activity 正在停止,这个方法调用完毕之后,新的 Activity 的 onResume() 方法才会被调用。
所以不建议在这个方法里做耗时的操作,这个方法和 onResume() 方法对应。
. onStop()
表示 Activity 即将停止,同样不建议在这个方法里进行耗时的操作,这个方法和 onStart() 方法对应。
但是需要在 onPause() 和 onStop() 中选择的话,选择 onStop 进行操作,这是因为 onStop() 调用的时候,新的 Activity 已经出现在前台并且可以与用户交互了。
. onDestory()
表示 Activity 即将被销毁,这个方法里可以做一些资源回收和释放的操作,如解除绑定 Service,反注册 BroadCaseReceiver 等。
非正常情况下的生命周期
. onSaveInstanceState()在系统配置发生改变之后,或者内存吃紧,系统回收 Activity 的时候,Activity 会调用这个方法,以保存当前 Activity 的状态。
从这个方法追踪源码到 PhoneWindow#saveHierarchyState() 方法中,可以看到
Activity 的默认实现是保存界面当前的焦点,以及调用了 View#onSaveInstanceState() 方法 来保存界面上所有
View 的状态。
贴一段 PhoneWindow#saveHierarchyState() 的代码
public BundlesaveHierarchyState() {
// ...
// 当前焦点
ViewfocusedView = mContentParent.findFocus();
if (focusedView != null)
{
if (focusedView.getId() != View.NO_ID) {
outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
} else {
if (false)
{
Log.d(TAG, "couldn't save which view has focus because the focused view "
+ focusedView + " has no id.");
}
}
}
// view 的状态保存
SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();
savePanelState(panelStates);
if (panelStates.size() > 0)
{
outState.putSparseParcelableArray(PANELS_TAG, panelStates);
}
// ActionBar 的状态保存
if (mDecorContentParent != null)
{
SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();
mDecorContentParent.saveToolbarHierarchyState(actionBarStates);
outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);
}
return outState;
}
. onCreate(Bundle savedInstanceState)
Activity 重新创建的时候,也会调用这个方法,正常状态下,savedInstanceState 为空,重新创建的时候,则包含之前保存的数据。
Activity 的默认实现与 onSaveInstanceState() 方法相对应,对之前保存的焦点和调用了
View 的 onRestoreInstanceState() 方法,对 View 的状态进行了恢复。
贴一段 PhoneWindow#onRestoreInstanceState 的代码
public void restoreHierarchyState(BundlesavedInstanceState)
{
// ...
// 恢复当前的焦点
int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID);
if (focusedViewId != View.NO_ID) {
ViewneedsFocus = mContentParent.findViewById(focusedViewId);
if (needsFocus != null)
{
needsFocus.requestFocus();
} else {
Log.w(TAG,
"Previously focused view reported id " + focusedViewId
+ " during save, but can't be found during restore.");
}
}
// 恢复 View 的状态
SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);
if (panelStates != null)
{
restorePanelState(panelStates);
}
// 恢复 ActionBar 的状态
if (mDecorContentParent != null)
{
SparseArray<Parcelable> actionBarStates =
savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
if (actionBarStates != null)
{
doPendingInvalidatePanelMenu();
mDecorContentParent.restoreToolbarHierarchyState(actionBarStates);
} else {
Log.w(TAG, "Missing saved instance states for action bar views! " +
"State will not be restored.");
}
}
}
. onRestoreInstanceState()
在 Activity 重新创建的时候,会回调这个方法,将之前 onSaveInstanceState()方法保存的数据进行恢复,需要恢复数据,这个方法和 onCreate()
选用一个方法即可。
不同之处是如果 onSaveInstanceState() 方法如果被调用,那么代表
Activity 一定被重新创建了,参数中的 savedInstanceState 一定不为空,而在 onCreate() 则需要做出判断。
引起 Activity 重新创建的系统配置
android.content.res.Configuration 中的许多成员变量,都属于系统配置的 item, 比如屏幕方向,系统语言等。如果不想因为某项内容改变而引起Activity 重新创建的话,可以在清单文件里指定。
<!-- 不希望 Activity 在屏幕方向改变的时候重新创建 --><activity
android:name=".MainActivity"
android:configChanges="orientation" />
启动模式
概览
一些总结的点
.singleTask只是让系统判定为“可以单task启动”,而不是直接开启新的task启动,需要加上taskAffinity属性,值不同于当前的taskAffinity(一般默认的taskAffinity的value为包名
taskAffinity属性设置为相同,可以让不同应用的Activity跑在同一个task中。
按下多任务键,就能看到task的数量。
同一个task中,按下返回键起弹栈的作用。
为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task
示例
下图是同一个Application中,存在两个task,按下多任务键的情况
IntentFilter
Intent 分为两种,显式 intent 和 隐式的 intent,显式 intent 指定了包名和类名,而隐式 intent 没有。对于需要接受隐式 intent 的组件,我们需要指定过滤的规则,用 IntentFilter 对象来包裹过滤的信息。
IntentFilter 的过滤信息有 action, category, data
action 的匹配规则
一个过滤规则中可以含有多个 action,只要 intent 中的 action 的任意一个 和过滤规则中的 action的任意一个 匹配, 即为匹配成功。
category 的匹配规则
一个过滤规则中可以含有多个 category,要求 intent 中的所有 category 和 过滤规则中的 部分/所有category 匹配, 即为匹配成功。
data 的匹配规则
与 action 类似,如果在过滤规则中定义了 action,那么 Intent 中必须也要有匹配的 data。data 包含有以下的数据
. mimeType 媒体类型
. URI
. Scheme URI
的模式,这里我理解为协议
. Host 主机名
. Port 端口号
. Path 完整的路径
. PathPattern 使用正则表达式匹配路径
. PathPrefix 路径前缀
如
<intent-filter>
<dataandroid:mimeType="image/*" />
<!-- moreattrs --></intent-filter>
为了匹配这个规则,我们这样子写
intent.serDataAndType(Uri.parse("file:url"), "image/png");
另外, setData() 方法和 setType() 方法是互斥的,设置了
uri 会把 mimeType 清除,反之亦然,要设置完整的 uri 和 mimeType,调用 setDataAndType(Uri data, String type) 方法.
确保有组件可以收到隐式 intent 避免出错
以 activity 为例, PackageManager 提供了以下方法,这两个方法都返回 能够接收到这个隐式 intent 的 activity 集合或者信息。
其他的组件也有类似的方法。
. queryIntentActivities
/*
* @see #MATCH_DEFAULT_ONLY
*/public abstract List<ResolveInfo>
queryIntentActivities(Intentintent, int flags);
. resolveActivity
/**
* @see #GET_RESOLVED_FILTER
*/public abstract ResolveInforesolveActivity(Intentintent, int flags);
我们看常量 MATCH_DEFAULT_ONLY 的定义:
/**
* Resolution and querying flag: if set, only filters that support the
* {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for
* matching. This is a synonym for including the CATEGORY_DEFAULT in your
* supplied Intent.
*/public static final int MATCH_DEFAULT_ONLY = 0x00010000;
也就是说,需要保证不出错,建议将 flags 参数设置为 MATCH_DEFAULT_ONLY ,
以排除无法接收隐式 intent 的 activity (也就是 category 中不包含 android.intent.category.DEFAULT 的
activity ),这样子,如果这个方法能返回不为空的数据,则 startActivity() 方法一定会调用成功。
文章来自:技术学习小组
相关文章推荐
- [总结]机器学习中用到的线性代数公式,看完这个就够了
- 旧的一年过去了总结一下!新的一年一定好好维护其这个blog!
- PHP这个题目要马上解决了 不拖了~~会PHP的都看看把~~现在总结在这里(我发了3贴 乱78遭的)
- sql2005安装后没有客户端 这个问题困扰好多开发人员!我通过自己的摸索和总结 终于搞明白了!!!
- Android中Activity生命周期学习总结。
- 基础总结篇之一:Activity生命周期
- 运行程序时提出了这个一个警告:Activity not started, its current task has been brought to the front
- 【推荐】C语言深度剖析,这个blog的作者总结的这些东西还是挺好的,下载也是免费的
- asp.net过滤不良字符(今天用到了这个东西上网搜了搜总结一下)
- (Pmtest8.asm总结)PagingDemoProc 注意这个这个程序段使用的是LinearAddrDemo线性地址。分页后线性地址要转换
- 这个学期过完了,总结一下(工程篇)
- [zt][我去年总结出这个结论,今天看到周早有这样的体会]共享软件的互联网化是未来的发展方向
- 回收站不见了 怎么办?--- 近日多人加Q要求解决这个问题---今天总结一下
- 总结一下2009--2010这个学期看的书、演讲
- 【原创】总结这个项目可复用的功能
- 这个帖子主要总结数据库备份方面的问题
- D-Day +21 of .NET 总结+反省,以及计划。这个学期前作未有的充实。
- 去年的这个时候应该有很多园友在写总结吧
- 关于排序的总结---这个总是考总是忘的东西
- 总结Android中TabActivity 的使用方法