AsyncTask、HandlerThread、IntentSerivce源码解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangwo1991/article/details/80211978

在进行耗时操作时,一般new Thread().start();开启一个子线程,然后通过handler消息去更新ui(关于handler可以看这里:android Handler、Looper、Messsage、MessageQueue源码解析)或者利用AsyncTask进行耗时操作;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //执行异步任务
        new WorkAsyncTask().execute();
    }
    class WorkAsyncTask extends AsyncTask<Void,Void,Void>{
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //任务开始的时候会回调   ui线程
        }

        @Override
        protected Void doInBackground(Void... params) {
            //操作任务逻辑   子线程
            return null;
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
            //更新进度的时候会回调  ui线程
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            //操作完成更新ui回调 ui线程
        }
    }
}

这是一段简易的AsyncTask使用的代码,通过几个方法的重写和回调就完成了异步任务,表面上并没有看到线程之间的切换,其实AsyncTask源码中利用handler消息已经实现了线程之间的自由切换;先来看下AsyncTask的构造方法;

/**
  * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
  *创建一个新的异步任务,这个构造方法的实例化必须在ui线程中
  */
    public AsyncTask() {
	//实例化一个WorkerRunnable WorkerRunnable是一个抽闲类,implements Callable接口,所以在实例化的时候就必须重写其中的call()方法
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Result result = null;
                try {
		    //设置线程的优先级  为后台线程
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //noinspection unchecked
		    //调用doInBackground方法,进行异步任务的操作,重写其方法,进行具体逻辑,并返回结果
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
		    //调用postResult方法,该方法中会利用handler消息进行线程切换
                    postResult(result);
                }
		//将异步任务的结果返回
                return result;
            }
        };
	//实例化一个FutureTask对象并将上面实例化好的WorkerRunnable作为参数传入
	//FutureTask<V> implements RunnableFuture<V>接口,可以重写其中的run方法
        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                try {
		    //会调用postResult方法,该方法中会利用handler消息进行线程切换
                    postResultIfNotInvoked(get());
                } catch (InterruptedException e) {
                    android.util.Log.w(LOG_TAG, e);
                } catch (ExecutionException e) {
                    throw new RuntimeException("An error occurred while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }

上面就是AsyncTask的构造方法,在使用AsyncTask的时候实例化一个AsyncTask对象后调用execute();方法就会去执行该异步任务;

@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
	    //根据指定的参数去执行一个异步任务,并返回它自己,以保持对它的引用	  
            //同时execute方法的执行要在ui线程中调用
    return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
    if (mStatus != Status.PENDING) {
        switch (mStatus) {
            case RUNNING:
		//不能执行异步任务,当前异步任务已经在running
                throw new IllegalStateException("Cannot execute task:"
                        + " the task is already running.");
            case FINISHED:
		//不能执行异步任务,当前异步任务已经执行了,一个异步任务只能被执行一次
                throw new IllegalStateException("Cannot execute task:"
                        + " the task has already been executed "
                            + "(a task can be executed only once)");
        }
    }
    //执行了executeOnExecutor方法后就会将mStatus表示改为Status.RUNNING状态
    mStatus = Status.RUNNING;
    //会调用onPreExecute();方法,开始执行异步任务的时候可以重写做一些开始动作;
    //onPreExecute方法是在ui线程中调用
    onPreExecute();

    mWorker.mParams = params;
    //调用Executor中的execute去执行,并传入一个FutureTask实例
    exec.execute(mFuture);

    return this;
}

通过上面这段代码可以知道:

不能对同一个异步任务重复执行,一个异步任务只能被执行一次;

onPreExecute方法是在ui线程中调用;

在调用executeOnExecutor()方法时需要传入一个Executor对象,在实例化AsyncTask时就已经实例好一个全局的Executor了;

/**
 * An {@link Executor} that executes tasks one at a time in serial
 * order.  This serialization is global to a particular process.
 */
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static class SerialExecutor implements Executor {
	//用于存储Runnable的容器
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
	    //在Runnable容器的末尾插入一个Runnable
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
			//调用run方法
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
		//调用Executor中的execute方法
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

Executor中execute方法的调用已经是在子线程中调用了;

/**
  * An {@link Executor} that can be used to execute tasks in parallel.
  */
    public static final Executor THREAD_POOL_EXECUTOR;

    static {
	//实例化一个线程池
	//CORE_POOL_SIZE 池中保持线程的数量
	//MAXIMUM_POOL_SIZE 池中允许的最大线程数
	//KEEP_ALIVE_SECONDS 闲置回收时间,当线程数大于内核时,这是多余空闲线程在终止之前等待新任务的最大时间。
	//TimeUnit.SECONDS 时间单位
	//sPoolWorkQueue 异步任务队列
	//sThreadFactory 线程工厂
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
	//设置允许超时
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }
这是一段实例化线程池的静态代码块,下面是AsyncTask系统设置线程池的一些参数;
//获取cup数
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
//池中保持线程的数量
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
//池中允许的最大线程数 cup数*2+1
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
// 闲置回收时间
private static final int KEEP_ALIVE_SECONDS = 30;
//异步任务队列 128
private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);
//线程工厂			
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    private final AtomicInteger mCount = new AtomicInteger(1);

    public Thread newThread(Runnable r) {
	//实例化线程
        return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
    }
};
如果当前线程池中的数量小于corePoolSize,创建并添加的任务。
如果当前线程池中的数量等于corePoolSize,缓冲队列 workQueue未满,那么任务被放入缓冲队列、等待任务调度执行。
如果当前线程池中的数量大于corePoolSize,缓冲队列workQueue已满,并且线程池中的数量小于maximumPoolSize,新提交任务会创建新线程执行任务。
如果当前线程池中的数量大于corePoolSize,缓冲队列workQueue已满,并且线程池中的数量等于maximumPoolSize,新提交任务由Handler处理。
当线程池中的线程大于corePoolSize时,多余线程空闲时间超过keepAliveTime时,会关闭这部分线程。	

