《Android Dev Guide》系列教程5:Android进程和线程

懒骨头(http://blog.csdn.com/iamlazybone)

当应用程序组件第一次运行时,Android在一个单独运行的线程里启动一个linux进程,默认情况下,这个程序的所有组件都将运行在这个进程和线程里。

然而,你可以让组件运行在其他的进程里,你也可以为任何进程新建额外的线程来运行。

进程

组件运行的进程受到manifest配置文件所控制。activity、service、receiver、provider这四种组件都有一个进程属性可以指定。这些属性可以让组件运行在自己的进程里,或者与其他组件共享进程或者禁止共享。可以让不同应用程序的组件运行在相同的进程里,只要提供相同的linux用户ID和相同的签名。application元素也有一个process属性,用来为所有的组件提供一个默认值。

所有的组件都在指定进程的主线程里被实例化,系统通过主线程调度组件。不会为每个实例都创建独立的线程。所以,这些回调方法:例如View.onKeyDown()方法报告用户的行为、声明周期的通知(在下面的章节讨论)总是运行在进程的主线程里。这就意味着系统调用组件时,没有组件可以一直运行很长时间或者以阻塞的方式操作(比如网络操作或者循环计算),因为这将会阻止进程里其他任何的组件加入。你可以为一些需要很长时间的操作建立独立的线程,作为接下来要讨论的主题:下一个。

Android在某些时刻可以据顶是否关闭一个进程,当可用内存很低时,并且其他进程需要立刻服务于用户时。在进程里运行的应用程序组件将被销毁。当这些组件重新被用户使用时,进程会重新启动。

当系统决定哪个进程将要被终止时,Android比较一下他们对用户的重要性。例如:一个不可见的activity比一个可见的activity更容易被关闭。是否关闭一个应用程序,取决于进程里运行中的activity的状态。这些状态待会在生命周期那一节中再讨论。


线程

即使你限制你的应用程序在一个独立的进程里,有时你需要新建一个线程来运行后台程序。因为界面必须对用户的操作很快的做出响应,所以像网络下载这样的一些耗时的行为,不该在主线程里进行。任何不能及时得到响应的事情都应该放在独立的线程里进行。

我们可以使用Java中的Thread对象来建立线程。Android提供一些基本的使用方便的类来管理线程。Looper可以在线程里运行一个消息循环,Handler来处理消息,Handler Thread 用来建立一个消息循环的线程。

远程程序调用

Android有一个轻量级的远程程序调用机制RPCs,当一个方法在本地声明,在其他地方被调用(比如其他进程里被调用),而不用返回值。这就需要将方法和数据分解为底层的操作系统可以理解的粒度,从本地的进程和地址空间传输到远程的进程和地址空间里,并在那里组装好。返回值需要回传。Android提供这些工作的代码,所以你可以专注于定义和实现这些接口。

一个RPC接口可以只包含方法。默认情况下,所有的方法都会同步化,本地方法会一直阻塞知道远程方法完成,甚至没有返回值。

简短来说,他的工作机制是这样的:先声明RPC的接口,用一个简单的IDL即接口定义语言来实现。通过声明,AIDL工具会生成java接口的定义,可以被本地和远程进程都能使用的定义。他包含两个内部类,如下图:

这两个内部类包含了所有你需要管理员远程调用你用IDL声明的接口的代码(太拗口)。两个内部类都要事先IBinder接口。其中一个在本地使用,你写代码时可以不用处理它,另一个是Stub,继承自Binder类。为了使IPC调用的内部代码有效,它包含了你用RPC接口所声明的方法。你可以继承Stub类来实现哪些方法,像上图那样。

通常情况下,远程进程会被一个后台服务所管理,因为服务可以通知系统给进程发消息,并且能连接到其他进程。他不仅包含了由aidl工具生成的接口文件,并且浩瀚Stub的子类事先RPC的方法。一个服务的客户端可以可以只有aidl工具生成的借口文件。

下面是一个服务和他的客户端是如何建立链接:

@服务的客户端(在本地端)实现onServiceConnected()和onServiceDisconnected()方法,所以当一个既定的远程服务链接成功时、或者断开连接时,他们可以被通知到。调用bindService()方法可以建立连接。

@服务的onBind()方法可以实现接受或者拒绝方法。这取决于接收到的Intent(bindService())。如果连接被接受了,他会返回一个Stub子类的实例。

@如果服务接受了连接,Android会调用客户端的onServiceConnected()方法,并且传递给一个IBinder对象,IBinder对象是一个被服务管理的Stub子类的代理。通过代理,客户端可以调用远程方法。

上面简短的介绍省略了一些RPC机制的细节。更多信息可以查看Designing a Remote Interface Using AIDL或者IBinder类的介绍。

线程安全方法

在一个新的contexts里,你实现的方法可能被多于1个的线程调用,因此必须是线程安全的。

这就是为什么被叫做远程方法,就像上节讨论的RPC机制一样。当调用一个实现自IBinder对象的方法时,此方法和IBinder一样属于同一个进程,那么方法在调用者的线程里执行。然而,如果在其他的进程里调用方法,那么方法在一个从Android维护的和IBinder在同意进程里的线程池里选择的一个线程里运行(太直译了),而不在主线程里运行。例如,一个服务的onBind()方法可以被服务所在进程的主线程所调用。onBind()返回的对象所实现的方法(例如一个实现RPC方法的Stub的子类)可以被线程池的方法调用。因为服务可以有多个客户端,同时可以有多个线程池服务于相同的IBinder方法。IBinder方法必须是方法安全的。

同样的,一个content provider内容提供商可以接收来自其他进程的数据请求。尽管ContentResolver和ContentProvider隐藏了管理进程间通信的细节,ContentProvider 方法响应这些需求:query方法,insert方法,delete方法,update更新方法,和getType方法,从contentProvider进程的线程池的线程里被调用,而不是主线程里。他们也可能同时被多个线程调用,所以也必须是线程安全的。

更多相关文章

  1. android Handler 机制研究学习笔记
  2. Android(安卓)消息处理机制(Looper、Handler、MessageQueue,Messa
  3. 【Android(安卓)开发】:数据存储之 SQLite 数据库操作(一)
  4. Android来电铃声默认设置的实现方法与怎么设置语音来电的默认铃
  5. Android(安卓)消息机制
  6. Android漫游记(1)---内存映射镜像(memory maps)
  7. Activity启动流程详解
  8. Chapter 10
  9. Android自动隐藏键盘

随机推荐

  1. Android开发实例详解之IMF(Android(安卓)S
  2. Prof Android app dev: Introduction and
  3. QQ For Android试用
  4. Android内存泄漏终极解决篇(上)
  5. 【Android】性能优化:电量消耗统计
  6. Android(安卓)Studio集成百度云推送
  7. Android.bp入门指南之Android.mk转换成An
  8. android常用布局详解
  9. frameworks中增加自定义服务使其也成为系
  10. ContentProvider数据模型