AsyncTask作为一个比Handler好用的消息处理类,掌握它是必须的,废话少说,直接往下看!
-----------------------------------------------------------------------------------------------------------------
AsyncTask 是一个抽象类(public abstract class AsyncTask extends Object),如果想使用它的话,我们必须创建一个子类去继承它。
看一下这个抽象类:android.os.AsyncTask<Params, Progress, Result>,指定了三个泛型参数,我们先分析一下这三个参数:
1. Params:在执行AsyncTask时需要传入的参数,可用于在后台任务中使用,这么说不懂?ok,下面代码会告诉你怎么用.
new DownloadTask().execute(params) --> doInBackground(Integer... params) // 这边的Integer可以自定义
2. Progress:后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
3. Result:当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型,比如我们常使用Boolean或String类型作为返回类型。
Notice:这三个参数是泛型参数,也就是说参数类型是根据要求传入的,所以在方法的使用过程中,一定要清晰参数类型的设定和使用。
这里给出一个最简单的自定义AsyncTask的方式:
class DownloadTask extends AsyncTask<Void, Integer, Boolean> {
......
}
当然,定义完一个继承AsyncTask的子类后,我们还需要覆写AsyncTask的几个方法:
1. onPreExecute()
2. doInBackground(Params...)
3. onProgressUpdate(Progress...)
4. onPostExecute(Result)
下面,我们就这4个方法的使用流程作一个详细的介绍:
onPreExecute():这个方法顾名思义,就是在异步任务处理之前需要执行的操作,那么它操作什么?简单的说就是进行一些界面上的初始化操作,比如:显示一个进度条对话框等。这个方法不是我们的重点方法,但是在使用过程中巧妙使用可以增强界面的可观性。
protected void onPreExecute() { super.onPreExecute(); // 可以进行一些预处理 }
doInBackground(Params...):这个就是AsyncTask中最为重要的方法了,因为这个方法中的所有代码都会在子线程中运行,我们也是在这个方法中去处理所有的耗时任务。
直接看代码:
protected Boolean doInBackground(Integer... params) { // 这边params是由execute()传进来的,这个execute方法可以在下面找到答案 for (int i = 0; i < 101; i++) { publishProgress(i); // 对主线程UI进行更新操作,将调用onProgressUpdate()方法
try { Thread.sleep(params[0]); // 休眠线程 } catch (Exception e) { e.printStackTrace(); } } return true; // 任务完成后return一个结果,这边的Boolean类型的结果 }
通过以上的代码,我们可以发现:任务一旦完成就可以通过return语句来将任务的执行结果返回,如果AsyncTask的第三个泛型参数被指定的是Void,就可以不返回任务执行结果。
在这个方法中是不可以进行UI操作的(子线程是无法对主线程进行修改的),如果需要更新UI元素的话,就需要调用publishProgress(Progress...)方法来完成了。
onProgressUpdate(Progress...):当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就会很快被调用,此方法中的参数是从哪边传来的,我想不需要解释了吧。
在这个方法中,可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应地更新,为什么?上代码!。
protected void onProgressUpdate(Integer... values) { // values[0] = i MainActivity.this.text.setText("当前进度是:" + String.valueOf(values[0]) + "%"); // 主线程进行操作 }
onPostExecute(Result):这个函数就是来执行return返回后的一些操作的,我们直接看下代码,就能理解。
protected void onPostExecute(Boolean b) { // b --> true if (b) { Toast.makeText(getBaseContext(), "Download succeed", Toast.LENGTH_SHORT).show(); // 后续操作 } else { Toast.makeText(getBaseContext(), "Download failed", Toast.LENGTH_SHORT).show(); } }
那么,问题来了,我们定义好了类、同时覆写了各种方法,但是如何启动它?
如果想要启动这个任务,只需编写一行代码:new DownloadTask().execute();
protected void onCreate(Bundle savedInstanceState) { // 这个方法你不要说你不认识~ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new DownloadTask().execute(100); // 这样就可以启动异步类了 }