2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > AsyncTask HandlerThread IntentSerivce源码解析

AsyncTask HandlerThread IntentSerivce源码解析

时间:2018-06-30 05:47:23

相关推荐

AsyncTask HandlerThread IntentSerivce源码解析

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

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//执行异步任务new WorkAsyncTask().execute();}class WorkAsyncTask extends AsyncTask<Void,Void,Void>{@Overrideprotected void onPreExecute() {super.onPreExecute();//任务开始的时候会回调 ui线程}@Overrideprotected Void doInBackground(Void... params) {//操作任务逻辑 子线程return null;}@Overrideprotected void onProgressUpdate(Void... values) {super.onProgressUpdate(values);//更新进度的时候会回调 ui线程}@Overrideprotected 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) {@Overrideprotected 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();方法就会去执行该异步任务;

@MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {//根据指定的参数去执行一个异步任务,并返回它自己,以保持对它的引用//同时execute方法的执行要在ui线程中调用return executeOnExecutor(sDefaultExecutor, params);}

@MainThreadpublic final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {if (mStatus != Status.PENDING) {switch (mStatus) {case RUNNING://不能执行异步任务,当前异步任务已经在runningthrow 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容器的末尾插入一个RunnablemTasks.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+1private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;// 闲置回收时间private static final int KEEP_ALIVE_SECONDS = 30;//异步任务队列 128private 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时就已经实例化了一个mainLoopersuper(Looper.getMainLooper());}@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg) {AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one result//在ui线程中处理异步任务的结果,更新uiresult.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;}

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

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()) {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);Log.d("jason4", Thread.currentThread().getName() + "_handleMessage");}};@Overrideprotected 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 {@Overridepublic 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");}@Overridepublic void onPreviewFrame(byte[] data, Camera camera) {if (mCamera != null) {mCamera.addCallbackBuffer(buffers);//编码Log.d("jason3", Thread.currentThread().getName() + "_onPreviewFrame");mainHandler.sendEmptyMessage(0);}}}@Overridepublic void surfaceCreated(SurfaceHolder holder) {//创建的时候回调//开启HandlerThreadcamareThread.start();//实例化一个handler 将camareThread中的looper设置给subHandlersubHandler = new Handler(camareThread.getLooper());subHandler.post(new CamareRunnable());}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {//改变的时候回调}@Overridepublic 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()方法开启一个线程;

@Overridepublic void run() {//获取当前线程idmTid = Process.myTid();//实例化一个LooperLooper.prepare();synchronized (this) {//获取实例化好的looper并赋值给mLoopermLooper = 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);}@Overrideprotected void onHandleIntent(Intent intent) {//onHandleIntent方法的回调是在子线程中}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);}@Overridepublic 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类型的字符串,该字符串用于子线程中,不过仅用于debuggingmName = name;}

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

@Overridepublic 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();//实例化一个HandlerThreadHandlerThread thread = new HandlerThread("IntentService[" + mName + "]");//开启子线程thread.start();//获取HandlerThread中实例化好的LoopermServiceLooper = thread.getLooper();//实例化一个Handler,并将HandlerThread中的Looper作为参数传入,所以ServiceHandler所在的线程也是在子线程中mServiceHandler = new ServiceHandler(mServiceLooper);}

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

@Overridepublic 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);}@Overridepublic void handleMessage(Message msg) {//消息的处理也是在子线程中,所以onHandleIntent回调是在子线程中onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);}}

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

@Overridepublic void onDestroy() {mServiceLooper.quit();}

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。