Activity的生命周期和启动模式笔记

2018-02-28  本文已影响0人  ZjyMac

一,Activity生命周期全面分析

(1)onCreate()
表示Activity正在被创建,主要做初始化工作例如加载界面布局资源,初始化所需数据。
(2)onRestart()
当前Activity 的 onPause()和onStop()被执行了 ,之后又回到了这个Activity会被调用
(3)onStart()
当前Activity已经可见,但是还没出现在前台及还无法和用户进行交互(也可理解为已经显示但用户还看不到)
(4)onResume()
当前Activity已经可见也可以与用户进行交互,与onStart()的区别在于 onResume处于前台,onStart()处于后台
(5)onPause()
当前Activity表示处于暂停状态,之后会调用onStop(),这里可以做一些不太耗时的操作,例如停止动画,存储数据等,这里要注意只有当前Activity走完onPause()方法 新的Activity才会执行onResume(极端情况下也有可能出现走到Pause方法立刻回到当前activity这个时候会走onResume)
(6)onStop()
当前Activity即将停止,可以做一写回收工作尽量避免过多的耗时操作
(7)onDestroy()
当前Activity即将被销毁,可以做回收工作和最终的资源释放

这里写图片描述

问题:为什么 当前Activity走完onPause()方法 新的Activity才会执行onResume()方法?
答:启动Activity的请求会由Instrumentationlai来处理,它通过Binder向AMS(ActivityManagerService)发起请求,AMS内部维护一个ActivityStack并负责栈内的Activity的状态同步,AMS通过ActivityThread去同步Activity的状态从而完成生命周期方法的调用,在ActivityStack中的resumeTipActivity-InnerlLock方法中 会判断栈顶的Activity 需要onPause后新的Activity才可以启动,启动后ActivityThread中的ApplicationThread调用scheduleLaunchActivity方法完成新的Activity的onCreate,onStart,onResume方法。

二,异常情况生命周期分析

例如横竖屏切换如果不做特殊处理,Activity就会被销毁并且重新创建,这个时候当销毁的时候会调用onSaveInstanceState()方法,重新创建会调用onRestoreInstanceState()。在这两个方法中系统会自动做一些恢复工作,例如文本框用户输入的数据,listview滚动的位置等。
系统自动恢复View工作的原理:
当Activity被意外终止后,Activity会调用onSaveInstanceState去保存数据,然后Activity会委托window去保存数据,接着window再委托顶级的容器view去保存数据,顶级容器是一个ViewGroup一般来说很可能是DecorView 之后顶层容器再去一一通知它的子元素来保存数据,是一种委托思想上层委托下层,android中view绘制,事件分发都是类似的思想。
保存时我们会在onSaveInstanceState中进行操作,当获取的时候我们可以在onCreate或者onRestoreInstanceState()中获取。
二者区别:
当onRestoreInstanceState被调用,其参数一定有值,不用额外去判断空值。onCreate就需要先去判断其参数是否为空再进行后续操作。

系统只在Activity异常终止的时候才会调用onSaveInstanceState与onRestoreInstanceState来储存和恢复数据,其他情况不会触发这个过程。但是按Home键或者启动新Activity仍然会单独触发onSaveInstanceState的调用。”

Activity优先级排序(由高到低)
1.前台Activity:正在和用户交互的Activity,优先级最高
2.可见非前台Activity:例如弹出对话框的Activity·,可见但是无法和用户直接交互
3.后台Activity:已经被暂停的Activity,比如执行了onStop()

<activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize" />

