AsyncTask,顾名思义,异步任务。说到异步,最简单的理解就是不一样步。再复杂一点理解,就得举例子了。html
假设我要去火车站买票,刚到火车站我忽然发现我忘了带身份证。怎么办?怎么办!java
想办法,想办法!我想我应该找个在学校的同窗帮我送过来,由于我不能本身回去拿啊,还要排队呢,走不开。嗯,要找人送过来。可是问题来了,我找人送身份证了,我去排队了,若是排到第一位了身份证还没到怎么办?叮,脑壳上面忽然亮了一个小灯泡,机智的我在排队前想到了两种方案:android
第一种方案,让售票员等着我,我后面队伍里买票的人也等着我,我一直在窗口第一位置等着同窗来送身份证,直到,个人身份证被送来,而后顺利买票。json
另外一种方案呢,就是我跟售票员说一下,让我在一边等着送身份证,后面的人继续买票,等个人身份证送来的时候我通知下售票员,就能够尽快排到队伍第一位(不必定是当即排到第一位,由于万一有人正在买票,我不能过去打断他)而后买票。数组
因此呢,选第一种仍是第二种?我确定选第二种,由于选第一种确定会被后面排队的人骂死,并且还有可能被售票员骂,搞很差还会挨揍,毕竟由于我一我的,浪费了这么多人的时间,也拖慢了售票员的工做效率。网络
好了,例子就说到这里。在例子里,第二种方法就是异步的。异步每每和多线程有关,并且异步任务也大可能是交由一个单独的线程完成,而后返回结果给主线程。这里售票员至关于cpu,而排队买票的人至关于等待被执行的任务,而我是个被标记为异步的任务(由于我知道我带身份证,不能当即买到票,因此排队前就想好了第二种方案),当cpu执行到我这个任务的时候,发现我这个任务可执行的条件(身份证)不具有,因此由我发起了一个异步任务(同窗送票),去获取可执行的条件,以后当即把位置让出来,让其余排队的任务继续执行。直到个人身份证拿来,而后立马通知cpu准备接待我。多线程
嗯,差很少就是这样了。开始说正文,android里面的AsyncTask。先上一段官网的引用:异步
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.ide
是英语,虽然我能懂大概是什么意思,可是仍是不翻译了,怕误人子弟,等我英语学的再好些再来翻译吧。不过仍是要解释下大概的意思,就是说AsyncTask能够在UI线程上作一些后台操做,也能返回操做结果到UI线程上。咱们知道UI线程是不能作一些耗时的操做的,可是有了AsyncTask,咱们能够这样作了。可是,url
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.
对于耗时比较久的任务,仍是不建议放在AsyncTask中执行。AysncTask被设计成Thread和Handler的辅助类,并不能执行过于复杂和耗时的任务,这种任务应该用其余方法这里就不说了。AsyncTask最好用于耗时最多只有几秒钟的操做,好比向网络请求个xml或是json之类的网络操做,或是用在程序的初始化界面等等。
下面说下AsyncTask的使用。其实很简单。
首先你须要定义一个AsyncTask的子类,而且必须重写父类的doInBackground(Params...)
方法。另外还有onPostExecute(Result)
方法也可重写,这个方法在doInBackground
以后被自动调用,因此你能够在这里写一些任务完成的通知代码。
先给一个官方的例子:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { 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的时候,必须在UI线程中执行,以下语句。
new DownloadFilesTask().execute(url1, url2, url3);
能够看到,在继承AsyncTask的时候,有几个泛型类型,如AsyncTask<URL, Integer, Long>
,简单解释下。
new DownloadFilesTask().execute()
的参数(最后传到了doInBackground
),这里的参数能够不仅一个,由于最后到方法里面,收到的是个数组。publishProgress
(用来在后台进程中发送进度的方法,直接使用的,不用定义)和onProgressUpdate
两个方法中。doInBackground
的返回类型,以及onPostExecute
的输入参数类型固然,若是你什么都不须要,能够都使用Void
。
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
另外,还有一个能够重写的方法,是onPreExecute()
,它在doInBackground
以前被调用,因此若是须要的话,你能够重写它而后作一些实例化进度条啊之类的工做。
最后,总结一下:
使用AsyncTask,你要作的是,继承父类,而后重写doInBackground(Params...)
,在里面实现后台操做,若是有返回结果的话,重写onPostExecute(Result)
而后处理后台程序的结果。
若是须要更新进度的话,在onPreExecute()
里实例化进度条(也能够不在这),以后在doInBackground(Params...)
里面用publishProgress()
发布进度值,而后重写onProgressUpdate(Progress...)
接收onPreExecute()
发布的结果,并添加更新进度条的代码。