Android知识体系查漏补缺(一)系统源码

1. 组件

1. 四大组件

  • ActivityService都是继承于Context基类,而BroadcastReceiverContentProvider则均是抽象基类。

1. Activity(活动)

1. 启动过程
  • 隐式启动根据actioncategoryURI这三者提供的信息来启动Activity。可以有多个category(见intent.addCategory()),但只能有一个action(见intent.setAction())。
  • Intent传值与Bundle传值的区别在于,Bundle可以复用,在某些情况下可以简化代码。IntentputExtra方法其实也是将值传给内部的Bundle
  • 如果调用了两次setContentView方法,只有最后一次才是有效的,因为setContentView方法所指定的View,只有在onCreate方法返回后才会显示在界面上。如若需要调用两次setContentView方法,可将第二次放在Handler内处理。
2. 启动模式
  • task指任务栈,用于装载Activity。启动模式为默认的时候,activity会运行在启动它的task中,不论两个activity是不是同一个应用。
  • 指定singleTopsingleTasksingleInstanceActivity在复用时会回调onNewIntent()onResume(),不回调onCreate()onStart()
  • android:taskAffinity属性配合singleTask使用,用于标识任务栈的名字。
3. 生命周期
  • onStart()之后可见,onResume()之后可交互。同理,onPause()之后不可交互,onStop()之后不可见。
  • 点击home键回到桌面后再次回到原Activity时:onRestart()onStart()onResume()
    实测无论从最近任务还是从launcher返回都遵循此路径,锁屏后再解锁时同样遵循此路径。
  • 单纯弹出Dialog或者下拉通知栏等并不会回调生命周期;跳转至对话框样式或透明的Activity时,会只调用onPause(),不调用onStop()
  • onCreate/onRestart中执行finish()onCreate()/onRestart()onDestroy()
    onStart中执行finish()onCreate()onStart()onStop()onDestroy()
  • 在异常情况下,如系统配置改变,会调用onSaveInstanceState()onRestoreInstanceState,但如果设置了android:configChanges属性,则只会调用onConfigurationChanged()

详细解释见:Activity的生命周期和启动模式。

2. Service(服务)

  • Service是一种可在后台执行长时间运行操作不提供界面的应用组件。一些后台工作不适合脱离四大组件独立运行在后台中(比如单独运行在工作线程中),这样进程容易被杀死。比较好的方法就是将后台工作放入Service中从而保证进程有一定的优先级,这样就不会轻易地被系统杀死。
  • Service分3种类型:前台服务(必须显示通知且不能清除)、后台服务、绑定服务。
  • Service同样运行于 UI 线程,不能执行耗时操作。如需执行耗时操作,则在Service内创建新线程或使用IntentService
1. 启动方式
  • startService()bindService()。前者是单向操作,适合往Service传递少量数据,后者是双向操作,会和应用组件绑定,可以进行持续交互。
  • 为确保应用的安全性,在启动Service时,始终使用显式Intent
  • 通过添加android:exported属性并将其设置为false,确保服务仅适用于自身应用,可以有效阻止其他应用启动该服务。
2. 生命周期
  • startService()创建服务后会无限期运行,必须通过stopSelf()自行停止,或由组件调用stopService()来停止。
  • bindService()创建服务后,客户端可通过unbindService()关闭连接。多个客户端可以绑定到相同服务,而且当所有绑定全部取消后,系统即会销毁该服务。服务不必自行停止运行。
    服务生命周期
3. IntentService
  • Service的子类,其使用工作线程逐一处理所有启动请求。如果不要求服务同时处理多个请求,此类为最佳选择。
  • 实现onHandleIntent(),该方法会接收每个启动请求的Intent,以便执行后台工作。
  • 在处理完所有启动请求后会停止服务,不必调用stopSelf()

参考:后台任务 - 服务:服务概览 | Android 开发者 | Android Developers

3. BroadcastReceiver(广播接收器)

1. 广播的使用场景
  • 同一应用内多个进程的不同组件之间的消息通信。
  • 不同应用间组件之间的消息通信。
