Android AsyncTask API устарел в Android 11. Какие есть альтернативы? - PullRequest
1 голос
/ 08 ноября 2019

РЕДАКТИРОВАТЬ : Этот вопрос не является дубликатом, так как

  1. Всего пару дней назад было выполнено принятие AOSP при устаревании.
  2. Другой вопрос касается использования AsyncTaskLoader поверх AsyncTask.

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. Это статический внутренний класс Деятельности. Я ищу то, что будет работать с 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) ;
        }     


    }

1 Ответ

4 голосов
/ 08 ноября 2019
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>());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...