AsyncTaskAPI 在 Android11中已被弃用?

谷歌不赞成在 Android 11中使用 Android AsyncTask API,并建议改用 java.util.concurrent。您可以检查提交 给你

 *
* @deprecated Use the standard <code>java.util.concurrent</code> or
*   <a href="https://developer.android.com/topic/libraries/architecture/coroutines">
*   Kotlin concurrency utilities</a> instead.
*/
@Deprecated
public abstract class AsyncTask<Params, Progress, Result> {

如果您在 Android 中使用异步任务来维护一个旧的代码库,那么将来可能需要对其进行更改。我的问题是,使用 java.util.concurrent代码片段应该适当地替换下面所示的代码片段。它是一个活动的静态内部类。我正在寻找的东西,将与 minSdkVersion 16工作

private static class LongRunningTask extends AsyncTask<String, Void, MyPojo> {
private static final String TAG = MyActivity.LongRunningTask.class.getSimpleName();
private WeakReference<MyActivity> activityReference;


LongRunningTask(MyActivity context) {
activityReference = new WeakReference<>(context);
}


@Override
protected MyPojo doInBackground(String... params) {
// Some long running task
            

}


@Override
protected void onPostExecute(MyPojo data) {


MyActivity activity = activityReference.get();
activity.progressBar.setVisibility(View.GONE);
populateData(activity, data) ;
}




}
157652 次浏览
private WeakReference<MyActivity> activityReference;

终于不用它了,因为 WeakReference<Context>一直是一个黑客,而不是一个合适的解决方案

现在人们将有机会清理他们的代码。


AsyncTask<String, Void, MyPojo>

基于此代码,实际上不需要 Progress,并且有一个 String输入 + MyPojo输出。

这实际上很容易实现,不需要任何 AsyncTask 的使用。

public class TaskRunner {
private final Executor executor = Executors.newSingleThreadExecutor(); // change according to your requirements
private final Handler handler = new Handler(Looper.getMainLooper());


public interface Callback<R> {
void onComplete(R result);
}


public <R> void executeAsync(Callable<R> callable, Callback<R> callback) {
executor.execute(() -> {
final R result = callable.call();
handler.post(() -> {
callback.onComplete(result);
});
});
}
}

如何传递字符串? 像这样:

class LongRunningTask implements Callable<MyPojo> {
private final String input;


public LongRunningTask(String input) {
this.input = input;
}


@Override
public MyPojo call() {
// Some long running task
return myPojo;
}
}

还有

// in ViewModel
taskRunner.executeAsync(new LongRunningTask(input), (data) -> {
// MyActivity activity = activityReference.get();
// activity.progressBar.setVisibility(View.GONE);
// populateData(activity, data) ;


loadingLiveData.setValue(false);
dataLiveData.setValue(data);
});


// in Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);


setContentView(R.layout.main_activity);


viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
viewModel.loadingLiveData.observe(this, (loading) -> {
if(loading) {
progressBar.setVisibility(View.VISIBLE);
} else {
progressBar.setVisibility(View.GONE);
}
});


viewModel.dataLiveData.observe(this, (data) -> {
populateData(data);
});
}

这个例子使用了一个单线程池,这对 DB 写(或序列化的网络请求)很有用,但是如果您想要 DB 读或多个请求,您可以考虑以下 Execator 配置:

