在进行耗时操作时,一般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;
}
这样一个异步任务就执行完毕了,从中看出:
doInBackground(mParams);方法是在子线程中执行;
onPreExecute()、onProgressUpdate()、onPostExecute()、onCancelled()等方法都是在ui线程中执行;
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()方法中可以直接进行耗时操作。