Android 总结4-四大组件

Posted by Jfson on 2019-01-15

Activity

1.Activity生命周期

(A)onPause→(B)onCreate→(B)onStart→(B)onResume→(A)onStop

  • (1)一个Activity或多或少会占有系统资源,而在官方的建议中,onPause方法将会释放掉很多系统资源,为切换Activity提供流畅性的保障,而不需要再等多两个阶段,这样做切换更快。
  • 如果如果Activity(A) 切回桌面或者打开新Activity(B) :onPause() -> onStop();如果Activity(B)采用了透明主题,那么A不会走onStop()
  • (2)按照生命周期图的表示,如果用户在切换Activity的过程中再次切回原Activity,是在onPause方法后直接调用onResume方法的,这样比onPause→onStop→onRestart→onStart→onResume要快得多。

与生命周期密切相关的onSaveInstanceState方法和onRestoreInstanceState方法在什么时候执行?
通过阅读源码会发现:横竖屏切换时或者非正常销毁(低优先级)。

  • onSaveInstanceState 是在onStop()之前

  • onRestoreInstanceState是在onStart之后、onResume之前调用的。

1
2
->onPause->onSaveInstanceState->onStop->onCreate->onStart
->onRestoreInstanceState->onResume
  • android:ConfigChanges属性发生改变,Activity 就会重建。除非进行指定了该属性,这也就不会触发onSaveInstanceState,onRestoreInstanceState
2.Fragment生命周期
  • 单个 Activity + Fragment 的启动?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Activity onCreate
Fragment onAttach
Fragment onCreate
Fragment onCreateView
Fragment onViewCreated
Activity onStart
// 下面两个由 super.onStart 触发
Fragment onActivityCreated
Fragment onStart
Activity onResume
Activity onPostResume
// 下面一个由 super.onPostResume 触发
Activity onResumeFragments
// 下面一个由 super.onResumeFragments 触发
Fragment onResume

3.LaunchMode

  • 当使用AppplicationContext启动 standard 模式的Activity 会Crash。需要指定FLAG_ACTIVITY_NEW_TASK,启动一个新的任务栈。(Activity 栈:TaskRecord)
  • standard:默认模式,不断的新建一个新的 Activity 加入到当前栈顶。多实例,入当前栈

  • singleTop: 栈顶复用模式(栈顶单实例)。和默认模式相比,新启动一个 Activity 时,如果当前栈顶就是这个 Activity 的实例,那就不会创建新的 Activity,而是调用该实例的 onNewIntent() 方法。其他情况行为和默认模式一致

  • singleTask:栈内复用模式。所需任务栈中有就复用,并移除其上所有Activity并调用该实例的 onNewIntent() 方法。

    所需任务栈中没有就新创建一个栈,压栈。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    在启动 singleTask 的 Activity时,系统会先检查是否有 Task 的
    affinity 值与该 Activity 的 taskAffinity 相同,如果有,Activity
    就会在这个 Task 中启动,否则就会在新的 Task
    中启动。因此,如果我们想要设置了 singleTask 启动模式的 Activity
    在新的 Task 中启动,就要为它设置一个独立的 taskAffinity
    属性值。如果不是在新的 Task 中启动,它会在已有的 Task
    中查看是否已经存在相应的 Activity 实例,如果存在,
    就会把位于这个 Activity 实例上面的 Activity 全部结束掉,
    即最终这个 Activity 实例会位于该 Task 的栈顶,
    并调用该实例的 onNewIntent() 方法。
  • singleInstance:单独的位于一个任务栈中

上述中的所需任务栈:TaskAffinity参数可以标识所需任务栈的名字。默认是应用的包名。TaskAffinity 和 allowTaskReparenting结合使用,想象一下应用A拉起微信,切后台,点开微信,是A拉起的页面

