一、AsyncTask被弃用的原因
1、内存泄漏问题:AsyncTask在早期的Android版本中使用了隐式的静态引用,导致在配置更改(如屏幕旋转)时容易发生内存泄漏。这是因为AsyncTask在执行期间会持有对启动它的Activity或Fragment的引用,而这些引用无法被及时释放,从而导致内存泄漏。
2、生命周期不可控问题:AsyncTask的执行是与UI组件(如Activity)绑定的,这意味着在Activity销毁或配置更改时,AsyncTask的执行可能会被取消或中断。这种生命周期依赖性使得在处理旋转屏幕等配置更改时,需要额外的处理才能确保任务能够正确执行。
3、并发执行限制:AsyncTask默认情况下会按顺序执行后台任务,并且在早期的Android版本中,同时只能执行一个AsyncTask实例。这导致了并发执行任务的限制,无法充分利用多核处理器的优势。
4、异常处理问题:AsyncTask中的异常处理机制相对较弱,对于后台任务中的异常,无法提供一种统一和可靠的方式来捕获和处理。
二、抽象类BackgroundTask
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public abstract class BackgroundTask {
private final Context context;
private final Handler handler;
private final ExecutorService THREAD_POOL_EXECUTOR;
public BackgroundTask( Context context) {
this.context = context;
handler = new Handler( Looper.getMainLooper( )) ;
THREAD_POOL_EXECUTOR = Executors.newFixedThreadPool( 5 ) ;
}
private interface Callback< R> {
void onComplete( R result) ;
}
private < R> void executeAsync( final Callable< R> callable, final Callback< R> callback) {
THREAD_POOL_EXECUTOR.submit( new Runnable ( ) {
@Override
public void run ( ) {
final R result;
try {
result = callable.call( ) ;
} catch ( Exception e) {
throw new RuntimeException( e) ;
}
runUI( new Runnable ( ) {
@Override
public void run ( ) {
callback.onComplete( result) ;
}
} ) ;
}
} ) ;
}
private void runUI( Runnable runnable) {
if ( Thread.currentThread( ) != context.getMainLooper( ) .getThread( )) {
handler.post( runnable) ;
} else {
runnable.run( ) ;
}
}
public void shutdown ( ) {
THREAD_POOL_EXECUTOR.shutdown( ) ;
}
public void executeOnExecutor ( ) {
runUI( new Runnable ( ) {
@Override
public void run ( ) {
onPreExecute( ) ;
}
} ) ;
executeAsync( new Callable< String> ( ) {
@Override
public String call ( ) {
return doInBackground( ) ;
}
} , new Callback< String> ( ) {
@Override
public void onComplete( String result) {
onPostExecute( result) ;
}
} ) ;
}
protected abstract void onPreExecute( ) ;
protected abstract String doInBackground( Integer.. . params) ;
protected abstract void onPostExecute( String rslt) ;
}
特点:
1、使用方法和AsyncTask一致,可以完美平替AsyncTask。
2、在Activity等生命周期结束时,可以调用shutdown()方法关闭线程池,避免内存泄漏问题。
三、使用示例
import android.content.Context;
public class MyAsyncTask extends BackgroundTask {
public MyAsyncTask( Context context) {
super( context) ;
}
@Override
protected void onPreExecute ( ) {
// 在主线程中执行,任务执行前的准备工作
// 例如显示进度条或初始化UI
}
@Override
protected String doInBackground( Integer.. . params) {
// 在后台线程中执行,耗时任务的代码
// 模拟耗时操作,每隔一秒更新进度,并返回结果
return "Task completed" ;
}
@Override
protected void onPostExecute( String result) {
// 在主线程中执行,任务完成后的操作
// 参数result为doInBackground方法的返回结果
// 更新UI,显示任务完成的消息
// textView.setText( result) ;
}
}
public class BaseActivity extends Activity {
public BackgroundTask task;
@Override
public void onDestroy ( ) {
if ( task != null) task.shutdown( ) ;
super.onDestroy( ) ;
}
}
public class LoginActivity extends BaseActivity {
.. .
public void onCreate( Bundle savedInstanceState) {
.. .
task = new MyAsyncTask( context) ;
task.executeOnExecutor( ) ;
.. .
}
}