Android Dev 进程与线程 学习

来源:互联网 发布:mac下视频音频格式转换 编辑:程序博客网 时间:2024/06/05 05:23

进程

概要

当某个应用组件启动且此应用没有运行任何其他组件时,系统会使用单个线程为应用启动新的Linux进程

默认情况,同一应用的所有组件在同一个进程和线程中运行

如果某个应用组件启动,并且该应用已存在进程,则该组件在已经存在的进程中启动,并使用同一个已经存在的进程

开发者可以设置应用的组件在不同的进程中运行

标示进程

如果想让应用的不同组件在不同的进程中运行,可以在AndroidManifest.xml中配置

<activity>、<service>、<receiver>、<provider> 都支持android:proess属性,用来指定在哪个进程中运行

每个组件均可在各自的进程中进行,或者一些组件其中一些组件共享一个进程

如果内存不足,系统可能会决定在某一时刻关闭某一进程

如何决定终止哪个进程,系统会权衡它们的相对重要程度

进程的生命周期

系统将尽量长时间的保持应用进程

为了新建进程或运行更重要的进程,最终需要移除旧的进程来回收内存

系统会更具进程中运行的组件及其状态,来把进程放入一种 重要性层次结构 中。必要的时候,系统首先kill 重要性低的进程->重要性略逊的进程 依次类推。

进程的5级重要性层次结构

  1. 前台进程 : 当前用户操作所需要的进程
    • 托管正在交互的Activity (已调用Activity的onResume方法)
    • 托管某个Service,这个Service被绑定到用户正在交互的Acivity
    • 托管某个Service,这个Service正在前台运行(服务已调用startForeground)
    • 托管某个Service,正在执行一个生命周期回调的Service (onCreate)
    • 托管某个BroadcastReceiver,这个广播正在执行onReceive方法
  2. 可见进程 : 会影响用户在屏幕上的所见内容的进程,可见进程被视为极其重要的进程
    • 托管不在前台,但仍对用户可见的Activity(已调用其onPause)
    • 托管绑定到可见Activity的Service
  3. 服务进程
    • 正在运行,已经使用startService方法启动的Service,并且不属于上述两个级别。
    • 服务进程通常在执行一些用户关心的操作(后台播放音乐,网络下载数据)
  4. 后台进程
    • 包含目前对用户不可见的Activity进程。 ( 已经调用Activity的onStop方法)
      • 这些进程对用户体验没有直接影响,系统可能随时终止它们,以回收内存供更高级别的进程使用
      • 通常会有很多后台进程在运行,这些进程通常会保存在LRU列表中。
      • 在LRU列表中,用户最近查看的Activity的进程会最后一个被kill
  5. 空进程
    • 不包含任何活动应用组件的进程
      • 保留这种进程的唯一目的是用做缓存,以缩短下次在其中运行组件所需要的启动时间。
    • 注意:

  • 根据当前活动组件的重要程度,系统会将进程评定为它可能达到的最高级别
  • 一个进程的级别可能会因为其他进程的依赖而有所提高:服务于另一个进程的进程,其优先级别不会低于其服务的进程
  • 使用服务代替工作线程,对于后台进程,能够更持久的。BroadcastReceiver也应该把耗时冗长的操作放入Service来做

线程

主线程

应用启动时,系统会为应用创建一个名为 “主线程” 的执行线程

主线程负责事件的分发给响应的用户界面部件

主线程也是应用与Android UI 包组件进行交互的线程,因此主线程又称为UI线程。

系统不会为每个组件实例创建单独的线程,运行于同一进程的的所有组件均在UI线程中实例化,对每个组件的系统调用均由主线程进行分派。因此影响系统回调的方法均在进程的UI线程中运行。

应用执行繁重的任务响应用户交互时,使用单线程模式可能会导致其性能低下。

用户不能通过工作线程操作UI,只能通过UI线程操作用户界面

Android单线程模式必须要遵守的原则

  1. 不要阻塞UI线程
  2. 不要在工作线程访问UI

工作线程

工作线程如何访问UI线程

Activity.runOnUiThread(Runnable)

View.post(Runnable)

View.postDelay(Runnable, long)

更复杂情况

使用Handler来处理来自UI线程的操作

AsyncTask

其他

ContentProvider可以接受来自其他进程的数据请求

ContentProvider 和 ContentResolver 隐藏了如何管理进程间通信的细节

请求的ContentProvider方法(query,insert,delete,update),将葱ContentProvider所在进程的线程池中调用,而不是使用进程的UI线程


0 0