执行完execute()方法,完成了线程的切换,这个时候在AsyncTask构造方法中实例化WorkerRunnable后会回调其中的call()方法,在call方法中就会去调用doInBackground(mParams);方法,所以doInBackground(mParams);方法的执行是在线性程中执行,具体逻辑由子类去实现,将执行结果返回后就会去调用postResult(result);方法;

private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    //通过getHandler获取Handler实例,然后再获取Message实例
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result));
    //其实就是target.sendMessage(this); 也就是handler.sendMessage(message);
    message.sendToTarget();
    return result;
}
private static Handler getHandler() {
    synchronized (AsyncTask.class) {
        if (sHandler == null) {
            sHandler = new InternalHandler();
        }
        return sHandler;
    }
}

这个时候获得到doInBackground(mParams);中执行的结果,通过handler实现了线程的切换,并将结果进行了发送,通知ui去更新;

private static class InternalHandler extends Handler {
        public InternalHandler() {
	    //在实例化handler时就已经实例化了一个mainLooper
            super(Looper.getMainLooper());
        }

        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    // There is only one result
		    //在ui线程中处理异步任务的结果,更新ui
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:
		    //在ui线程中更新异步任务的进度
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
    }
private void finish(Result result) {
    if (isCancelled()) {
	//如果异步任务已经取消就会调用onCancelled()方法
        onCancelled(result);
    } else {
	//调用onPostExecute方法更新ui,具体逻辑由子类实现
        onPostExecute(result);
    }
    //修改异步任务执行的状态
    mStatus = Status.FINISHED;
}

这样一个异步任务就执行完毕了,从中看出:

扫描二维码关注公众号,回复: 4534041 查看本文章

doInBackground(mParams);方法是在子线程中执行;

onPreExecute()、onProgressUpdate()、onPostExecute()、onCancelled()等方法都是在ui线程中执行;

onPreExecute()、onProgressUpdate()、onPostExecute()、onCancelled()等方法在ui线程中执行的原因是在实例化handler时实例化了一个main looper;

AsyncTask就是handler+looper+线程池

AsyncTask在使用的时候并不需要去实例化handler和looper等对象,方便了不少,但是在使用的时候也需要注意:

线程池容量不够抛出异常;
内存泄露;

