分享

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

 lifei_szdz 2012-12-26

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

分类: Android Application 802人阅读 评论(0) 收藏 举报

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

懒骨头(http://blog./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进程的线程池的线程里被调用,而不是主线程里。他们也可能同时被多个线程调用,所以也必须是线程安全的。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多