引言

当应用程序的组件第一次运行时,Android将启动一个只有一个执行线程的Linux过程。默认,应用程序所有的组件运行在这个过程和线程中。然而,你能够安顿组件运行在其余过程中,且你能够为过程衍生出其它线程。本文从上面几点来介绍Android的过程与线程:

1、过程
2、线程
2.1、近程过程调用(Remote procedure calls,RPCs)
2.2、线程平安办法

1、过程

组件运行于哪个过程中由清单文件管制。组件元素——<activity>、<service>、<receiver>、<provider>,都有一个process属性能够指定组件运行在哪个过程中。这个属性能够设置为每个组件运行在本人的过程中,或者某些组件共享一个过程而其余的不共享。他们还能够设置为不同应用程序的组件运行在同一个过程中——假如这些应用程序共享同一个Linux用户ID且被调配了同样的权限。<application>元素也有process属性,为所有的组件设置一个默认值。

所有的组件都在特定过程的主线程中实例化,且零碎调用组件是由主线程差遣。不会为每个实例创立独自的线程,因而,对应这些调用的办法——诸如View.onKeyDown()报告用用户的行为和生命周期告诉,总是运行在过程的主线程中。这意味着,没有组件当被零碎调用时应该执行很长时间或阻塞操作(如网络操作或循环计算),因为这将阻塞过程中的其它组件。你能够为长操作衍生独立的线程。

public boolean onKeyDown(int keyCode,KeyEvent event):默认实现KeyEvent.Callback.onKeyMultiple(),当按下视图的KEYCODE_DPAD_CENTER或KEYCODE_ENTER而后开释时执行,如果视图可用且可点击。

参数

keyCode-示意按钮被按下的键码,来自KeyEvent
event-定义了按钮动作的KeyEvent对象

返回值

如果你处理事件,返回true;如果你想下一个接收者处理事件,返回false。

当内存残余较小且其它过程申请较大内存并须要立刻调配,Android要回收某些过程,过程中的应用程序组件会被销毁。当他们再次运行时,会从新开始一个过程。

当决定终结哪个过程时,Android会衡量他们对用户重要性的绝对权值。例如,与运行在屏幕可见的流动过程相比(前台过程),它更容易敞开一个过程,它的流动在屏幕是不可见(后盾过程)。决定是否终结过程,取决于运行在过程中的组件状态。对于组件的状态,将在前面一篇——组件生命周期中介绍。

2、线程

尽管你可能会将你的应用程序限度在一个过程中,但有时候你会须要衍生一个线程做一些后盾工作。因为用户界面必须很快地响应用户的操作,所以流动寄宿的线程不应该做一些耗时的操作如网络下载。任何不可能在短时间实现的操作应该调配到别的线程。

线程在代码中是用规范的Java线程对象创立的,Android提供了一些不便的类来治理线程——Looper用于在线程中运行音讯循环、Handler用户解决音讯、HandlerThread用户设置一个音讯循环的线程。

Looper类

该类用户在线程中运行音讯循环。线程默认没有音讯循环,能够在线程中调用prepare()创立一个运行循环;而后调用loop()解决音讯直到循环完结。大部分音讯循环交互是通过Handler类。上面是一个典型的执行一个Looper线程的例子,别离应用prepare()和loop()创立一个初始的Handler与Looper交互:

class LooperThread extends Thread {

 public Handler mHandler;       public void run() {        Looper.prepare();               mHandler = new Handler() {            public void handleMessage(Message msg) {                // process incoming messages here            }        };               Looper.loop();    }   

}

更多的对于Looper的信息及Handler、HandlerThread请参阅相干材料。

2.1、近程过程调用(Remote procedure calls,RPCs)

Android有一个轻量级的近程过程调用机制——办法在本地调用却在近程(另外一个过程中)执行,后果返回给调用者。这须要将办法调用和它随同的数据合成为操作系统可能了解的档次,从本地过程和地址空间传输到近程过程和地址空间,并从新组装调用。返回值以相同方向传输。Android提供了做这些工作的所有代码,这样咱们能够专一于定义和执行RPC接口自身。

一个RPC接口仅蕴含办法。所有的办法同步地执行(本地办法阻塞直到近程办法执行实现),即便是没有返回值。简言之,该机制工作原理如下:首先,你用简略的IDL(interface definition language,接口定义语言)申明一个你想实现的RPC接口。从这个申明中,aidl工具生成一个Java接口定义,提供给本地和近程过程。它蕴含两个外部类,如下图所示:

外部类有治理你用IDL定义的接口的近程过程调用所须要的所有代码。这两个外部类都实现了IBinder接口。其中之一就是在本地由零碎外部应用,你写代码能够疏忽它。另外一个是Stub,扩大自Binder类。除了用于无效地IPC(interprocess communication)调用的外部代码,外部类在RPC接口申明中还蕴含办法申明。你能够定义Stub的子类实现这些办法,如图中所示。

通常状况下,近程过程有一个服务治理(因为服务能告诉零碎对于过程和它连贯的其它过程的信息)。它有由aidl工具生成的接口文件和Stub子类实现的RPC办法。服务的客户端仅有由aidl工具生成的接口文件。

上面介绍服务如何与它的客户端建设连贯:

服务的客户端(在本地端的)应该实现onServiceConnected() 和onServiceDisconnected() 办法,因而当与近程服务建设连贯胜利和断开连接是会告诉它。而后调用bindService() 建设连贯。
服务的onBind()办法将实现为承受或回绝连贯,者取决于它承受到的用意(该用意传送到binServive())。如果连贯被承受,它返回一个Stub子类的实例。
如果服务承受连贯,Android调用客户端的onServiceConnected()办法且传递给它一个IBinder对象,返回由服务治理的Stub子类的一个代理。通过代理,客户端能够调用近程服务。
这里只是简略地形容,省略了一些RPC机制的细节。你能够查阅相干材料或持续关注Android开发之旅,前面将为你奉上。

2.2、线程平安办法

在一些状况下,你实现的办法可能会被不止一个线程调用,因而必须写成线程平安的。这对近程调用办法是正确的——如上一节探讨的RPC机制。当从IBinder过程中调用一个IBinder对象中实现的一个办法,这个办法在调用者的线程中执行。然而,当从别的过程中调用,办法将在Android保护的IBinder过程中的线程池中抉择一个执行,它不在过程的主线程中执行。例如,一个服务的onBind()办法在服务过程的主线程中被调用,在onBind()返回的对象中执行的办法(例如,实现RPC办法的Stub子类)将在线程池中被调用。因为服务能够有一个以上的客户端,所以同时能够有一个以上的线程在执行同一个IBinder办法。因而,IBinder的办法必须是线程平安的。

同样,一个内容提供者能够承受其它过程产生的数据申请。尽管ContentResolver 和 ContentProvider 类暗藏过程通信如何治理的,对应哪些申请的ContentResolver 办法——query()、insert()、delete()、update()、getType(),在内容提供者的过程的线程池中被调用,而不是在这一过程的主线程中。因为这些办法能够同时从任意数量的线程中调用,他们也必须实现为线程平安的。

注:来自51CTO博客作者Saylor87的作品