您的位置:首页 > 移动开发 > Android开发

Android中异步加载方案

2016-03-19 21:34 477 查看

概述

避免在UI线程中进行耗时任务,这应该是我们开发者的共识。因为在主线程进行耗时任务,会造成UI线程卡顿,带来不好的用户体验。更严重者则会出现ANR。所以我们应该尽量把耗时操作放在后台进行,比如 文件的IO操作对数据库的SQL操作和对网络的访问复杂的计算逻辑

异步操作一般都涉及一下几个问题:

1. 使用什么来进行异步,即创建什么样的工具

2. 如何创建异步任务,即怎么样发送到该工具中

3. 该工具如何将返回值返回给用户

可以执行异步任务的类总结:demo在gittub上戳我

1. HandlerThread

Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.


HandlerThread是frameWork为我们提供的一个具有Looper的子线程,可以使用该线程的handler。该处理方式适用于小型的项目,对并发要求不大的。因为它只维持一个Thread,一次只能运行一个任务。

类中代码:

//将任务提交到队列中
public void post(Runnable command) {
getHandler().post(command);
}

//将任务放在队列首部,赶紧执行。适合于读取时候。
public void postAtFrontOfQueue(Runnable command) {
getHandler().postAtFrontOfQueue(command);
}

//延迟一点时间执行该任务。
public void postDelayed(Runnable command, long delayMillis) {
getHandler().postDelayed(command, delayMillis);
}

//在指定时间开始执行。
public void postAtTime(Runnable command, long delayMillis) {
getHandler().postAtTime(command, delayMillis);
}

//退出该WorkThread.
public void quit() {
if (Build.VERSION.SDK_INT >= 18) {
getWorkThread().quitSafely();
} else {
getWorkThread().quit();
}
}


更多封装移步: TinyTaskManager.java

2. IntentService

The IntentService class provides a straightforward structure for running an operation on a single background thread.

使用IntentService执行后台任务,在一般用来初始化字典数据,下载一些文件等。它运行在子线程中,并且以Service形式存在,会提高进程的优先级,不容易被系统清理。

3. ThreadPoolExecutor

可参考上篇线程池

在Android中使用ThreadPoolExecutor,根据项目对异步任务使用多少来自己创建。可以参考一大神的github lite-async

4. Loaders

使用LoaderManager异步加载数据库

官方文档Loaders

AsyncTasLoader不进行加载操作的原因及解决方法(太坑了)

A CursorLoader to load data backed by a ContentProvider.
如果使用CursorLoader,就必要使用ContentProvider作为其支持。

Alternatively, you can implement your own subclass of Loader or AsyncTaskLoader to load data from some other source.
当然,也可以继承Loader或者AsyncTaskLoader来实现自己的异步加载类。


查看AsyncTaskLoader源码,发现其底层使用的是AsyncTask。╮(╯▽╰)╭。

the given LoaderManager.LoaderCallbacks implementation is associated with the loader, and will be called when the loader state changes.
If at the point of this call the caller is in its started state, and the requested loader already exists and has generated its data, then the system calls onLoadFinished() immediately (during initLoader()),
so you must be prepared for this to happen. See onLoadFinished for more discussion of this callback


在第二次调用init()时候,要注意他会直接调用onLoadFinished()方法。you should prepared for it。(好难用!!!)

5. Thread + Handler

这种方式就很简单,直接new Thread().start(),再使用UI线程的handler对象发回UI线程中。

值得注意的是,Android中大多数类都持有Handler对象,大可不必自己创建Handler对象。比如在Activity中直接使用runOnUiThread(),自定义控件时候使用post()方法等。

6. AsyncTask

详细用法请看:AsyncTask-Sample

实用中比较很少用AsyncTask,串行处理任务,核心线程大于一个时,也只能等待该任务完成再完成下一个,会造成线程资源的浪费,感觉不是很实用。

加强理解图:



7.RxAndroid

RxAndroid使得线程的调度变得很简单,现在还未深入学习,之后学完后再添加进来。

异步时要注意Activity的生命周期

当异步执行完成了,Activity却退出了前台,或者已经结束,如果异步完成时要操作UI,那么这种情况下肯定会报错,具体的错误取决于场景。这个问题的解法就是在异步操作完成后要用Activity.isFinishing()来判断下Activity是否还是alive的。

即使异步操作中不涉及UI,那么当Activity转入后台,或者退出时,也要及时的终止工作线程,否则也会造成Activity的对象无法及时销毁而最终导致内存泄露。

参考:

关于Android中工作者线程的思考

官方文档: Best Practices for Background Jobs

Android异步指南
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: