Anroid异步处理
移动开发要求我们正确处理好主线程和子线程之间的关系,耗时操作放到子线程中
而异步处理技术是提高应用性能,解决主线程和子线程之间通信的关键
异步处理技术很多种,下图为完整的继承树
可以看到Thread是异步处理技术的基础
创建现场有两种方法,一种继承Thread并重写run方法
一种实现Runnable
一般来讲Android应用层都基于liunx的pthreads
应用层可以分为三种类型的线程
- 主线程,即UI线程,若是在其他线程中更新UI,则会报错,抛出
CalledFromWrongThreadException
- Binder线程,这个线程用于不同进程之间线程的通信,每个进程都维护了一个线程池,用来处理其他进程中线程发送的消息,进程包括系统服务,Intents,ContentProviders和Service;典型应用场景是应用提供一个给其他进程通过AIDL接口绑定的Service
- 后台进程
HandlerThread
HandlerThread是一个集成了Looper和MessageQueue的线程,当启动他时会自动生成Looper和MessageQueue,然后等待消息进行处理
run方法源码
@override
public void run(){
mTid=Process.myTid();
Looper.prepare();
synchronized(this){
mLooper=Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid=-1;
}
HandlerThread中只有一个消息队列,队列中的消息是顺序执行的,因此是线程安全的,吞吐量会收到一定的影响,队列中的任务可能会被前面未执行完的任务阻塞。
HandlerThread的内部机制确保了在创建Looper和发送消息之间不存在竞争关系,这个是通过HandlerThread.getLooper()实现为一个阻塞操作实现的。
AsyncQueryHandler
这是用于ContentProvider上面执行异步的CRUD操作的工具类,CRUD操作会被放到一个单独的子线程中执行,当操作结束获取到消息后,将通过消息的方式传递给调用AsyncQueryHandler的线程,也就是主线程
AsyncQueryHandler是一个抽象类,继承自Handler,通过封装ContentResolver、HandlerThread、Handler等实现对ContentProvider的异步操作
IntentService
由于Service的各个生命周期函数是运行在主线程的,本身不带异步处理技术
Android引入了IntentService,IntentService是Service的子类,具有一样的生命周期,不过它提供了在后台线程中处理异步任务的机制
它是在后台线程中顺序执行所有任务,通过给Context.startService传递一个Intent类型的参数可以启动IntentService的异步执行,如果此时IntentService正在运行中,那个这么新的Intent将会进入消息队列中进行排队等待前面任务的执行完成后才能执行,若此时没有IntentService在运行,那将会启动一个新的IntentService。
当后台线程队列中所有任务均被处理完后,IntentService将会结束它的生命周期,因此我们不需手动结束IntentService
Executor Framework
它为我们提供了这些功能
- 创建工作线程池,同时通过队列来控制能够在这些线程执行的任务的个数
- 检测导致线程意外终止的错误
- 等待线程执行完成并获取执行结果
- 批量执行线程,并通过固定的顺序获取执行结果
- 在合适的时机启动后台线程,从而保证线程执行结果可以很快反馈给用户
AsyncTask
AsyncTask是在Executor框架基础上进行的封装,实现将耗时任务移动到工作线程中执行即doInBackground方法
,同时提供方便的接口实现工作线程和主线程的通信如onPostExecute方法与onProgressUpdate方法
若是异步处理,则最大核心线程数为系统CPU核数+1,这是由AsyncTask中的ThreadPoolExecutor指定的
Loader
Loader是Android3.0开始引入的一个异步数据加载框架,使得Activity或Fragment异步加载数据变得很简单,并且当数据源发生变化时,他能够及时发出消息通知
它所涉及的api:
-
Loader:加载器框架的基类,当一个加载器被激活后,他就会开始监视数据源并在数据发生变化时发送新的结果
-
AsyncTaskLoader:Loader的子类,是基于AsyncTask实现的异步数据加载类,是一个抽象类,其子类必须实现
loadInBackground
,在其中进行具体数据加载操作 -
CursorLoader:AsyncTaskLoader的子类,封装了对ContentResolver的query操作,实现从ContentProvider中查询数据的功能
-
LoaderManager:抽象类,Activity和Fragment默认会关联一个LoaderManager的对象,我们只需要通过getLoaderManager即可获取,LoaderManager是用来管理一个或多个加载其对象的
-
LoaderManager.LoaderCallbacks:LoaderManager的回调接口,主要有三个方法
① onCreateLoader():初始化并返回一个新的Loader实例
② onLoadFinished():当一个加载器完成加载过程之后会回调这个方法
③ onLoaderReset():当一个加载器被重置并且数据无效时会回调这个方法
例子
package com.example.load;
import android.app.ListActivity;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.SimpleCursorAdapter;
/**
* Created by 王小俊 on 2017/5/9.
*/
public class ContactActivity extends ListActivity
implements LoaderManager.LoaderCallbacks<Cursor>{
private static final int CONTACT_NAME_LOADER_ID=0;
static final String[] CONTACTS_SUMMARY_PROJECTION =new String[]{
ContactsContract.Contacts._ID,ContactsContract.Contacts.DISPLAY_NAME
};
SimpleCursorAdapter mAdapter;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
initAdapter();
getLoaderManager().initLoader(CONTACT_NAME_LOADER_ID,null,this);
}
private void initAdapter(){
mAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, null,
new String[]{ContactsContract.Contacts.DISPLAY_NAME},
new int[]{android.R.id.text1}, 0);
setListAdapter(mAdapter);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(this, ContactsContract.Contacts.CONTENT_URI,
CONTACTS_SUMMARY_PROJECTION, null, null,
ContactsContract.Contacts.DISPLAY_NAME + "ASC");
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}
小结
在具体使用需考虑以下因素
- 尽量使用更少的系统资源,例如CPU和内存
- 为应用提供更好的性能和相应度
- 实现和使用不复杂
- 写出的代码是否符合好的设计,是否易于理解和维护