4.IntentFilter

  • 启动Activity 可以分为显示调用和隐式调用。

    • 常规的显示调用不多说,需要明确指定被启动对象的组件信息,包括包名和类名:new Intent()

    • 隐式调用

      通过Intent Filter来实现的,它一般用在没有明确指出目标组件名称的前提下。Android系统会根据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。一般是用于在不同应用程序之间.

      一个Activity 可以有多个,只要匹配上一个就可以。

      • action

        中可以有多个action;区分大小写

      • category

        intent中如果出现了category,不管有几个,都必须是intent filter中已经定义的category,也就是说intent可以没有category,一旦有,每个都必须和intent filter中定义的任意一个category相同;那为什么我们没在intent filter中加android.intent.category.DEFAULT这个category会报错呢?原因是系统在调用startActivity或者startActivityForResult的时候会默认在intent中加上android.intent.category.DEFAULT这个category。 系统会默认给个android.intent.category.DEFAULT

      • data

        可以配置scheme;host;port;path等等相当于scheme,夸应用常用scheme

5.广播(动态注册和静态注册区别,有序广播和标准广播)

  • 1.注册方式(动态注册 & 静态注册)
    • android中,我们如果想接收到广播信息,必须自定义我们的广播接收者。要写一个类来继承BroadcastReceiver,并且重写其onReceive()方法,实现接收到特定广播所要做的事情。
    • 动态注册-> 代码层级的registerReceiver
    • 静态注册-> Manifest.xml中静态注册
    • 动态注册不是常驻型广播,也就是说广播跟随activity的生命周期期。静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行
    • 动态注册的广播 永远要快于 静态注册的广播,不管静态注册的优先级设置的多高,不管动态注册的优先级有多低
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// ------- 动态注册 -------
//new出上边定义好的BroadcastReceiver
MyBroadCastReceiver yBroadCastReceiver = new MyBroadCastReceiver();
//实例化过滤器并设置要过滤的广播
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
//注册广播
myContext.registerReceiver(smsBroadCastReceiver,intentFilter,
"android.permission.RECEIVE_SMS", null);
// --------- 静态注册 ---------
<receiver android:name=".MyBroadCastReceiver">
<!-- android:priority属性是设置此接收者的优先级(从-1000到1000) -->
<intent-filter android:priority="20">
<actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS">
</uses-permission>
  • 2.有序广播和标准广播
    • 通过mContext.sendBroadcast(Intent)或mContext.sendBroadcast(Intent, String)发送的是无序广播(后者加了权限);
    • 通过mContext.sendOrderedBroadcast(Intent, String, BroadCastReceiver, Handler, int, String, Bundle)发送的是有序广播。
    • 无序广播:所有的接收者都会接收事件,不可以被拦截,不可以被修改。
    • 有序广播:按照优先级,一级一级的向下传递,接收者可以修改广播数据,也可以终止广播事件。

6.service生命周期

  • Service两种启动方式
    • 1.直接开启startService,使用stopService关闭。stratService和stopService一一对应,一个开启,一个结束。生命周期:StartService -> onCreate() -> onStartCommond() -> stopService -> onDestory()
    • 2.绑定开启bindService,使用unbindService解绑关闭。bindServic和unbindService一一对应,一个绑定开启,一个解绑结束。生命周期:BindService -> onCreate() -> onBind() -> UnbindService() ->onUnbind() -> onDestory()
  • 区别
    • start和stop只能开启和关闭,无法操作service。bind和unbind可以操作service。
    • start开启的service,调用者退出后service仍然存在。bind开启的service,调用者退出后,随着调用者销毁。
  • 注意
    • 1.在整个生命周期内,只有startCommand()能被多次调用。其他方法只能被调用一次。(即只能绑定和解绑一次。)
    • 2.绑定后没有解绑,无法使用stopService()将其停止。
    • 3.如果已经onCreate(),那么startService()将只调用startCommand()。
    • 4.如果是以bindService开启,那么使用unbindService时就会自动调用onDestroy销毁。
      根据条件所有的判定图如下:

pv UV: