Handler、AsyncTask、HandlerThread和IntentService之间的对比

耗时操作的几种操作方式

Thread Handler Looper MessageQueue

创建handler时会创建looer对象并用looper中的messageQueue对象初始化当前messageQueue当使用handler发送消息时会有两种方式发送:sendMessage和dispatchMessage
前者发送的消息会直接发送至messageQueue中通过looper对象循环处理并将结果转发至handler的handleMessage方法中经过了线程之间的切换
后者则通过判断是否存在Runnable接口回调来选择返回信息的方式存在的话则直接调用Runnable中的run方法,若不存在则直接调用handler中的handMessage方法,在同一线程完成

在主线程使用
在主线程创建handler对象并其修饰为static类型,覆写handleMessage方法对收到的message对象进行处理,从打印信息可以发现当前线程为main线程即主线程,其中的looper对象是在ActivityThread.main中创建的
handler 使用示例:

public static Handler handler = new Handler() { 
        @Override   
        public void handleMessage(Message msg) {   
            switch (msg.what) {   
                case 10001:   
                    Log.d("main", msg.obj + "" + Looper.myLooper().getThread().getName());   
            }  
        }
    };

thread使用:

new Thread(new Runnable() {
        @Override
        public void run() {
            Message message = handler.obtainMessage();
            message.what = 10001;
            message.obj = "hello";
            handler.dispatchMessage(message);
        }
    }).start();

在thread线程中使用handler对象时参考Lopper源码中的示例:

private class LopperThread extends Thread {
        private Handler mHandler;

        @Override
        public void run() {
            super.run();
            Looper.prepare();
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case 10001:
                            Log.d("main", msg.obj + "" + Looper.myLooper().getThread().getName());
                    }
                }
            };
            Message message = mHandler.obtainMessage();
            message.what = 10001;
            message.obj = "hello";
            mHandler.sendMessage(message);
            Looper.loop();
        }
    }

使用方法为:

LopperThread thread = new LopperThread();
thread.start();

AsyncTask

asynctask的创建:

public class MyTestTask extends AsyncTask<Integer, Integer, String> {

    private static final String TAG = MyTestTask.class.getSimpleName();

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.i(TAG, "onPreExecute->运行前,主线程)" + Looper.myLooper().getThread().getName());
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Log.i("TAG", "onPostExecute->运行后,主线程" + Looper.myLooper().getThread().getName());
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        Log.i("TAG", "onProgressUpdate->更新进度,主线程" + Looper.myLooper().getThread().getName());
    }

    @Override
    protected String doInBackground(Integer... params) {
        Log.i(TAG, "doInBackground->运行中,子线程");
        for (int i = 0; i < 10; i++) {
            publishProgress(i);
        }
        return "finish";
    }
}

其中三个泛型的参数分别为:
Params(传入doInBackground方法中的参数)
Progress(onProgressUpdate方法中更新进度的参数)
Result(后台执行完成后的返回参数)

使用:

for (int i = 0; i < 128; i++) {
    new MyTestTask().execute();
}

使用须知:AsyncTask
3.0之前为并发执行最大并发数两位128(参见2.3.7源码MAXIMUM_POOL_SIZE = 128),当并发数量大于128时会报异常
3.0之后AsyncTask变为顺序执行,当上一个任务完成后才会执行下一个任务,顺序执行
参考链接

HandlerThread

handlerthread继承自Thread所以本来就是线程,只是在线程的run方法中添加了looper循环来实现耗时操作,在使用时先调用start方法开启线程然后通过mHandlerThread.getLooper()的方法获取handlerThread中的looper对象和新创建的hanlder对象进行绑定即通过以下方法初始化新建的handler:

public Handler(Looper looper) {
     this(looper, null, false);
}

在handler初始化后即和handlerthread完成绑定,需注意的是耗时操作需在新建的handler的handleMessage方法中进行

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

通过Looper.prepare()和 Looper.loop()实现了looper循环使用方法:

初始化:
HandlerThread mHandlerThread = new HandlerThread("myHandlerThread");
mHandlerThread.start();
Handler mHandler = new Handler(mHandlerThread.getLooper()) {
      @Override
      public void handleMessage(Message msg) {
      //耗时操作
      do something....
           Log.i("tag", "message_obj:" + msg.obj.toString());
      }
};

发送Message:
Message msg = new Message();
msg.obj = "message_obj";
mHandler.sendMessage(msg);

参考链接

IntentService

IntentService在onCreate时使用HandlerService对ServiceHandler进行了绑定,在ServiceHandler的handleMessage方法中调用了抽象方法onHandleIntent进行耗时操作,所以在IntentService的onHandleIntent方法中可以进行耗时操作,在onHandleIntent调用后还调用了stopSelf方法结束自己,所以IntentService当执行完耗时操作后会自动销毁

代码示例:

public class TestIntentService extends IntentService {
    private static String TAG = "IntentServiceLoad";

    public TestIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        //耗时操作
        // TODO: 2018/1/25 do something...
        Log.d(TAG, "onHandleIntent");
    }
}

使用方法和service相同就不举例说明了,在应用中一般会用来下载文件

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,475评论 4 372
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,744评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,101评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,732评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,141评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,049评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,188评论 2 320
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,965评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,716评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,867评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,341评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,663评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,376评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,200评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,990评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,179评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,979评论 2 279

推荐阅读更多精彩内容