private static final Executor THREAD_POOL_EXECUTOR =
new ThreadPoolExecutor(5, 128, 1,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

Google 建议使用 Java 的并发框架或 Kotlin 协程。但是 Rxjava 最终比 java 具有更多的灵活性和特性,因此获得了相当多的流行。

Android 不赞成在 Android 11中使用 AsyncTask API,以便从一开始就解决一些问题。

现在怎么办?

  • 线头
  • 刽子手
  • RxJava
  • 可倾听期货
  • 协奏曲

为什么是 Coroutines?

协同程序是 Kotlin 的异步编程方式 支持是稳定的,因为科特林1.3,连同一个 kotlinx.coroutines 库 -

  • 结构化并发
  • 非阻塞,顺序代码
  • 取消传播
  • 自然异常处理

根据 Android 文档AsyncTask空气污染指数三十中被否定,建议使用 标准 java.util.while 或者 < a href = “ https://developer.android.com/subject/library/Architecture/coroutines”rel = “ noReferrer”> Kotlin 并发实用程序 代替。

使用后者可以非常简单地实现:

  1. CoroutineScope上创建通用扩展函数:

     fun <R> CoroutineScope.executeAsyncTask(
    onPreExecute: () -> Unit,
    doInBackground: () -> R,
    onPostExecute: (R) -> Unit
    ) = launch {
    onPreExecute() // runs in Main Thread
    val result = withContext(Dispatchers.IO) {
    doInBackground() // runs in background thread without blocking the Main Thread
    }
    onPostExecute(result) // runs in Main Thread
    }
    
  2. 对任何具有 Dispatchers.Main上下文的 CoroutineScope使用该函数:

    • ViewModel:

      class MyViewModel : ViewModel() {
      
      
      fun someFun() {
      viewModelScope.executeAsyncTask(onPreExecute = {
      // ... runs in Main Thread
      }, doInBackground = {
      // ... runs in Worker(Background) Thread
      "Result" // send data to "onPostExecute"
      }, onPostExecute = {
      // runs in Main Thread
      // ... here "it" is the data returned from "doInBackground"
      })
      }
      }
      
    • ActivityFragment:

      lifecycleScope.executeAsyncTask(onPreExecute = {
      // ... runs in Main Thread
      }, doInBackground = {
      // ... runs in Worker(Background) Thread
      "Result" // send data to "onPostExecute"
      }, onPostExecute = {
      // runs in Main Thread
      // ... here "it" is the data returned from "doInBackground"
      })
      

    要使用 viewModelScopelifecycleScope,请在应用程序的 建造,分级文件的依赖项中添加下一行:

    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION" // for viewModelScope
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$LIFECYCLE_VERSION" // for lifecycleScope
    

    在写 final LIFECYCLE_VERSION = "2.3.0-alpha05"的时候

更新 :

我们还可以使用 onProgressUpdate函数实现进度更新:

fun <P, R> CoroutineScope.executeAsyncTask(
onPreExecute: () -> Unit,
doInBackground: suspend (suspend (P) -> Unit) -> R,
onPostExecute: (R) -> Unit,
onProgressUpdate: (P) -> Unit
) = launch {
onPreExecute()


val result = withContext(Dispatchers.IO) {
doInBackground {
withContext(Dispatchers.Main) { onProgressUpdate(it) }
}
}
onPostExecute(result)
}

使用任何 CoroutineScope(viewModelScope/lifecycleScope,参见上面的实现)和 Dispatchers.Main上下文,我们可以称之为:

someScope.executeAsyncTask(
onPreExecute = {
// ... runs in Main Thread
}, doInBackground = { publishProgress: suspend (progress: Int) -> Unit ->
        

// ... runs in Background Thread


// simulate progress update
publishProgress(50) // call `publishProgress` to update progress, `onProgressUpdate` will be called
delay(1000)
publishProgress(100)


        

"Result" // send data to "onPostExecute"
}, onPostExecute = {
// runs in Main Thread
// ... here "it" is a data returned from "doInBackground"
}, onProgressUpdate = {
// runs in Main Thread
// ... here "it" contains progress
}
)

在这里,我使用 Coroutines 创建了一个 AsyncTask 的替代方案,它可以与 AsyncTask 一样使用,而不需要更改项目中的大量代码。

  1. 创建一个新的抽象类 AsyncTaskCoroutine,它接受输入参数和输出参数数据类型,当然这些参数是可选的:)

     import kotlinx.coroutines.Dispatchers
    import kotlinx.coroutines.GlobalScope
    import kotlinx.coroutines.async
    import kotlinx.coroutines.launch
    
    
    abstract class AsyncTaskCoroutine<I, O> {
    var result: O? = null
    //private var result: O
    open fun onPreExecute() {}
    
    
    open fun onPostExecute(result: O?) {}
    abstract fun doInBackground(vararg params: I): O
    
    
    fun <T> execute(vararg input: I) {
    GlobalScope.launch(Dispatchers.Main) {
    onPreExecute()
    callAsync(*input)
    }
    }
    
    
    private suspend fun callAsync(vararg input: I) {
    GlobalScope.async(Dispatchers.IO) {
    result = doInBackground(*input)
    }.await()
    GlobalScope.launch(Dispatchers.Main) {
    
    
    onPostExecute(result)
    
    
    
    
    }
    }
    }
    

