美文网首页
Android异步处理技术(二)

Android异步处理技术(二)

作者: BlingBest | 来源:发表于2018-12-29 17:13 被阅读9次

AsyncQueryHandler


           AsyncQueryHandler 是用于ContentProvider上面执行异步的CRUD(Create, Read,Update,Delete)操作的工具类,CURD操作会被放到一个单独的子线程中执行,当操作结束获取到结果后,将通过消息的方式传递给调用AsyncQueryHandler的线程,通常就是主线程。AsyncQueryHandler是一个抽象类,继承自Handler,通过封装ContentResolver,HandlerThread,Handler等实现对ContentProvider的异步操作。

AsyncQueryHandler封装了如下四个方法用来操作ContentProvider,分别对应上面说到的CRUD操作。

AsyncQueryHandler的子类可以根据实际需求实现下面的回调函数,从而得到上面的CRUD操作的返回结果

IntentService

          我们知道Service的各个生命周期函数是运行在主线程的,因此它本身并不是一个异步处理技术,为了能够在Service中实现在子线程中处理耗时任务,Android 引入了一个Service的子类:IntentService,IntentService具有Service一样的生命周期,同时也提供了在后台线程中处理异步任务的机制,与HandlerThread类似,IntentService也是在一个后台线程中顺序执行所有的任务,我们通过给Context.startService传递给一个Intent类型的参数可以启动IntentService的异步执行,如果此时IntentService正在运行中,那么这个新的Intent将会进入队列进行排队,直到后台线程处理完队列前面的任务,如果此时IntentService没有在运行,那么将会启动一个新的IntentService,当后台线程队列中所有任务完成之后,IntentService将会结束它的生命周期,因此IntentService不需要开发者的手动结束。

           IntentService本身是一个抽象类,因此,使用前需要继承它并实现onHandlerIntent方法,在这个方法中实现具体的后台处理业务逻辑,同时在子类的构造方法中需要调用super(String name)传入子类的名字。

上面代码中的setIntentRedelivery方法如果设置为true,那么IntentService的onStartCommand方法将会返回START_REDELICER_INTENT,这时,如果onHandlerIntent方法返回之前进程死掉了,那么进程将会重新启动,intent将会重新投递

通过查看IntentService的源码,我们可以发现事实上IntentService是通过HanlderThread来实现后台任务的处理的

Executor Framework

我们知道,创建和销毁对象,是存在开销的,如果应用中频繁出现线程的创建和销毁,那么会影响到应用的性能,使用Java Executor 框架可以通过线程池等机制解决这个问题,改善应用的体验,Executor框架为开发者提供如下能力

1 创建工作线程池,同时通过队列来控制能够在这些线程执行的任务的个数

2 检测导致线程意外终止的错误

3 等待线程执行完成并获取执行结果

4 批量执行线程,并提供固定的顺序获取执行结果

5 在合适的时机启动后台线程,从而保证线程执行结果可以很快反馈给用户

Executor框架的基础是一个名为Executor的接口定义,Executor的主要目的是分离任务的创建和它的执行,最终实现上述所说的功能点

开发者可以通过实现Executor接口并重写execute 方法从而实现自己的Executor类,最简单的是直接在这个方法中创建一个线程来执行Runnable。

实例应用中execute方法很少是这么简单的,通常需要增加类似队列,任务优先级等功能,最终实现一个线程池,线程池是任务队列和工作队列的集合,这两者组合起来来实现生产者消费着模式,Executor框架为开发者提供了预定义的线程池实现

1 固定大小的线程池:通过Executor.newFixedThreadPool(n)创建,其中n表示线程池中线程的个数

2 可变大小的线程池:通过Executors.newCachedThreadPool()创建,当有新的任务需要执行时,线程池会创建新的线程来处理它,空闲的线程会等待60秒来执行新任务,当没有任务可执行时就自动销毁,因此可变大小线程池会根据任务队列的大小而变化

3 单个线程的线程池:通过Executor.newSingleThreadExecutor()创建,这个线程池中永远只有一个线程来穿行执行任务队列中的任务

corePoolSize:核心线程数。核心线程会一直存在与线程池中,及时当前没有任务需要处理,当线程数小于核心线程数时,及时当前有空闲的线程,线程池也会优先创建新的线程来处理任务

maximumPoolSize:最大线程数,当线程数大于核心线程数,且任务队列已经满了,这时线程池就会创建新的线程,直到线程数量达到最大线程数为止

keepAliveTime:线程的空闲存活时间,当线程的空闲时间超过这个之时,线程会被销毁,知道线程数等于核心线程数

unit :keepAliveTimes的单位,可选的有TimeUnit类中的NANOSECONDS,MICROSECONDS,MI 1LLISECONDS和SECONDS

workQueue:线程池所使用的任务缓冲队列

AsyncTack


AsyncTask 是在Executor框架基础上进行的封装,它实现将耗时任务移动到工作线程中执行,同时提供方便的接口实现工作线程和主线程的通信,使用AsyncTask一般会用到方法

其中,除了doInBackground方法是在工作线程种执行,其他的都是在主线程种执行,,在不同的Android 系统版本中,AsyncTask的表现不尽相同,在不同的系统版本中,AsyncTask的execute和executeOnExecutor方法的运行有些许差别。

        可以看到,如果使用AsyncTask执行的任务需要并行执行的话,那么在API Level大于13的版本上建议使用executorOnExecutor代替execute。

        一个应用中使用的所有AsyncTask实例会共享全局的属性,也就是说如果AsyncTask中的任务是串行执行,那么应用中所有的AsyncTask都会进行排队,只有等前面的任务执行完成之后,才会接着执行下一个AsyncTask 中的任务,在executeOnExecutor或者API Level大于13的系统上面执行execute()方法,都会是这个效果,如果AsyncTask是异步执行,那么在四核CPU系统上,最多也只有五个任务可以同时进行,其他任务需要在队列中排队,等待空闲的线程。

Loader

         Loader是Android 3.0开始引入的一个异步数据加载框架,它使得在Activity或者Fragment中异步加载数据变得很简单,同时它在数据源发生变化时,能够及时发生消息通知。Loader框架的API主要如下:

Loader:加载器框架的基类,封装了实现异步数据加载的接口,当一个加载器被激活后,它就会开始监视数据源并在数据发生改变时发生新的结果。

AsyncTaskLoader:Loader的子类,顾名思义,它是基于AsyncTask实现的异步数据加载,它是一个抽象类,子类必须实现LoadInBackground方法,在其中进行具体的数据加载操作。

CursorLoader:AsyncTaskLoader的子类,封装了对ContentResolver的query操作,实现从ContentProvider中查询数据的功能。

LoaderManager:抽象类,Activity 和Fragment默认都会关联一个LoaderManager的对象,开发者只需要通过getLoaderManager即可获取,LoaderManager是用来管理一个或者多个加载器对象的

LoaderManager.LoaderCallbacks:LoaderManager的回调接口,主要有如下三个方法

onCreateLoader():初始化并返回一个新的Loader实例

onLoaderFinished():当一个加载器完成加载过程之后会回调这个方法

onLoaderReset():当一个加载器被重置并且数据无效时会回调这个方法

总结

Android平台提供了如此多的异步处理技术,我们在进行选择时候需要根据具体的业务需求而定:

1 尽量使用更少的系统资源,例如CPU和内存等

2 为应用提供更好的性能和响应度

3 实现和使用起来不复杂

4 写出来的代码是否符合好的设计,是否易于理解和维护

相关文章

网友评论

      本文标题:Android异步处理技术(二)

      本文链接:https://www.haomeiwen.com/subject/iphplqtx.html