AsyncTask:
[AsyncTask的缺陷和问题]
关于线程池:asynctask对应的线程池ThreadPoolExecutor都是进程范围内共享的,都是static的,所以是asynctask控制着进程范围内所有的子类实例。由于这个限制的存在,当使用默认线程池时,如果线程数超过线程池的最大容量,线程池就会爆掉(3.0后默认串行执行,不会出现这个问题)。针对这种情况,可以尝试自定义线程池,配合asynctask使用。
关于默认线程池:核心线程池中最多有CPU_COUNT+1个,最多有CPU_COUNT*2+1个,线程等待队列的最大等待数为128,但是可以自定义线程池。线程池是由AsyncTask来管理的,线程池允许tasks并行运行,xuyao注意的是并发情况下数据的一致性问题,新数据可能会被老数据覆盖掉,类似volatile变量。所以希望tasks能够串行运行的话,使用SERIAL_EXECUTOR。
自定义线程池:executeOnExecutor(Executor exec,Params… params) 自定义Executor
execute(Params… params){return executeOnExecutor(sDefaultExecutor,params);}
AsyncTask在不同的SDK版本中的区别:
调用AsyncTask的excute方法不能立即执行程序的原因分析及改善方案
通过查阅官方文档发现,AsyncTask首次引入时,异步任务是在一个独立的线程中顺序的执行,也就是说一次只能执行一个任务,不能并行的执行,从1.6开始,AsyncTask引入了线程池,支持同时执行5个异步任务,也就是说同时只能有5个线程运行,超过的线程只能等待,等待前面的线程某个执行完了才被调度和运行。换句话说,如果一个进程中的AsyncTask实例个数超过5个,那么假如前5个都运行很长时间的话,那么第6个只能等待机会了。
这是AsyncTask的一个限制,而且对于2.3以前的版本无法解决。如果你的应用需要大量的后台线程去执行任务,那么你只能放弃使用AsyncTask,自己创建线程池来管理Thread,或者干脆不用线程池直接使用Thread也无妨。不得不说,虽然AsyncTask较Thread使用起来方便,但是它最多只能同时运行5个线程,这也大大局限了它的实力,你必须要小心设计你的应用,错开使用AsyncTask的时间,尽力做到分时,或者保证数量不会大于5个,否则就会遇到上次提到的问题。可能是Google意识到了AsyncTask的局限性了,从Android3.0开始对AsyncTask的API作出了一些调整:每次只启动一个线程执行一个任务,完成之后再执行第二个任务,也就是相当于只有一个后台线程在执行所提交的任务。
1、生命周期
很多开发者会认为一个在Activity中创建的AsyncTask会随着Activity的销毁而销毁。然而事实并非如此。AsyncTask会一直执行,直到doInBackground()方法执行完毕。然后,如果cancel(boolean)被调用,那么onCancelled(Result result)方法会被执行;否则,执行onPostExecute(Result result)方法。如果我们的Activity销毁之前,没有取消AsyncTask,这有可能让我们的AsyncTask崩溃(crash)。因为它想要处理的view已经不在了。所以,我们总是必须确保在销毁活动之前取消任务。总之,我们使用AsyncTask需要确保AsyncTask正确的取消。
2、内存泄漏
如果AsyncTask被声明为Activity的非静态的内部类,那么AsyncTask会保留一个对Activity的引用。如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄漏。
3、结果丢失
屏幕旋转或Activity在后台被系统杀掉等情况会导致Activity的重新创建,之前运行的AsyncTask会持有一个之前Activity的引用,这个引用已经无效,这时调用onPostExecute()再去更新界面将不再生效。
4、并行还是串行
在Android1.6之前的版本,AsyncTask是串行的,在1.6至2.3的版本,改成了并行的。在2.3之后的版本又做了 修改,可以支持并行和串行,当想要串行执行时,直接执行execute()方法,如果需要执行executeOnExecutor(Executor)。
3.Android机制
(1)Linux Sandbox 沙箱机制:Android将数据分为system和data两个区。其中system是只读的,dada用来存放应用自己的数据,这保证了系统数据不会被随意改写。
应用之间的数据相互独立,每个应用都会有一个user id和group id,只有相同的user id并且来自同一个作者,才能访问它们的数据。作者通过对apk签名来标识自己,签名和uid构成了双重的保证。
(2)用户权限机制:文件权限,UID,GID
(3)用户权限机制:android permission机制限制应用访问特定的资源,例如照相机、网络、外部存储等api
如何让两个app运行在同一个进程里?
- 两个app要用相同的private key来签名
- 两个app的Manifest文件中要添加一样的属性 android:sharedUserId(设置成相同的UID)
4.Binder机制
跨进程间通信(IPC):四大组件之间通过Intent互相跳转,Android实现IPC的方式是binder机制。
[android中的跨进程通信的实现(一)——远程调用过程和aidl]
[Android中的Binder机制的简要理解]
[Android中的Binder机制的简要理解二]
In the Android platform, the binder is used for nearly everything that happens accross in the core plateform.
最底层的是Android的ashmen(Anonymous shared memoryy)机制,它负责辅助实现内存的分配,以及跨进程间通信所需要的内存共享。AIDL(Android Interface Definition Language)对BInder的使用进行了封装,可以让开发者方便的进行方法的远程调用,后面会详细介绍。Intent是最高一层的抽象,方便开发者进行常用的跨进程调用。
从英文字面上意思看,Binder具有粘结剂的意思,那么它把什么东西粘结在一起呢?在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和Service Manager运行在用户区间,Binder驱动程序运行内核空间。Binder就是一种把这四个组件粘合在一起的粘结剂了,其中,核心组件便是Binder驱动了,ServiceManager提供了辅助管理的功能,Client和Server正是在Binder驱动和ServiceManager提供的基础设施上,进行Client-Server之间的通信。