Android中线程的不同形态(Thread、AsyncTask、HandlerThread、IntentService)

线程作为CPU最小调度单位,使我们开发中进程需要用到的功能。在Android中,除了java原本就提供的Thread以外,还提供了其他形式的线程,如AsyncTask、IntentService、HandlerThread, 它们的底层还是都封装的Thread,但却提供了更加丰富的功能。所以在Android中,常用的线程的形态有:

  • 1、Thread;
  • 2、AsyncTask;
  • 3、IntentService;
  • 4、HandlerThread;

1、AsyncTask

AsyncTask的底层其实用到了线程池,它并不适合进行特别耗时的后台任务,如果有耗时较长的任务,建议使用线程池。原因就在于AsyncTask的任务默认是串行执行的,如果前面的任务很耗时,则后面的任务长期都得不到执行。AsyncTask的源码分析将放到下一篇博客中来进行,本篇先讲它的使用。

核心方法:

  • excute: 创建好AsyncTask对象后,需要调用此方法才开始执行任务;
  • onPreExecute:在主线程中执行,在异步任务执行之前执行,可以做一些准备工作;
  • doInBackground:在线程池中执行,执行具体的异步任务。在这个方法中可以调用publishProgress方法来更新任务的进度;
  • onProgressUpdate:在主线程中执行,调用publishProgress方法后会被调用;
  • onPostExecute:在主线程中执行,异步任务执行完毕后会被调用,返回执行结果;
  • onCancelled:在主线程中执行,异步任务被取消时会被调用,这样onPostExecute方法将不会被调用;

以上方法中,只有doInBackground方法是在线程池中去执行的,毕竟耗时操作也是在这个方法中去完成的。

示例代码如下:

private class MyTask extends AsyncTask<Params, Progress, Result> {

    ....

  // 作用:执行 线程任务前的操作
  @Override
  protected void onPreExecute() {
       ...
    }

  // 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
  @Override
  protected String doInBackground(String... params) {
        ...
        // 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
         publishProgress(count);     
     }

  // 作用:在主线程 显示线程任务执行的进度
  @Override
  protected void onProgressUpdate(Integer... progresses) {
        ...
    }

  // 作用:接收线程任务执行结果、将执行结果显示到UI组件
  @Override
  protected void onPostExecute(String result) {

     ...// UI操作

    }

  // 作用:将异步任务设置为:取消状态
  @Override
    protected void onCancelled() {
    ...
    }
}

  MyTask mTask = new MyTask();
  mTask.execute();

使用AsyncTask有几个点需要特别注意:

  • 1、AsyncTask的类必须在主线程中被加载,即第一次访问AsyncTask这个类必须在主线程中进行,这一点在Android4.1及以上版本,已由系统本身完成,在ActivityThread的main方法调用了AsyncTask的init方法,从而完成了类加载;
  • 2、AsyncTask对象必须在主线程中创建;
  • 3、execute方法必须在主线程中调用;
  • 4、以上方法除了execute和onCancelled方法,其他方法不要在代码中主动去调用,这个Android内部已经封装好了,有一套完整的调用机制,我们只需要重写这几个方法即可;
  • 5、一个AsyncTask对象只能调用一次execute方法。否则会报错;

2、HandlerThread

HandlerThread继承自Thread,它的实现很简单,就是在内部封装了Handler以及创建了对应的Looper对象,从而可以像主线程一样使用Handler消息机制来处理多个任务,它的源码如下:

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

    //构造方法需要传入线程的名字
    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    //用来重写,在开启消息循环之前被调用
    protected void onLooperPrepared() {
    }

    //主要的地方在这个run方法
    @Override
    public void run() {
        mTid = Process.myTid();
        //创建消息队列
        Looper.prepare();//在run方法的开始,创建Looper对象和MessageQueue
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        //开启消息循环
        Looper.loop();//在run方法的末尾,开启消息循环
        mTid = -1;
    }
    
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    //用于停止消息循环
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }
    //用于停止消息循环
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    public int getThreadId() {
        return mTid;
    }
}

所以,如果我们要想在一个子线程中简单的去使用Handler消息机制,直接使用此类即可,就不需要自己另行封装了。HandlerThread在源码中的一个使用场景就是IntentService,下面将讲到。

3、IntentService

  • IntentService 是一个抽象类,所以必须创建它的子类才能使用IntentService
  • IntentService继承自Service,因此是一种特殊的服务,优先级比普通的后台线程要高,不容易被回收,适合执行一些高优先级的后台任务
  • IntentService封装了HandlerThread和Handler

源码入下:

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

    //自定义的Handler,这样可以把收到的任务消息发送给HandlerThread处理
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            //onHandleIntent处理具体的任务,运行在HandlerThread中
            onHandleIntent((Intent)msg.obj);
            //任务执行完毕会自动结束
            stopSelf(msg.arg1);
        }
    }

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

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

    //第一次启动时会调用onCreate
    @Override
    public void onCreate() {
        super.onCreate();
        //创建HandlerThread
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        //调用HandlerThread的run方法,开启HandlerThread的消息循环,以便接收消息处理具体的任务
        thread.start();
        
        //获取HandlerThread的looper,创建ServiceHandler,这样通过ServiceHandler发送的消息最后都会在HandlerThread中处理
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        //每次调用IntentService都会执行onStartCommand方法,发送一个任务消息给HandlerThread处理,任务的信息通过Intent传递
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

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

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

    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}
  • IntentService通过Intent来传递任务参数,当任务执行完毕时会调用stopSelf(int startId)自己停止服务;
  • IntentService的onHandleIntent是一个抽象方法,需要我们自己实现,用于处理具体的任务;
  • 每执行一个后台任务就需要启动一次IntentService,IntentService内部通过消息的方式向HanderThread请求执行任务,Handler的Looper是顺序执行任务的,所以IntentService也是顺序执行后台任务的,因为Handler消息机制本身就只能串行的去执行任务;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值