Android AsyncTask API mencela di Android 11. Apa alternatifnya?

21

EDIT : Pertanyaan ini bukan duplikat sebagai

  1. Hanya beberapa hari yang lalu AOSP berkomitmen pada penghentian telah dilakukan.
  2. Pertanyaan lain adalah tentang menggunakan AsyncTaskLoader di atas AsyncTask.


Google mencela Android AsyncTask API di Android 11 dan menyarankan untuk menggunakannya java.util.concurrentsebagai gantinya. Anda dapat melihat komit di sini

 *
 * @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> {

Jika Anda mempertahankan basis kode yang lebih lama dengan tugas-tugas tidak sinkron di Android, Anda mungkin harus mengubahnya di masa mendatang. Pertanyaan saya adalah apa yang seharusnya menjadi pengganti yang tepat dari cuplikan kode yang ditunjukkan di bawah ini java.util.concurrent. Ini adalah kelas dalam statis dari suatu Kegiatan. Saya mencari sesuatu yang akan berhasilminSdkVersion 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) ;
        }     


    }
Zeeshan
sumber
5
"Sudah usang" berarti bahwa Google merekomendasikan Anda untuk pindah ke hal lain. Itu tidak berarti bahwa kelas akan dihapus dalam waktu dekat. Secara khusus, AsyncTasktidak dapat dihapus tanpa merusak kompatibilitas.
CommonsWare
2
@ Style-7 tidak.
EpicPandaForce
Tidak ada yang namanya "kelas dalam statis". Maksudmu kelas bersarang statis.
beroal

Jawaban:

22
private WeakReference<MyActivity> activityReference;

Baguslah bahwa itu sudah usang, karena WeakReference<Context>selalu merupakan peretasan, dan bukan solusi yang tepat .

Sekarang orang akan memiliki kesempatan untuk membersihkan kode mereka.


AsyncTask<String, Void, MyPojo> 

Berdasarkan kode ini, Progresssebenarnya tidak diperlukan, dan ada Stringinput + MyPojooutput.

Ini sebenarnya cukup mudah dilakukan tanpa menggunakan 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);
            });
        });
    }
}

Bagaimana cara melewati String? Seperti itu:

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

Dan

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

Contoh ini menggunakan kumpulan utas tunggal yang baik untuk penulisan DB (atau permintaan jaringan serial), tetapi jika Anda menginginkan sesuatu untuk DB dibaca atau beberapa permintaan, Anda dapat mempertimbangkan konfigurasi Pelaksana berikut:

private static final Executor THREAD_POOL_EXECUTOR =
        new ThreadPoolExecutor(5, 128, 1,
                TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
EpicPandaForce
sumber
Saya menerima pesan kesalahan executor.post. Tidak dapat menyelesaikan metode
Kris B
@ KrisB rupanya disebut execute()bukanpost()
EpicPandaForce
Apakah Anda tahu apakah boleh melakukan Contextini? Saya tahu bahwa memasukkan Contextke dalam AsyncTaskadalah salah satu masalahnya.
Kris B
Anda masih perlu menjalankan ini dalam ViewModel, mempertahankan fragmen, singleton, atau apa pun, seperti yang biasa Anda lakukan dengan apa pun yang tidak sinkron di Android.
EpicPandaForce
1
newSingleThreadExecutorlebih baik untuk menulis, tetapi Anda harus menggunakan THREAD_POOL_EXECUTORdi akhir posting untuk membaca database.
EpicPandaForce
3

Google merekomendasikan penggunaan kerangka kerja Java Concurrency atau Kotlin Coroutines. tetapi Rxjava akhirnya memiliki lebih banyak fleksibilitas dan fitur kemudian java concurrency sehingga memperoleh popularitas yang cukup tinggi.

Wahab Khan Jadon
sumber