Android AsyncTask API устарел в Android 11. Каковы альтернативы?

Google не поддерживает Android AsyncTask API в Android 11 и предлагает использовать 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. Это статический внутренний класс Activity. Я ищу то, что будет работать с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) ;
        }     


    }

23 ответа

Решение
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);
    }); 
}

В этом примере используется однопоточный пул, который подходит для записи в БД (или сериализованных сетевых запросов), но если вам нужно что-то для чтения БД или нескольких запросов, вы можете рассмотреть следующую конфигурацию Executor:

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

Вы можете напрямую использовать Executors из java.util.concurrent пакет.

Я также искал об этом и нашел решение в этом посте Android Async API is Deprecated.

К сожалению, сообщение использует 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.

Надеюсь, что это поможет вам. Благодарю вас

Одна из самых простых альтернатив - использовать Thread

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

Если ваш проект поддерживает JAVA 8, вы можете использовать лямбда

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

Согласно документации Android AsyncTaskбыл объявлен устаревшим на уровне API 30, и вместо него предлагается использовать стандартные утилиты параллелизма java.util.concurrent или 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. Используйте функцию с любым 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"
              })
          }
      }
      
    • В Activity или Fragment:

      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"
      })
      

    Использовать viewModelScope или lifecycleScopeдобавьте следующую строку (строки) к зависимостям файла build.gradle приложения:

    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 (см. реализации выше) мы можем назвать это:

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
    }
)

Этот класс используется для выполнения фоновой задачи в фоновом потоке этот класс работа для всех андроид версии API включают Android 11 и этот код та же работа, как AsyncTask с doInBackground и 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();

Android отказался от AsyncTask API в Android 11, чтобы с самого начала избавиться от части проблем.

Так, что теперь?

  • Потоки
  • Исполнители
  • RxJava
  • Слушаемые фьючерсы
  • Сопрограммы

Почему сопрограммы?

Корутины - это способ Kotlin для асинхронного программирования. Поддержка компилятора стабильна, начиная с Kotlin 1.3, вместе с kotlinx.coroutines библиотека -

  • Структурированный параллелизм
  • Неблокирующий, последовательный код
  • Распространение отмены
  • Естественная обработка исключений

Здесь я создал альтернативу для AsyncTask с использованием Coroutines, которые можно использовать так же, как 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. InCase, если вам нужно отправить параметры прохода

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

class, похоже, не будет удален в ближайшее время, но мы все равно просто не рекомендуем его, потому что:

  • Мы не хотели добавлять множество подавляющих аннотаций.
  • Альтернативные решения имеют слишком много шаблонов или, в большинстве случаев, не имеют реального преимущества перед другими.AsyncTask.
  • Мы не хотели заново изобретать велосипед.
  • Мы не хотели бояться того дня, когда его, наконец, уберут.
  • Рефакторинг занимает слишком много времени.

Пример

Просто добавьте файл ниже в свой проект, затем найдите «android.os.AsyncTask" импортирует и заменяет все на пакет, который вы выбрали для указанного файла.

Как вы, возможно, уже знаете, это не имеет большого значения, и в основном это то, что хорошо известноAndroidXбиблиотека делает все время.

Получать AsyncTask.javaфайл по адресу: https://gist.github.com/top-master/0efddec3e2c35d77e30331e8c3bc725c

Принятый ответ хорош. Но ... я не видел реализации метода 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();

На самом деле я написал об этом две истории для Medium:

Первый - это Java и обходной путь с Runnable, второй - решение Kotlin и сопрограмм. Конечно, оба с примерами кода.

Google рекомендует использовать платформу Java Concurrency или Kotlin Coroutines. но Rxjava имеет гораздо больше гибкости и возможностей, чем параллелизм java, поэтому приобрел довольно большую популярность.

Моя индивидуальная замена: https://github.com/JohnyDaDeveloper/AndroidAsync

Он работает только тогда, когда приложение запущено (в частности, действие, которое запланировало задачу), но оно способно обновлять пользовательский интерфейс после завершения фоновой задачи.

