在以下操做中都是基于UI主线程,在异步任务中使用Handler机制更新UI必须用new Handler();
来初始化。java
// 默认使用UI主线程的Looper Handler mHandler = new Handler(); mHandler.post(new Runnable(){});
在Android开发中常常会使用到线程,一想到线程,不少同窗就当即使用
new Thread(){...}.start();
这样的方式。这样若是在一个Activity中屡次调用上面的代码,那么将建立多个匿名线程,程序运行的越久可能会愈来愈慢。所以,须要一个Handler来启动一个线程,以及删除一个线程。
保证线程不会重复的建立。异步
特色:async
代码示例:ide
// UI线程的Handler Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); // 处理UI更新 }; HandlerThread mBackThread = new HandlerThread("mybackthread"); mBackThread.start(); // 后台线程的Handler Handler mBackHandler = new Handler(mBackThread.getLooper()); mBackHandler.post(new Runnable() { @Override public void run() { // 后台线程执行耗时操做,异步 ... // mHandler发消息,回到主线程更新UI mHandler.sendMessage(msg); } });
注意:mBackHandler
的初始化必须在mBackThread.start();
以后,不然拿不到这个线程的looper。
这种模式经过mBackHandler.post(new Runnable() {})
来实现后台异步任务执行,全部后台任务都是经过HandlerThread
这个线程执行的,可是HandlerThread
是串行执行任务的,也就是每次post
后进入队列排队执行。
HandlerThread
的退出:oop
@Override protected void onDestroy() { super.onDestroy(); if(mBackThread != null){ mBackThread.quitSafely(); try { mBackThread.join(); mBackThread = null; mBackHandler = null; } catch (InterruptedException e) { e.printStackTrace(); } } }
查看源码AsyncTask只是对Thread和Handler的一个封装。post
AsyncTask <Params, Progress, Result>
Params
: 指定的是咱们传递给异步任务执行时的参数的类型Progress
: 指定的是咱们的异步任务在执行的时候将执行的进度返回给UI线程的参数的类型Result
: 指定的是异步任务执行完后返回给UI线程的结果的类型onPreExecute()
:UI Thread当中执行,这个方法是在执行异步任务以前的时候执行,咱们能够在异步任务执行前作UI提示doInBackground(Params... params)
:这个方法就是来处理异步任务的方法,执行耗时操做。这个方法也是必需要实现的抽象方法。onProgressUpdate(Progess... values)
:UI Thread当中执行,用来更新进度条等onPostExecute(Result... result)
:UI Thread当中执行,当异步任务执行完以后,将doInBackground
结果返回给这个方法来更新UIexecute(Params... params)
executeOnExecutor(Executor exec, Params... params)
execute
默认执行方式不统一,1.5中顺序执行,1.6到 2.3中并行执行,3.0之后又改回串行执行,并添加并行执行接口executeOnExecutor
execute
AsyncTask
对象只能被执行一次,即只能调用一次execute
,不然会抛出异常报错Caused by: java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
// 初始化AsyncTask及执行 protected void function() { ... // 串行执行,识别一张bitmap,每次执行前都须要从新new一个对象 mClassifierAsyncTask = new ClassifierAsyncTask(); mClassifierAsyncTask.execute(bitmap); } // 自定义AsyncTask任务类,实现doInBackground private ClassifierAsyncTask mClassifierAsyncTask; private class ClassifierAsyncTask extends AsyncTask<Bitmap , Void, String >{ @Override protected void onPreExecute() { super.onPreExecute(); mTvResult.setText(getString(R.string.classifying)); } @Override protected String doInBackground(Bitmap... bitmaps) { if(mMyTfClassifier == null) { mMyTfClassifier = new MyTfClassifier(MainActivity.this); } String result = mMyTfClassifier.recognizeImage(bitmaps[0]); return result; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); mTvResult.setText(result); } }
Activity
屏幕旋转或销毁时,若是AsyncTask
没有执行完毕就会存在内存泄露。特别是屏幕旋转时AsyncTask
没有执行完毕,会致使屏幕异常。ui