2. Inside Activity 现在使用和旧的 AsycnTask 一样的方法

 new AsyncTaskCoroutine() {
@Override
public Object doInBackground(Object[] params) {
return null;
}
    

@Override
public void onPostExecute(@Nullable Object result) {
    

}
    

@Override
public void onPreExecute() {
    

}
}.execute();
  1. 以防万一,如果你需要发送通过参数

      new AsyncTaskCoroutine<Integer, Boolean>() {
    
    
    @Override
    public Boolean doInBackground(Integer... params) {
    return null;
    }
    
    
    @Override
    public void onPostExecute(@Nullable Boolean result) {
    
    
    }
    
    
    @Override
    public void onPreExecute() {
    
    
    }
    }.execute();
    

我的定制替代品: https://github.com/JohnyDaDeveloper/AndroidAsync

它只在应用程序运行时才能工作(更具体地说,是安排任务的活动) ,但是它能够在后台任务完成后更新 UI

编辑: 我的 AsyncTask 不再需要 Activity 才能运行。

最简单的替代方法之一是使用 Thread

new Thread(new Runnable() {
@Override
public void run() {
// do your stuff
runOnUiThread(new Runnable() {
public void run() {
// do onPostExecute stuff
}
});
}
}).start();

如果您的项目支持 JAVA 8,您可以使用 lambda:

new Thread(() -> {
// do background stuff here
runOnUiThread(()->{
// OnPostExecute stuff here
});
}).start();

您可以使用这个自定义类作为 AsyncTask < > 的替代方案,这与 AsyncTask 相同,因此您不需要为此付出额外的努力。

import android.os.Handler;
import android.os.Looper;


import androidx.annotation.NonNull;
import androidx.annotation.Nullable;


import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class TaskRunner {


private static final int CORE_THREADS = 3;
private static final long KEEP_ALIVE_SECONDS = 60L;
private static TaskRunner taskRunner = null;
private Handler handler = new Handler(Looper.getMainLooper());
private ThreadPoolExecutor executor;


private TaskRunner() {
executor = newThreadPoolExecutor();
}


public static TaskRunner getInstance() {
if (taskRunner == null) {
taskRunner = new TaskRunner();
}
return taskRunner;
}


public void shutdownService() {
if (executor != null) {
executor.shutdown();
}
}


public void execute(Runnable command) {
executor.execute(command);
}


public ExecutorService getExecutor() {
return executor;
}


public <R> void executeCallable(@NonNull Callable<R> callable, @NonNull OnCompletedCallback<R> callback) {
executor.execute(() -> {
R result = null;
try {
result = callable.call();
} catch (Exception e) {
e.printStackTrace(); // log this exception
} finally {
final R finalResult = result;
handler.post(() -> callback.onComplete(finalResult));
}
});
}


private ThreadPoolExecutor newThreadPoolExecutor() {
return new ThreadPoolExecutor(
CORE_THREADS,
Integer.MAX_VALUE,
KEEP_ALIVE_SECONDS,
TimeUnit.SECONDS,
new SynchronousQueue<>()
);
}


public interface OnCompletedCallback<R> {
void onComplete(@Nullable R result);
}
}

如何使用它? 请按照下面的例子。

用 lambda 表情

TaskRunner.getInstance().executeCallable(() -> 1, result -> {
});




TaskRunner.getInstance().execute(() -> {
});

没有 lambda 表达式

TaskRunner.getInstance().executeCallable(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 1;
}
}, new TaskRunner.OnCompletedCallback<Integer>() {
@Override
public void onComplete(@Nullable Integer result) {


}
});


TaskRunner.getInstance().execute(new Runnable() {
@Override
public void run() {


}
});

注意: 不要忘记关闭执行器服务

TaskRunner.getInstance().shutdownService();

只需用这个 Thread 替换整个类,并将其放入一个方法中以传递变量

new Thread(() -> {
// do background stuff here
runOnUiThread(()->{
// OnPostExecute stuff here
              

});
}).start();

在片段中将上下文添加到 runOnUiThread()方法:

 new Thread(() -> {
// do background stuff here
context.runOnUiThread(()->{
// OnPostExecute stuff here
});
}).start();

您可以直接使用 java.util.concurrent包中的 Executors

我也搜索了它,我发现了一个解决方案在这个 不推荐使用 Android 异步 API的职位。

