AsyncTask
,相信你们已经很熟悉了。它的内部封装了Thread
和Handler
,这让咱们能够将一些耗时操做放到AsyncTask
,而且能将结果及时更新到UI上。AsyncTask
主要用于短期耗时操做,长时间耗时操做不建议使用AsyncTask
。下面经过Google官方的一个例子来认识AsyncTask
的用法。并发
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected void onPreExecute() { showProgress(); } 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"); } }
AsyncTask
是一个抽象类,咱们要使用时必须自定义一个类继承于它。AsyncTask
的原型为:ide
public abstract class AsyncTask<Params, Progress, Result> { }
它接收三个泛型参数,分别表示参数类型、进度类型、结果类型。测试
上述的例子中DownloadFilesTask
接收参数类型为URL
类型,使用Integer
类型表示任务进度,最终的任务结果是一个Long
类型。this
注意:上面三个泛型类型不必定都得用一个明确的类型,对于没有使用的类型,可使用
Void
类型代替。url
继承AsyncTask
至少须要重写doInBackground
方法,同时AsyncTask
也提供了另外三个方法供咱们重写,分别是onPreExecute
、onProgressUpdate
、onPostExecute
。线程
publishProgress
方法被调用后执行,它运行在UI线程中。一般用于展现整个任务的一个进度。doInBackground
的返回结果会透传给onPostExecute
的参数值,它运行在主线程中。一般咱们从这里获取任务执行完成后的结果数据。AsyncTask
类必须在UI线程加载。(在4.1系统版本以上会自动完成)AsyncTask
对象必须在UI线程建立,也就是说AsyncTask
的构造方法必须在UI线程中调用。(通过测试AsyncTask
对象能够在子线程建立,只要保证execute
方法在UI线程执行就OK的。可是没有人会这样作,由于画蛇添足!!!)execute
方法必须在UI线程中调用。这样作是保证onPreExecute
方法运行在UI线程。onPreExecute
、doInBackground
、onProgressUpdate
、onProgressUpdate
方法。在AsyncTask
诞生之初,任务是在一个后台线程中顺序执行的。从Android 1.6开始,就变成了能够在后台线程中并行执行任务。而后,到了Android 3.0版本,又改为了单线程顺序执行,以此避免并发任务产生的错误行为。code
为了验证上述结论,下面看一个Demo例子。orm
public class MainActivity extends Activity { public static final String TAG = "MyApplication"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new MyTask("task1").execute(); new MyTask("task2").execute(); new MyTask("task3").execute(); new MyTask("task4").execute(); new MyTask("task5").execute(); new MyTask("task6").execute(); } private class MyTask extends AsyncTask<Void, Void, Void> { private String taskName; MyTask(String taskName) { this.taskName = taskName; } @Override protected Void doInBackground(Void... integers) { try { Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void aVoid) { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Log.e(TAG, taskName + " finish at: " + df.format(new Date())); } } }
这个例子比较简单,就是在MainActivity
启动时,执行了六次MyTask
,并将任务执行后的时间节点打印出来。对象
手机的系统版本是Android 8.0,从上面的Log信息能够看出,AsyncTask
的确是串行执行的。因为现有测试机最低系统版本都是Android 4.1,已经很难找到Android 3.0如下的老古董机子了blog