【android教程】Android应用程序基础(Application Fundamentals)2

2012-11-07 01:10 阅读 777 次 评论关闭

7、清理堆栈
当用户离开一个task一段时间后,系统就会清理掉task里出了rootActivity 以外的Activity,如果用户又回来了,显示的是rootActivity,就像是用户离开 又回来,是放弃以前的东西,开始新的东西。
上面说的是默认的情况,有一些Activity的属性可以用来控制和修改这些行 为。
alwaysRetainTaskState
如果一个task里的root Activity的alwaysRetainTaskState属性设置为true ,那么前面描述的默认情况就不会出现了,task即使过了一段时间也会一直保留 所有的Activity。
clearTaskOnLaunch
如果一个task里的root Activity的clearTaskOnLaunch属性设置为true,和 alwaysRetainTaskState相反,即使是一瞬间的离开,系统马上就会清理掉task 里出rootActivity以外的所有Activity。
finishOnTaskLaunch
这个属性和clearTaskOnLaunch一样,但是他是对一个Activity起作用,不是 整个task,他能引起所有的Activity离开,包括root Activity,当这个属性设 置为true,只是当用户使用这个应用时Activity才在task里,一旦用户离开后重 新回来,显示的不是当前的界面。
还有其他的方法来从task里强制移动Activity,如果一个Intent对象里包含 FLAG_ACTIVITY_CLEAR_TOP标志,并且目标task里已经一个在自己task里可以处 理Intent的Activity(就是处理这个Intent无需实例化另外一个Activity),那 么在这个Activity之上的所有Activity将被清除,能处理这个Intent的Activity 就移到栈顶来处理这个Intent,例如ABCD堆栈,含有FLAG_ACTIVITY_CLEAR_TOP 标志的Intent来启动B,那么清除CD,B到达栈顶来响应Intent,此时是AB,如果 B设置了standard属性,那么还是清楚CD,然后再创建一个实例来响应Intent, 此时是ABB,因为standard属性的Activity总是创建一个新的实例来响应新的 Intent。
8、进程和线程(Processes and Threads)
当一个应用的第一个组件需要运行时,android系统就为这个组件启动一个只 有一个线程的Linux进程,默认的,应用的所有组件都运行这个进程中的这个线 程中。
但是,你可以安排组件运行在其他的进程中,并且为你的任意的进程增加若 干线程。
1、进程
组件运行的进程是在manifest文件里控制的,四大组件都一个process属性可 以指定进程来运行,这些属性可以被设置为了每个组件都可以运行在他自己的进 程中,或者几个组件共享一个进程,或者不共享,如果两个应用共享一个Linux user ID并且有相同的权限,那么就可以使这两个应用中的组件运行在相同的进 程中,<application>也有process属性,用来指定对所有组件的属性。
所有的组件都在指定的进程中的主线程中实例化,系统调用这些组件就是从 主线程里发出的,其他的线程将不会对每个组件再实例化,所有作为调用的回应 的这些方法,比如说View.onKeyDown()还是组件的生命周期函数等等都是运行在 这个主线程中的,这就意味着当系统调用这个组件时,这个组件不能长时间的阻 塞线程(比如说网络操作,循环计算),因为这样会阻塞这个进程中的其他组件 ,你可以将很耗时的任务分到其他的线程中。
当内存不足或者有其他更紧急的进程要求时,Android系统可能关闭一个进程 ,运行在这个进程中的应用组件因此被销毁,当用户又重新回来时,进程才被重 新启动。
至于究竟要停止哪个进程,android系统是通过衡量哪个进程对用户来说更重 要来实现的
2、线程
你可以限制你的应用运行在一个进程中,但是有的时候你需要新开一个线程 在后台运行,用户界面需要随时对用户的要求做出反应,所以一些很耗时的工作 应该重新启动一个线程来做,以免阻塞主进程。
Android系统提供了一系列方便的类来管理线程(Looper,Handler, HandlerThread)

3、远程调用(Remote procedure calls)
Android系统有一个轻量级的远程调用机制(RPC)-----一个方法在本地调用 ,但是在远程执行(在另外一个进程里),返回给调用端的所有结果都必须的系 统能理解的,将数据从本地进程和地址空间传递到远程的进程和地址空间,并在 远端重新装配,返回值的时候传输方向相反,android系统会去做这些传输的工 作,让你能够集中精力来定义你的RPC
一个RPC接口只能包含方法,默认的,即使是没有值返回,所有的方法都是同 步执行的,就是说本地方法一直会阻塞直到远端的方法执行完毕)。
简单的说,这个远程调用的机制是这样工作的:
首先你需要用IDL(interface definition language)声明你的RPC接口,然 后android系统会使用aidl工具来形成一个java接口,并且这个java接口是本地 进程和远端进程都可以获得的,这个java接口包含了两个内部类,请看下图:

这两个内部类有管理远程调用(你用IDL声明的接口)的所以代码,两个内部类 都实现IBinder接口,一个是在本地(内部)使用,这个你可以不用自己写代码,另 外一个叫做Stub,继承自Binder类的,包含所有完成进程间通信(IPC)的代码 ,他包含你在RPC接口中声明的所有方法,你应该继续继承Stub类来实现这些方 法。
一般的,远端进程应该由一个service来管理(因为一个service能通知系统 关于这个进程和他连接到的其他进程)。

9、进程的生命周期(Processes and lifecycles)
Android系统总是尽最大的努力来维持一个应用的进程,但系统的内存不足时 就可能需要关闭一些旧的进程了,但是决定关闭哪个进程呢,android系统把所 以的进程放进一个重要性树里,最低重要性的进程将会被停止,系统有5种重要 性等级,重要性从高到低如下:
(1)、前台进程。一个前台进程是当前执行用户请求的进程,如果有如下的 一种情形的那么他就是前台进程:
a、这个进程里运行着一个正在和用户交互的Activity(这个Activity的 onResume()方法被调用)。
b、这个进程里有绑定到当前正在和用户交互的Activity的一个service
c、这个进程里有一个service对象,这个service对象执行了至少一个他生命 周期的函数(onCreate(), onStart(), or onDestroy()).
d、这个进程里有一个执行了onReceive()方法的broadcastreceiver对象
只有一定数量的前台进程在任何时间都存在,他们只有在最后的时刻被停止 ---系统的内存太少了而不能运行这些仅有的前台进程了),一般的,在那个时 刻,手机会重新设置内存页的状态,所以停止一些前台的进程是为了保持对用户 操作的快速响应。
(2)可见进程。一个可见进程一个没有任何前台显示的组件,但是仍然可以 影响到用户当前屏幕所看见的东西,如果有如下的一种情形那么他就是可见进程 。
a、这个进程里一个Activity,但是这个Activity当前不是在前台显示,但是 仍然对用户是可见的(这个Activity的onPause()方法被调用),比如说一个 Activity调用一个dialog,那么这个dialog是当前显示的组件,这个Activity不 是在前台显示,但是对用户是可见的。
b、这个进程里有一个绑定到一个可见Activity(如上所述的Activity)的 service
一个可见进程是极端重要的,只有在为了显示所有前台进程时,即显示前台 进程都不够时,才会停止可见进程。
(3)、服务进程。一个服务进程是一个通过startService()启动的但是没 有在前两个分类中的进程,虽然服务进程不是用户直接能看见的,但是他也总是 做一些用户很关心的事(如在后台播放mp3,从网络上下载东西),所以系统会 一直保持服务进程运行,除非内存不足以运行服务进程,前台进程,可见进程。
(4)后台进程。一个后台进程是运行一个当前对用户是不可见的Activity( 这个Activity的onStop()被调用),这些进程对用户体验没有什么直接的影响 ,当内存不足以运行前台进程,可见进程,服务进程时,可以随时停止后台进程 ,通常有很多的后台进程在运行,系统会把这些后台进程放进一个LRU中(最近 使用队列),最近使用的就最后停止。
(5)空进程。一个空进程就是进程里没有任何活动的应用组件,维持这种进 程的唯一原因就是作为一种缓存,当一个组件需要启动时加快启动的速度,系统 为了平衡进程缓存和核心缓存会停止这些空的进程。
Android系统会取一个进程里的所以组件的最高重要性来安排进程的重要性, 比如说,一个进程里有一个service和一个可见的Activity,那么这个进程会被 安排成一个可见进程,而不是服务进程。
另外,一个进程的重要性有可能会因为其他进程的依赖而升高,一个进程不 能比他所服务的进程的重要性低,比如有进程A里的service绑定到了进程B的组 件上,那么进程A的重要性至少和进程B的一样,或者更高。
因为一个服务进程的重要性比运行一个后台Activity的进程高,所以,当一 个Activity做一些长时间运行的任务时,最好启动一个service来做,而不是放 到一个线程里去做,特别是这个任务的时间可能比Activity运行的时间还长的时 候,比如在后台播放音乐,或者上传一张图片到网上,使用一个service保证了 这个任务至少是服务进程的重要性,broadcast receiver也是一样,长时间运行 的任务也最好是放到一个service里,而不是放到一个线程里。

Terry_龙

版权声明:本文著作权归原作者所有,欢迎分享本文,谢谢支持!
转载请注明:【android教程】Android应用程序基础(Application Fundamentals)2 | 猎微网

评论已关闭!