不幸的是,这篇文章使用的是 Kotlin,但是经过一点努力,我已经把它转换成了 Java。这就是解决办法。

ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());


executor.execute(new Runnable() {
@Override
public void run() {


//Background work here


handler.post(new Runnable() {
@Override
public void run() {
//UI Thread work here
}
});
}
});

非常简单,对吧? 如果您在项目中使用 Java8,那么您可以将它简化一点。

ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());


executor.execute(() -> {
//Background work here
handler.post(() -> {
//UI Thread work here
});
});

尽管如此,它还是不能在代码的简洁性方面击败 kotlin,但是比以前的 Java 版本要好。

希望这个能帮到你,谢谢

使用这个类来执行后台线程中的后台任务这个类是 适用于所有 Android API 版本,包括 Android11,这个代码也是同样的工作像 AsyncTask背景OnPostExecute方法

public abstract class BackgroundTask {


private Activity activity;
public BackgroundTask(Activity activity) {
this.activity = activity;
}


private void startBackground() {
new Thread(new Runnable() {
public void run() {


doInBackground();
activity.runOnUiThread(new Runnable() {
public void run() {


onPostExecute();
}
});
}
}).start();
}
public void execute(){
startBackground();
}


public abstract void doInBackground();
public abstract void onPostExecute();


}

复制上面的类之后,您可以将它与下面的代码一起使用:

new BackgroundTask(MainActivity.this) {
@Override
public void doInBackground() {


//put you background code
//same like doingBackground
//Background Thread
}


@Override
public void onPostExecute() {


//hear is result part same
//same like post execute
//UI Thread(update your UI widget)
}
}.execute();

HandlerThread 可以作为 AsyncTask的替代品,它们是长时间运行的线程:

您可以创建两个处理程序对象,其中一个将用于从 workerThread 向 UI Thread 发送消息。

Handler uiHandler,workerHandler;
Message msg;
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Handler.Callback callback=new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
// handle messages sent from working thread (like updating UI)...
return true;
}
}
uiHandler=new Handler(callback);
workerHandler = new Handler(handlerThread.getLooper());
workerHandler.post(new Runnable(){
// Perform required task
uiHandler.sendMessage(msg); // this message will be sent to and handled by UI Thread
});

另外,请记住 HandlerThreads 运行在活动的生命周期之外,因此需要正确地清理它们,否则就会出现线程泄漏。您可以在 Activity 的 onDestroy ()中使用兼容()方法来防止线程泄漏。

您可以根据自己的需要迁移到下一种方法

  • 线程 + 处理程序
  • 执行人
  • 未来
  • 意向服务
  • 作业调度器
  • RxJava
  • 协同程序(Kotlin)

[ Android 异步变体]

事实上,我写了两篇关于它的中篇小说:

第一个是 Java 和 Runnable 的解决方案,第二个是 Kotlin 和 coroutines 解决方案。 当然,两者都带有代码示例。

这是我的原则

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public abstract class AsyncTaskRunner<T> {


private ExecutorService executorService = null;
private Set<Callable<T>> tasks = new HashSet<>();


public AsyncTaskRunner() {
this.executorService = Executors.newSingleThreadExecutor();
}
    

public AsyncTaskRunner(int threadNum) {
this.executorService = Executors.newFixedThreadPool(threadNum);
}




public void addTask(Callable<T> task) {
tasks.add(task);
}


public void execute() {
try {
List<Future<T>> features = executorService.invokeAll(tasks);


List<T> results = new ArrayList<>();
for (Future<T> feature : features) {
results.add(feature.get());
}
this.onPostExecute(results);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
this.onCancelled();
} finally {
executorService.shutdown();
}


}


protected abstract void onPostExecute(List<T> results);


protected void onCancelled() {
// stub
}


}

还有用法例子。 扩展 AsyncTaskRunner类,

class AsyncCalc extends AsyncTaskRunner<Integer> {


public void addRequest(final Integer int1, final Integer int2) {
this.addTask(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
// Do something in background
return int1 + int2;
}
});
}


@Override
protected void onPostExecute(List<Integer> results) {
for (Integer answer: results) {
Log.d("AsyncCalc", answer.toString());
}
}
}

那就用吧!

AsyncCalc calc = new AsyncCalc();
calc.addRequest(1, 2);
calc.addRequest(2, 3);
calc.addRequest(3, 4);
calc.execute();