2. 接收广播
  • 通过两种方式:清单声明的接收器或上下文注册的接收器。
  • 如果在清单中声明接收器,如果应用尚未运行,系统会在广播发出后启动应用。
  • 对于清单声明的接收器,可以在清单中将android:exported属性设置为false,就不会接收来自应用外部的广播。
  • 以 Android 8.0(API 级别 26)或更高版本为目标平台时,对于大多数隐式广播(没有明确针对应用的广播),不能使用清单来声明接收器。
  • 如果希望多花一点时间(在 10 秒以内)来处理广播,在接收器的onReceive()方法中调用goAsync(),并将BroadcastReceiver.PendingResult传递给后台线程。要执行长时间运行的工作,使用JobScheduler调度作业。
3. 发送广播
  • 有序广播:sendOrderedBroadcast(Intent, String),可被拦截,接收者可以修改。运行顺序通过匹配的intent-filterandroid:priority属性来控制。
  • 无序广播:sendBroadcast(Intent),不可被拦截,接收者不可修改。
  • 本地广播:LocalBroadcastManager.sendBroadcast,只在应用内传播,效率高,无安全问题。
    注:LocalBroadcastManager将弃用,因其是应用级事件总线,在应用中使用了层违规行为:任何组件都可以监听来自其他任何组件的事件。可以将LocalBroadcastManager替换为可观察模式的其他实现。合适的选项可能是LiveData或被动流,具体取决于用例。
  • 粘性广播sendStickyBroadcast (Intent),广播会留存至接收器注册。因安全问题,从 Android 5.0(API 级别21)开始不推荐使用。
4. 通过权限限制广播
  • 发送广播时可以指定权限参数。接收器若要接收此广播,则必须在清单中请求该权限。
  • 如果在注册广播接收器时指定了权限参数,则广播方必须在清单中请求该权限,才能向该接收器发送Intent

参考:后台任务 - 广播:广播概览 | Android 开发者 | Android Developers

4. ContentProvider(内容提供程序)

  • 内容提供程序以一个或多个表的形式将数据呈现给外部应用,这些表与在关系型数据库中找到的表类似。
1. 访问提供程序
  • 以客户端的形式使用应用的Context中的ContentResolver对象,从而与提供程序进行通信。提供程序对象从客户端接收数据请求、执行请求的操作并返回结果。
  • ContentResolver的方法可提供持续存储的基本“CRUD”(创建、检索、更新和删除)功能。
2. 内容 URI
  • 用于在提供程序中标识数据的 URI, 包括整个提供程序的符号名称(其授权)和指向表的名称(路径)。如用户字典表的完整 URI 中,user_dictionary是提供程序的授权,words是表的路径。content://架构)始终显示,并且会将其标识为内容 URI :
	content://user_dictionary/words
  • 许多提供程序均允许将 ID 值追加至 URI 末尾,从而访问表中的单个行。例如,从用户字典中检索_ID4的行,可以使用此内容 URI:
	Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI, 4);
3. 创建内容提供程序
  • 内容提供程序以两种方式提供数据:文件数据结构化数据
  • 构建提供程序:设计数据存储,设计内容 URI ,实现ContentProvider类,实现内容提供程序 MIME 类型,实现协定类,实现内容提供程序权限等。
  • 即使底层数据为私有数据,所有应用仍可读取提供程序的数据或向其写入数据,因为提供程序默认未设置权限。如要更改此情况,在清单文件中为提供程序设置权限。权限为自定义权限,需在清单文件中定义,客户端访问时需申请此权限。
4. ContentObserver
  • 用于观察特定 URI 引起的数据库的变化。通过ContentResolver来注册和取消注册。
  • 需要在ContentProvider中数据发生变动时调用getContext().getContentResolver().notifyChange(uri, null)来通知。

参考:内容观察者:ContentObserver - 简书
应用数据和文件 - 内容提供程序:内容提供程序 | Android 开发者 | Android Developers
访问内容提供程序:内容提供程序基础知识 | Android 开发者 | Android Developers
创建内容提供程序:创建内容提供程序 | Android 开发者 | Android Developers

你可能感兴趣的:(学习笔记,Android)