Android 多线程--AsyncTask详解

AsyncTaskAndroid提供的一个助手类,它对ThreadHandler进行了封装,方便我们使用。Android之所以提供AsyncTask这个类,就是为了方便我们在后台线程中执行操作,然后将结果发送给主线程,从而在主线程中进行UI更新等操作。在使用AsyncTask时,我们无需关注ThreadHandlerAsyncTask内部会对其进行管理。总结起来就是: 3个泛型,4个步骤。3个泛型指的是什么呢?我们来看看AsyncTask这个抽象类的定义,当我们定义一个类来继承AsyncTask这个类的时候,我们需要为其指定3个泛型参数:

AsyncTask<Params, Progress, Result>    

● Params: 这个泛型指定的是我们传递给异步任务执行时的参数的类型    

● Progress: 这个泛型指定的是我们的异步任务在执行的时候将执行的进度返回给UI线程的参数的类型    

● Result: 这个泛型指定的异步任务执行完后返回给UI线程的结果的类型 我们在定义一个类继承AsyncTask类的时候,必须要指定好这三个泛型的类型,如果都不指定的话,则都将其写成Void,例如:AsyncTask <Void, Void, Void>

4个步骤:当我们执行一个异步任务的时候,其需要按照下面的4个步骤分别执行     ●onPreExecute():这个方法是在执行异步任务之前的时候执行,并且是在UI Thread当中执行的,通常我们在这个方法里做一些UI控件的初始化的操作,例如弹出要给ProgressDialog

@MainThread    

public finalAsyncTask<Params,Progress,Result>execute(Params... params) {

    returnexecuteOnExecutor(sDefaultExecutor,params);    

}

     该方法有MainThread注解,表示该方法是运行在主线程中的。在AsyncTask执行了execute()方法后就会在UI线程上执行onPreExecute()方法,
     该方法在task真正执行前运行,我们通常可以在该方法中显示一个进度条,从而告知用户后台任务即将开始。例如要弹出ProgressDialog。
    ●doInBackground(Params... params):

@WorkerThread    

protected abstractResultdoInBackground(Params... params);

     该方法有WorkerThread注解,表示该方法是运行在单独的工作线程中的,而不是运行在主线程中。    
     onPreExecute()方法执行完之后,会马上执行这个方法,这个方法就是来处理异步任务的方法,
     Android操作系统会在后台的线程池当中开启一个worker thread来执行我们的这个方法,所以这个方法是在worker thread当中执行的,
     这个方法执行完之后就可以将我们的执行结果发送给我们的最后一个 onPostExecute 方法,在这个方法里,我们可以从网络当中获取数据等一些耗时的操作,例如当需要更新progressDialog进度的时候,可以手动调用

publishProgress(Progress... values)  动态更新进度。

●onProgressUpdate(Progess... values):

@SuppressWarnings({"UnusedDeclaration"})
@MainThread
protected void onProgressUpdate(Progress... values) {
}

该方法也具有MainThread注解,表示该方法是在主线程上被调用的,且传入的参数是Progress泛型定义的不定长数组。如果在doInBackground中多次调用了publishProgress方法,那么主线程就会多次回调onProgressUpdate方法。

我们在异步任务执行的时候,有时候需要将执行的进度返回给我们的UI界面,例如下载一张网络图片,我们需要时刻显示其下载的进度,就可以使用这个方法来更新我们的进度。这个方法在调用之前,我们需要在 doInBackground 方法中调用一个 publishProgress(Progress) 的方法来将我们的进度时时刻刻传递给 onProgressUpdate 方法来更新 。

●onPostExecute(Result... result):

@SuppressWarnings({"UnusedDeclaration"})
@MainThread
protected void onPostExecute(Resultresult) {
}

该方法也具有MainThread注解,表示该方法是在主线程中被调用的。当我们的异步任务执行完之后,就会将结果返回给这个方法,我们可以将返回的结果显示在UI控件上。

总结:

·  AsyncTask的对象必须在UI Thread当中实例化

·  execute方法必须在UI Thread当中调用

·  不要手动的去调用AsyncTaskonPreExecute, doInBackground, publishProgress, onProgressUpdate, onPostExecute方法,这些都是由Android系统自动调用的

·  AsyncTask任务只能被执行一次

 

缺陷:

1.AsyncTask一旦执行了 doInBackground,就算调用取消方法,也会将doInBackground里面的代码执行完毕,才会停止。

2.当大量异步发生时,超过128个时,导致线程池满了,会出异常。(最多容纳128个异步线程,最多能并发处理当前(cpu个数*2+1)个的线程)。

3.内存泄漏:还有一种常见的情况就是,在Activity中使用非静态匿名内部AsyncTask类,由于Java内部类的特点,AsyncTask内部类会持有外部类的隐式引用。由于AsyncTask的生命周期可能比Activity的长,当Activity进行销毁AsyncTask还在执行时,由于AsyncTask持有Activity的引用,导致Activity对象无法回收,进而产生内存泄露。



©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页