Android 中的 HandlerThread 和 IntentService

栏目: Android · 发布时间: 5年前

内容简介:本篇介绍 HandlerThread 和 IntentService 相关概念。从 handlerThread 的实现来看它和普通的 Thread 有着显著的不同,普通的 Thread 中的 run() 方法都是在执行一个耗时任务,而 HandlerThread 的 run() 方法中却创建了消息队列,外界需要通过 handler 的消息方式来通知 HandlerThread 来执行一个具体的任务。如果你想看一个实例以及源码解析可以看HandlerThread可以创建一个带有looper的线程。looper

本篇介绍 HandlerThread 和 IntentService 相关概念。

  • HandlerThread 是什么?能做什么?与 Handler 和 Thread 是何种关系?
  • IntentService 是什么?与 Service 是何种关系?是线程吗?与线程何种关系?有什么优点?

HandlerThread

从 handlerThread 的实现来看它和普通的 Thread 有着显著的不同,普通的 Thread 中的 run() 方法都是在执行一个耗时任务,而 HandlerThread 的 run() 方法中却创建了消息队列,外界需要通过 handler 的消息方式来通知 HandlerThread 来执行一个具体的任务。如果你想看一个实例以及源码解析可以看 彻底了解 HandlerThread

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

HandlerThread可以创建一个带有looper的线程。looper对象可以用于创建Handler类来进行来进行调度。看看其基本用法是怎样:

HandlerThread thread = newHandlerThread("handler_thread");
thread.start();//必须要调用start方法
final Handler handler = newHandler(thread.getLooper()){}

如上所示,就可以很轻松的创建Handler对象了。

IntentService

之前我们有情况需要在 Service 进行一些后台的耗时操作,但是又不能直接在 Service 中进行,此时会选择在 Service 中再开一个线程,但是这样不够优雅,因为我们需要自己去管理 Service 的生命周期以及子线程。

IntentService 是一种特殊的服务(封装了 HandlerThread 和 Handler),继承与 Service 并且是一个抽象类。并且由于它是服务的原因导致他的优先级比单纯的线程高很多。IntentService 适用于高优先级的 Service(不容易被杀死)。IntentService 封装了 Handler 和 HandlerThread。你可以通过 startService(Intent) 来提交请求,该 Service会在需要的时候创建,当完成所有的任务以后自己关闭,且请求是在工作线程处理的。

按照鸿洋博客上面的例子,写出 Demo 可以看文章结束处链接(实际 Demo 不要忘了注册服务),主要效果就是模拟耗时的上传操作,并且用广播在 Service 与 Activity 之间通信。

public class UploadImgService extends IntentService
{
    private static final String ACTION_UPLOAD_IMG = "com.zhy.blogcodes.intentservice.action.UPLOAD_IMAGE";
  
    // 复写 onHandleIntent 根据传入的 intent 来选择具体的操作
    @Override
    protected void onHandleIntent(Intent intent)
    {
        if (intent != null)
        {
            final String action = intent.getAction();
            if (ACTION_UPLOAD_IMG.equals(action))
            {
                final String path = intent.getStringExtra(EXTRA_IMG_PATH);
              	// 耗时操作
                handleUploadImg(path);
            }
        }
    }
  
    @Override
    public void onCreate()
    {
        super.onCreate();
        Log.e("TAG","onCreate");
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        Log.e("TAG","onDestroy");
    }
}

我们对上面代码进行分析:onHandleIntent 方法会从参数中解析出具体的后台任务标识,然后根据不同的标识来执行具体的任务。而我们通过实验可知,发起多个任务之后,任务在后台是排队执行的,并且在最后一个任务执行完毕之后,IntentService 才真正的停止。

分析 IntentService 的源码如下:

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
          	// 回调 onHandleIntent()
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
                super.onCreate();
      	// 初始化 HandlerThread
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
      	// Handler 发送消息
        mServiceHandler.sendMessage(msg);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
      	// 回调 onStart()
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

	// 抽象方法
    protected abstract void onHandleIntent(Intent intent);
}

注意下:回调完成后回调用 stopSelf(msg.arg1),注意这个 msg.arg1 是个 int 值,相当于一个请求的唯一标识。每发送一个请求,会生成一个唯一的标识,然后将请求放入队列,当全部执行完成(最后一个请求也就相当于getLastStartId == startId),或者当前发送的标识是最近发出的那一个(getLastStartId == startId),则会销毁我们的Service.很简单的道理如果我们使用 stopSelf() 的话,会立即停止服务,这时候可能还会有其他的消息没有处理,如果传入的是 -1 则直接销毁。

那么,当任务完成销毁 Service 回调 onDestory,可以看到在 onDestroy 中释放了我们的Looper:mServiceLooper.quit()。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Agile Web Development with Rails, Third Edition

Agile Web Development with Rails, Third Edition

Sam Ruby、Dave Thomas、David Heinemeier Hansson / Pragmatic Bookshelf / 2009-03-17 / USD 43.95

Rails just keeps on changing. Rails 2, released in 2008, brings hundreds of improvements, including new support for RESTful applications, new generator options, and so on. And, as importantly, we’ve a......一起来看看 《Agile Web Development with Rails, Third Edition》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

html转js在线工具
html转js在线工具

html转js在线工具