Android常用异步任务执行方法

2017-06-06  本文已影响0人  redspider110

Handler原理及基本概念

每个 Thread 只对应一个 Looper  
每个 Looper 只对应一个 MessageQueue
每个 MessageQueue 中有 N 个 Message
每个 Message 最多指定一个 Handler 来处理事件
每个 Thread 可以对应多个 Handler

在如下操作中都是基于UI主线程,在异步任务中使用Handler机制更新UI必须用new Handler();来初始化。

// 默认使用UI主线程的Looper
Handler mHandler = new Handler();
mHandler.post(new Runnable(){});

Thread创建与销毁

在Android开发中经常会使用到线程,一想到线程,很多同学就立即使用
new Thread(){...}.start();这样的方式。这样如果在一个Activity中多次调用上面的代码,那么将创建多个匿名线程,程序运行的越久可能会越来越慢。因此,需要一个Handler来启动一个线程,以及删除一个线程。
保证线程不会重复的创建。

使用HandlerThread和Handler配合实现异步后台任务

特点

代码示例:

// UI线程的Handler
Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        // 处理UI更新
};

HandlerThread mBackThread = new HandlerThread("mybackthread");
mBackThread.start();
// 后台线程的Handler
Handler mBackHandler = new Handler(mBackThread.getLooper());
mBackHandler.post(new Runnable() {
    @Override
    public void run() {
        // 后台线程执行耗时操作,异步
        ...
        // mHandler发消息,回到主线程更新UI
        mHandler.sendMessage(msg);
    }
});

注意mBackHandler的初始化必须在mBackThread.start();之后,否则拿不到这个线程的looper。
这种模式通过mBackHandler.post(new Runnable() {})来实现后台异步任务执行,所有后台任务都是通过HandlerThread这个线程执行的,但是HandlerThread是串行执行任务的,也就是每次post后进入队列排队执行。
HandlerThread的退出:

@Override
protected void onDestroy() {
    super.onDestroy();
    if(mBackThread != null){
        mBackThread.quitSafely();
        try {
            mBackThread.join();
            mBackThread = null;
            mBackHandler = null;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

AsyncTask实现异步任务执行

查看源码AsyncTask只是对Thread和Handler的一个封装。

基本概念

注意事项

代码示例

// 初始化AsyncTask及执行
protected void function() {
    ...
    // 串行执行,识别一张bitmap,每次执行前都需要重新new一个对象
    mClassifierAsyncTask = new ClassifierAsyncTask();    
    mClassifierAsyncTask.execute(bitmap);
}

// 自定义AsyncTask任务类,实现doInBackground
private ClassifierAsyncTask mClassifierAsyncTask;
private class ClassifierAsyncTask extends AsyncTask<Bitmap , Void, String >{

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mTvResult.setText(getString(R.string.classifying));
    }

    @Override
    protected String doInBackground(Bitmap... bitmaps) {
        if(mMyTfClassifier == null) {
            mMyTfClassifier = new MyTfClassifier(MainActivity.this);
        }
        String result = mMyTfClassifier.recognizeImage(bitmaps[0]);
        return result;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        mTvResult.setText(result);
    }
}

存在的问题

Activity屏幕旋转或销毁时,如果AsyncTask没有执行完毕就会存在内存泄露。特别是屏幕旋转时AsyncTask没有执行完毕,会导致屏幕异常。

上一篇 下一篇

猜你喜欢

热点阅读