参数说明:
“mcc“ 移动国家号码,由三位数字组成,每个国家都有自己独立的MCC,可以识别手机用户所属国家。
“mnc“ 移动网号,在一个国家或者地区中,用于区分手机用户的服务商。
locale“ 所在地区发生变化,一般指切换系统语言
“touchscreen“ 触摸屏已经改变。(这不应该常发生,可以忽略)
“keyboard“ 键盘模式发生变化,例如:用户接入外部键盘输入。
"keyboardHidden" 键盘的可访问性发生变化——例如:用户发现了硬件键盘。
“navigation“ 导航型发生了变化。(这不应该常发生。)
"screenLayout" 屏幕布局发生变化——这个会导致显示不同的Activity。
"fontScale" 字体缩放因子发生变化——用户选择了新的字体大小。
"uiMode" 当UI模式发生改变的时候——当用户放置设备到桌子或/汽车或夜间模式改变的时候可以引起UI模式变化。阅读UiModeManager。在API级别8时引入。
"orientation" 屏幕方向发生变化——用户旋转了屏幕。注意:如果应用程序的目标API级别是13或更高(通过属性minSdkVersion和属性targetSdkVersion声明),你也需要声明配置项screenSize,因为这将在设备选择肖像和屏幕方向时发生改变。
"screenSize" 当前可用屏幕大小发生变化。这代表一个当前可用大小的变化,和当前的比率相关,因此当用户选择不同的画面和图像,会发生变化。然而,如果你的程序目标API级别是12或更低,你的Activity总是会自己处理这个配置变化(这个变化不会引起Activity的重启,甚至在Android 3.2或更新的设备上)。在API级别13里加入的。
"smallestScreenSize" 物理屏幕大小的变化。不管方向的变化,仅仅在实际物理屏幕打包变化的时候,如:外接显示器。这个配置项的变化引起在smallestWidth configuration里的变化。然而,如果你的程序目标API级别是12或更低,你的Activity将自己处理这个变化(这个变化不会引起Activity的重启,甚至在Android 3.2或更新的设备上)在API级别13里加入的。

三,启动模式

<activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize"
            android:launchMode="singleTask"/>

通过标志位指定启动模式

  Intent intent=new Intent();
        intent.setClass(this,IndexActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
 Intent intent = new Intent();
        //把打电话的动作ACTION_CALL封装至意图对象当中
        intent.setAction(Intent.ACTION_CALL);
        //设置打给谁
        intent.setData(Uri.parse("tel:" + phone));//这个tel:必须要加上,表示我要打电话。否则不会有打电话功能,由于在打电话清单文件里设置了这个“协议”
        //把动作告诉系统,启动系统打电话功能。
        startActivity(intent);

自定义Activity,并隐式方式启动

<activity android:name=".NextActivity">
    <intent-filter>
        <action android:name="com.itydl"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

在<action>标签中我们指明了当前活动可以响应 com.itydl 这个 action,我们可以随便写里面的内容,它的加入表示给我们的Activity添加一个动作,只有带动作的Activity才能被隐式启动。而<category>标签则包含了一些附加信息,更精确地指明了当前的活动能够响应的 Intent 中还可能带有的 category。意图中设置的action必须跟"com.itydl"是完全匹配的,只有<action>和<category>中的内容同时能够匹配上 Intent中指定的 action和 category时,这个活动才能响应该 Intent。我们也道,android.intent.category.DEFAULT 是一种默认的 category,在调用startActivity()方法的时候会自动将这category添加到 Intent中

对于Action的原理是:当StartActivity()运行的时候,该Activity会去系统所有清单文件中找对应的Action("")里面能匹配的Activity,找有没有对应的action与我们所写入的能匹配的,如果有(这里是NextActivity),这样就启动了NextActivity。

 Intent intent = new Intent();
        intent.setAction("com.itydl");
        startActivity(intent);

添加Data

<intent-filter>
    <action android:name="com.itydl"/>
    <data android:scheme="ydl"/>
    <category android:name="android.intent.category.DEFAULT"/>
</intent-filter>

在这里浅显介绍一下系统添加data下面的标签都有哪些:

<data>标签中主要可以配置以下内容。

  1. android:scheme
    用于指定数据的协议部分。
  2. android:host
    用于指定数据的主机名部分。
  3. android:port
    用于指定数据的端口部分,一般紧随在主机名之后。
  4. android:path
    用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。
  5. android:mimeType
    用于指定可以处理的数据类型,允许使用通配符的方式进行指定。只有<data>标签中指定的内容和 Intent 中携带的 Data 完全一致时,当前活动才能够响应该 Intent。不过一般在<data>标签中都不会指定过多的内容,常见的是mimeType和scheme。
intent.setData(Uri.parse("ydl:qwe"));
上一篇 下一篇

猜你喜欢

热点阅读