线程只是最基本的应用,在复杂的场景下使用Thread代码可读性会变的很多差而且也容易出错。 android为了简化开发者的工作量,提供了一些更容易使用的封装。
HandlerThread
为了让Handler在非主线程工作,可以使用HandlerThread。 如题使用如下:
Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); HandlerThread handlerThread = new HandlerThread("backThread",Process.THREAD_PRIORITY_BACKGROUND); handlerThread.start(); handler = new Handler(handlerThread.getLooper()); }复制代码
使用HandlerThread的Looper之后,Handler就是在HandlerThread所在线程中处理消息了。 其实HandlerThread就是新建了线程,然后调用了Looper.prepare();
和Looper.loop();
AsyncTask
AsyncTask 现在使用的人已经不多了,它也是一个使用很简单的后台任务类,开发者不需要关注Thread和Handler就能在后台线程完成轻量级和时间较短的任务,并且最后在UI线程更新。
/*第一个为入参类型 *第二个是进度类型 *第三个是结果类型private class DownloadFilesTask extends AsyncTask{ protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }复制代码
下面可以看方法在哪个线程调用 :
@WorkerThread protected abstract Result doInBackground(Params... params); @MainThread protected void onPreExecute() { } @MainThread protected void onPostExecute(Result result) { } @MainThread protected void onProgressUpdate(Progress... values) { }复制代码
其实AsyncTask有一个包含一个静态的线程池,最小同时运行两个线程,最多4个线程。
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)); private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final int KEEP_ALIVE_SECONDS = 30; 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()); } }; private static final BlockingQueuesPoolWorkQueue = new LinkedBlockingQueue (128); /** * An { @link Executor} that can be used to execute tasks in parallel. */ public static final Executor THREAD_POOL_EXECUTOR; static { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); threadPoolExecutor.allowCoreThreadTimeOut(true); THREAD_POOL_EXECUTOR = threadPoolExecutor; }复制代码
其中还有一个handler用于更新UI线程。
private static Handler getMainHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(Looper.getMainLooper()); } return sHandler; } } private Handler getHandler() { return mHandler; }复制代码
由于都是静态的,所以其实所有的AsyncTask都是公用这个线程池和Handler。 AsyncTask使用起来也很简单,但是有一些限制,只能在UI线程实例化和调用。
new DownloadFilesTask().execute(url1,url2,url3);复制代码
IntentService
IntentService
是为了处理异步任务而对Service
的封装。 其实原理也很简单。
private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } } @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 thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); 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); }复制代码
就是在Service的OnCreate里创建了一个HandlerThread,然后把需要处理的Intent发送到这个Handler在后台线程中处理并且完毕后调用stopSelf关闭服务。
使用上和Service一样,就是需要重写onHandleIntent
方法。