要点提炼|开发艺术之四大组件

提到四大组件大家肯定再熟悉不过了,本篇侧重于对四大组件工作过程的分析:

  • 概述
  • 工作过程
    • Activity
    • Service
    • BroadcastReceiver
    • ContentProvider

1.概述

a.Activity

  • 类型:展示型组件。
  • 作用:展示一个界面并和用户交互。
  • 使用:
    • 需要在AndroidManifest中注册。
    • 需要借助Intent启动,两种方式:
      • 显示Intent:
        Intent intent=new Intent(xxx.this,xxx.class); startActivity(intent);
      • 隐式Intent:
        Intent intent=new Intent(); intent.setAction(xxx); intent.addCategory(xxx); startActivity(intent);
    • 四种启动模式:
      • standard:标准模式
      • singleTop:栈顶复用模式
      • singleTask:栈内复用模式
      • singleInstance:单实例模式
    • 对用户而言是可见的。
    • 通过finish()结束一个Activity。

相关基础入门之Activity篇开发艺术之Activity

b.Service

  • 类型:计算型组件。
  • 作用:在后台执行一系列计算任务,耗时的后台计算建议在单独的线程中执行。
  • 使用:
    • 需要在AndroidManifest中注册。
    • 需要借助Intent启动:
      Intent intent = new Intent(xxx.this, xxx.class); startService(intent);
    • 两种运行状态:
      • 启动状态:通过startService()
      • 绑定状态:通过bindService()
    • 用户无法感知。
    • 通过unBindService()stopService()完全停止一个Service。

相关基础入门之Service篇

c.BroadcastReceiver

  • 类型:消息型组件。
  • 作用:在不同的组件乃至不同的应用之间传递消息。
  • 使用:
    • 两种注册方式:
      • 动态注册:通过Context.registerReceiver()& Context.unRegisterReceiver(),必须要应用启动才能注册并接收广播。
      • 静态注册:在AndroidManifest文件中注册,不需要启动应用即可接收广播。
    • 需要借助Intent发送广播:
      Intent intent = new Intent("xxx"); sendBroadcast(intent);
    • 四种广播类型:
      • 普通广播
      • 有序广播
      • 本地广播
      • 粘性广播
    • 用户无法感知。
    • 没有停止概念。

相关基础入门之BroadcastReceiver篇

d.ContentProvider

  • 类型:共享型组件。
  • 作用:向其他组件乃至其他应用共享数据。
  • 使用:
    • 需要在AndroidManifest中注册。
    • 无需借助Intent启动。
    • 四种操作:注意需要处理好线程同步
      • insert():添加数据
      • update():更新数据
      • delete():删除数据
      • query():查询数据
    • 用户无法感知。
    • 无需手动停止。

相关基础入门之ContentProvider篇IPC方式之ContentProvider
考考自己android四大组件的运行状态


二.工作过程

由于相关源码非常多,这里借用@amurocrash的UML图来提炼流程更为直观,另附相关源码分析的文章供大家详细了解。

a.Activity

Activity启动过程流程图:

Activity启动过程

结论

  • ActivityManagerService、ApplicationThread都是Binder
  • Application的创建也是通过Instrumentation来完成的,这个过程和Activity对象一样,都是通过类加载器来实现的。
  • Activity的启动过程最终回到ApplicationThread中,通过ApplicationThread.scheduleLaunchActivity() 将启动Activity的消息发送并交由Handler H处理。
  • Handler H对消息的处理会调用handleLaunchActivity()->performLaunchActivity()得以最终完成Activity的创建和启动。

源码分析Activity的工作过程

b.Service

  • Service启动过程流程图:
Service启动过程
  • Service绑定过程流程图:
Service绑定过程

结论

  • ContextImpl是Context的具体实现,通过Activity.attach()和Activity建立关联。Activity.attach()中还会完成Window的创建并和Activity&Window的关联,由此事件可传递给Window。
  • ActivityServices是一个辅助ActivityManagerService(AMS)进行Service管理的类,包括Service的启动、绑定和停止。
  • 和Activity类似的,Service的启动/绑定过程最终回到ApplicationThread中,通过ActivityThread.handleCreateService()/ActivityThread.handleBindService完成Service的启动/绑定,注意绑定Service的后续还必须 告知客户端已经成功连接Service 的这一流程,由ActivityManagerService.publishService()去完成。

源码分析Service的工作过程

c.ContentProvider

  • ContentProvider启动过程流程图:
ContentProvider启动过程
  • 启动的入口为ActivityThread.main():创建ActivityThread实例并创建主线程消息队列;
  • ->ActivityThread.attach():远程调用AMS.attachApplication()并提供ApplicationThread用于和AMS的通信;
  • ->AMS.attachApplication():通过ActivityThread.bindApplication()方法和Handler H来调回ActivityThread.handleBindApplication();
  • ->ActivityThread.handleBindApplication():先创建Application、再加载ContentProvider、最后回调Application.onCreate()

图片来源四大组件的工作过程

  • Query过程流程图:
Query过程

insert()delete()update()类似,这里不展开

结论

  • ContentProvider的multiprocess属性:ContentProvider是否是单例,一般用单例。
  • 访问ContentProvider需要ContentResolver,其真正实现类是ApplicationContentResolver。当ContentProvider所在进程未启动时,第一次访问它会触发ContentProvider的创建以及进程启动。
  • 当ContentProvider所在的进程启动时,会同时被启动并被发布到AMS中。注意:ContentProvider.onCreate()Application.onCreate()执行。
  • 同样的,最终通过ActivityThread.handleBindApplication()完成ContentProvider的创建。

源码分析 ContentProvider的工作过程

d.BroadcastReceiver

  • 四大组件的静态注册都是在应用安装时由PackageManagerService(PMS)解析注册,当动态注册Service时流程为:
Receiver动态注册过程
  • 广播发送和接收过程流程图:
广播发送和接收过程

结论:

  • 动态注册广播最终会跨进程交给AMS,并把远程Receiver( 实际上传的是IIntentReceiver,是个Binder )对象和远程IntentFilter保存起来,完成注册任务。
  • 发送广播时,系统为intent添加了两个标记位:
    • FLAG_INCLUDE_STOPPED_PACKAGES :广播也会发送到已经停止的APP(两个标记共存时,以该标记为准)
    • FLAG_EXCLUDE_STOPPED_PACKAGES :广播不会发送给已经停止的APP(系统为所有广播默认添加该标记)
  • 最终在ReceiverDispatcher .performReceive ()里回调了Receiver 的onReceive(),使得广播得以接收并处理。

源码分析BroadcastReceiver 的工作过程


希望这篇文章对你有帮助~