不过在使用的时候会发现AsyncTask这样子使用一个线程,一个异步任务,有时候并不能满足需要,这个时候可以使用HandlerThread;

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    private HandlerThread camareThread = new HandlerThread("camare_thread");
    private Handler subHandler;
    private Camera mCamera;
    private byte[] buffers;
    private Handler mainHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.d("jason4", Thread.currentThread().getName() + "_handleMessage");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        surfaceView = (SurfaceView) findViewById(R.id.surface_view);
        surfaceHolder = surfaceView.getHolder();
        //设置监听回调
        surfaceHolder.addCallback(this);
    }

    class CamareRunnable implements Runnable, Camera.PreviewCallback {

        @Override
        public void run() {
            //打开相机
            //子线程中打开
            Log.d("jason1", Thread.currentThread().getName() + "_open");
            mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
            try {
                mCamera.setPreviewDisplay(surfaceHolder);
            } catch (IOException e) {
                e.printStackTrace();
            }
            Camera.Parameters parameters = mCamera.getParameters();
            //设置相机参数
            parameters.setPreviewSize(480, 320); //预览画面宽高
            mCamera.setParameters(parameters);
            //获取预览图像数据
            buffers = new byte[480 * 320 * 4];
            mCamera.addCallbackBuffer(buffers);
            mCamera.setPreviewCallbackWithBuffer(this);
            mCamera.startPreview();
            Log.d("jason2", Thread.currentThread().getName() + "_run");
        }

        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            if (mCamera != null) {
                mCamera.addCallbackBuffer(buffers);
                //编码
                Log.d("jason3", Thread.currentThread().getName() + "_onPreviewFrame");
                mainHandler.sendEmptyMessage(0);
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //创建的时候回调
        //开启HandlerThread
        camareThread.start();
        //实例化一个handler 将camareThread中的looper设置给subHandler
        subHandler = new Handler(camareThread.getLooper());
        subHandler.post(new CamareRunnable());
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        //改变的时候回调
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        //销毁的时候回调
    }
}

这是一段简易的开启相机和预览的代码,运行发现jason1、jason2、jason3所打印的都是子线程,只有jason4打印的是主线程;这样子就能一个线程多个任务了;那为什么HandlerThread就可以呢?

/**
 * Handy class for starting a new thread that has a looper. The looper can then be 
 * used to create handler classes. Note that start() must still be called.
 */

这个是HandlerThread的注释,开启一个线程已经拥有一个Looper,这个Looper可以用来创建一个Handler

所有可以将HandlerThread看作是Thread+Looper;确实HandlerThread 是继承Thread的;

public class HandlerThread extends Thread 
public HandlerThread(String name) {
        super(name);
		//name 是指定创建的HandlerThread实例的名称
		//线程的优先级 一个默认的优先级
		//最终调用下面那个两个参数的构造方法进行实例化
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }

实例化完毕后调用start()方法开启一个线程;

    
@Override
    public void run() {
	//获取当前线程id
        mTid = Process.myTid();
	//实例化一个Looper
        Looper.prepare();
        synchronized (this) {
	    //获取实例化好的looper并赋值给mLooper
            mLooper = Looper.myLooper();
            notifyAll();
        }
	//设置线程的优先级
        Process.setThreadPriority(mPriority);
	//这个方法可以根据自己的需要去重写,如果想在Looper.loop();之前做一些事情,就可以重写onLooperPrepared();
        onLooperPrepared();
	//开始轮询
        Looper.loop();
        mTid = -1;
    }

还提供了quit()、getLooper()等方法,其实HandlerThread的源码并不多;

接下来稍微说下IntentService

public class MyIntentService extends IntentService{
    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public MyIntentService(String name) {
        super(name);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        //onHandleIntent方法的回调是在子线程中
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

IntentService extends Service就是一个Service,但是有不同于其他的Service,其实IntentService就是HandlerThread+Looper+Service;

/**
  * Creates an IntentService.  Invoked by your subclass's constructor.
  *
  * @param name Used to name the worker thread, important only for debugging.
  */
public IntentService(String name) {
    super();
	//和其他的Service不一样,实例化需要传入一个String类型的字符串,该字符串用于子线程中,不过仅用于debugging
    mName = name;
}

开启一个Service后,就会根据需要去重写onCreate()、onStart()、onStartCommand()等方法;

    @Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
	//实例化一个HandlerThread
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
	//开启子线程
        thread.start();
	//获取HandlerThread中实例化好的Looper
        mServiceLooper = thread.getLooper();
	//实例化一个Handler,并将HandlerThread中的Looper作为参数传入,所以ServiceHandler所在的线程也是在子线程中
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

onStartCommand()方法话还是调用的是onStart()方法;

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
	//在onStart方法中主要就是通过handler发送了一个消息,不过该消息的发送是在子线程中发送的
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

根据handler发送的消息会在ServiceHandler内部类中进行处理;

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);
        }
    }

在onDestory的时候会将Looper移除掉;

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }
其实IntentService的作用就是在开启一个服务的时候,刚好如果有耗时操作时,不需要自己开启一个线程或者异步任务去执行该耗时操作,使用IntentService的onHandleIntent()方法中可以直接进行耗时操作。


猜你喜欢

转载自blog.csdn.net/wangwo1991/article/details/80211978