接受的答案是好的,但是..。 我没有看到 Cancel ()方法的实现

所以我的可能取消运行任务(模拟取消)的实现如下。 如果任务中断,则需要取消以不运行 postExecute ()方法。

public abstract class AsyncTaskExecutor<Params> {
public static final String TAG = "AsyncTaskRunner";


private static final Executor THREAD_POOL_EXECUTOR =
new ThreadPoolExecutor(5, 128, 1,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());


private final Handler mHandler = new Handler(Looper.getMainLooper());
private boolean mIsInterrupted = false;


protected void onPreExecute(){}
protected abstract Void doInBackground(Params... params);
protected void onPostExecute(){}
protected void onCancelled() {}


@SafeVarargs
public final void executeAsync(Params... params) {
THREAD_POOL_EXECUTOR.execute(() -> {
try {
checkInterrupted();
mHandler.post(this::onPreExecute);


checkInterrupted();
doInBackground(params);


checkInterrupted();
mHandler.post(this::onPostExecute);
} catch (InterruptedException ex) {
mHandler.post(this::onCancelled);
} catch (Exception ex) {
Log.e(TAG, "executeAsync: " + ex.getMessage() + "\n" + Debug.getStackTrace(ex));
}
});
}


private void checkInterrupted() throws InterruptedException {
if (isInterrupted()){
throw new InterruptedException();
}
}


public void cancel(boolean mayInterruptIfRunning){
setInterrupted(mayInterruptIfRunning);
}


public boolean isInterrupted() {
return mIsInterrupted;
}


public void setInterrupted(boolean interrupted) {
mIsInterrupted = interrupted;
}
}

使用此类的示例:

public class MySearchTask extends AsyncTaskExecutor<String> {


public MySearchTask(){
}


@Override
protected Void doInBackground(String... params) {
// Your long running task
return null;
}


@Override
protected void onPostExecute() {
// update UI on task completed
}


@Override
protected void onCancelled() {
// update UI on task cancelled
}
}


MySearchTask searchTask = new MySearchTask();
searchTask.executeAsync("Test");

在这里,我还使用抽象类创建了 AsyncTask 的替代方案,它可以作为类复制。

/app/src/main/java/. ./AsyncTasks.java

public abstract class AsyncTasks {
private final ExecutorService executors;


public AsyncTasks() {
this.executors = Executors.newSingleThreadExecutor();
}


private void startBackground() {
onPreExecute();
executors.execute(new Runnable() {
@Override
public void run() {
doInBackground();
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
onPostExecute();
}
});
}
});
}


public void execute() {
startBackground();
}


public void shutdown() {
executors.shutdown();
}


public boolean isShutdown() {
return executors.isShutdown();
}


public abstract void onPreExecute();


public abstract void doInBackground();


public abstract void onPostExecute();
}

实现/使用上述类

new AsyncTasks() {
@Override
public void onPreExecute() {
// before execution
}


@Override
public void doInBackground() {
// background task here
}


@Override
public void onPostExecute() {
// Ui task here
}
}.execute();

医生说:

AsyncTask 此类在 API 级别30中已被弃用 并发或 Kotlin 并发实用程序。

您需要使用 Handler或协程代替 AsyncTask

使用 Java 处理程序

new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// Your Code
}
}, 3000);

使用 Kotlin 的处理程序

Handler(Looper.getMainLooper()).postDelayed({
// Your Code
}, 3000)

我的答案与其他答案相似,但是更容易理解 imo。

这是班级名单:

public class Async {


private static final ExecutorService executorService = Executors.newCachedThreadPool();


private static final Handler handler = new Handler(Looper.getMainLooper());


public static <T> void execute(Task<T> task) {
executorService.execute(() -> {
T t = task.doAsync();
handler.post(() -> {
task.doSync(t);
});
});
}


public interface Task<T> {
T doAsync();


void doSync(T t);
}


}

下面是一个如何使用它的例子:

    String url;
TextView responseCodeText;
    

Async.execute(new Async.Task<Integer>() {
        

@Override
public Integer doAsync() {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
return connection.getResponseCode();
} catch (IOException e) {
return null;
}
}


@Override
public void doSync(Integer responseCode) {
responseCodeText.setText("responseCode=" + responseCode);
}
        

});