Вы можете использовать этот настраиваемый класс как альтернативу 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);
    }
}

Как это использовать? Пожалуйста, следуйте приведенным ниже примерам.

С лямбда-выражениями

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


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

Без лямбда-выражений

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();

Просто замените весь класс этим потоком и поместите его в метод для передачи переменных

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

и во фрагменте добавьте контекст в runOnUiThread() метод:

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

Мой ответ похож на другие, но его легче читать.

Это класс:

      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);
        }
        
    });

Вы можете перейти на следующие подходы в зависимости от ваших потребностей

  • Тема + Обработчик
  • Исполнитель
  • Будущее
  • IntentService
  • JobScheduler
  • RxJava
  • Корутины (Котлин)

[Асинхронные варианты Android]

Это альтернатива классу android.os.AsyncTask:

      abstract class AsyncTask<Params, Progress, Result>(
        private val scope: LifecycleCoroutineScope,
        private var coroutineContext: CoroutineContext = Dispatchers.Default,
) {
    private var job: Job? = null
    private var result: Result? = null

    open fun onPreExecute() {}

    fun execute(params: Params) {
        job = scope.executeAsyncTask(
                onPreExecute = {
                    onPreExecute()
                },
                doInBackground = { publishProgress: suspend (progress: Progress) -> Unit ->
                    result = doInBackGround(publishProgress, params)
                    result
                },
                onPostExecute = {
                    onPostExecute(it)
                },
                onProgressUpdate = {
                    onProgressUpdate(it)
                },
                coroutineContext)
    }

    open fun onPostExecute(result: Result?) {}

    abstract suspend fun doInBackGround(publishProgress: suspend (progress: Progress) -> Unit, params: Params): Result?

    open fun onProgressUpdate(progress: Progress) {}

    fun cancel() = job?.let {
        if (it.isActive) {
            it.cancel()
            onCancelled(result)
        }
    }

    open fun onCancelled(result: Result?) {}

    private fun <Progress, Result> CoroutineScope.executeAsyncTask(
            onPreExecute: () -> Unit,
            doInBackground: suspend (suspend (Progress) -> Unit) -> Result,
            onPostExecute: (Result) -> Unit,
            onProgressUpdate: (Progress) -> Unit,
            coroutineContext: CoroutineContext,
    ) = launch(Dispatchers.Main) {
        onPreExecute()
        val result = withContext(coroutineContext) {
            doInBackground {
                withContext(Dispatchers.Main) { onProgressUpdate(it) }
            }
        }
        onPostExecute(result)
    }
}

WorkManager – это правильный путь

      OneTimeWorkRequest mywork = new OneTimeWorkRequest.Builder(FlipMediaPeriodicWorker.class)
                .setInitialDelay(activity.currentMedia.timing, TimeUnit.SECONDS)
                .build(); 
WorkManager.getInstance(activity).enqueue(mywork);

Вы можете сделать его рекурсивным, чтобы повторять задачи менее 15 минут.

Это мой код

      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();

HandlerThread можно использовать как альтернативу AsyncTask. Это долгоиграющие потоки. Пример HandlerThread приведен ниже:

Вы можете создать два объекта-обработчика. Один из них будет использоваться для отправки сообщения из workerThread в поток пользовательского интерфейса.

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 запускаются за пределами жизненного цикла вашей деятельности, поэтому их необходимо правильно очистить, иначе у вас будут утечки потоков. Вы можете использовать методы quit() или quitSafely() в onDestroy() Activity, чтобы предотвратить утечки потоков.

Документы говорят:

AsyncTask Этот класс устарел на уровне API 30. Вместо этого используйте стандартные утилиты параллелизма java.util.concurrent или 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)

В приведенном выше коде пользователя Attaullah можно ли присвоить определенное имя каждой фоновой задаче, создаваемой с помощью этого класса? Это упростило бы анализ фоновых задач в профилировщике студии Android.

Другие вопросы по тегам