Android 11'de kullanımdan kaldırılan Android AsyncTask API'sı Alternatifler nelerdir?


21

DÜZENLEME : Bu soru aşağıdaki gibi bir kopya değil

  1. Sadece birkaç gün önce AOSP'nin kullanımdan kaldırılması taahhüdü yapıldı.
  2. Diğer soru, AsyncTask üzerinden AsyncTaskLoader'ı kullanmakla ilgilidir.


Google, Android 11'de Android AsyncTask API'sını kullanımdan kaldırıyor ve java.util.concurrentbunun yerine kullanılmasını öneriyor . taahhüdü buradan kontrol edebilirsiniz

 *
 * @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'de eşzamansız görevlere sahip daha eski bir kod tabanını koruyorsanız, gelecekte bunu değiştirmeniz gerekecektir. Benim sorum, aşağıda gösterilen kod snippet'inin uygun şekilde değiştirilmesi gerektiğidir java.util.concurrent. Bir Faaliyetin statik bir iç sınıfıdır. Birlikte çalışacak bir şey arıyorumminSdkVersion 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) ;
        }     


    }

5
"Kullanımdan kaldırıldı", Google'ın başka bir şeye taşınmanızı önerdiği anlamına gelir. Bu, sınıfın yakın zamanda kaldırılacağı anlamına gelmez. Özellikle AsyncTaskgeriye dönük uyumluluk bozulmadan çıkarılamaz.
CommonsWare


2
@ Style-7 değil.
EpicPandaForce

"Statik iç sınıf" diye bir şey yoktur. Statik iç içe bir sınıf demek istediniz.
beroal

Yanıtlar:


22
private WeakReference<MyActivity> activityReference;

İyi bir kurtuluş, çünkü WeakReference<Context>her zaman bir hackti ve uygun bir çözüm değildi .

Artık insanlar kodlarını sterilize etme şansına sahip olacaklar.


AsyncTask<String, Void, MyPojo> 

Bu koda dayanarak Progress, aslında gerekli değildir ve bir Stringgiriş + MyPojoçıkış vardır.

AsyncTask'ı kullanmadan bunu gerçekleştirmek oldukça kolaydır.

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

Dize nasıl geçirilir? Şöyle ki:

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

Ve

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

Bu örnekte, DB yazma (veya serileştirilmiş ağ istekleri) için iyi olan tek iş parçacıklı bir havuz kullanılmıştır, ancak DB okumaları veya birden çok istek için bir şey istiyorsanız, aşağıdaki Yürütücü yapılandırmasını göz önünde bulundurabilirsiniz:

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

Hata alıyorum executor.post. Yöntem çözülemiyor
Kris B

@KrisB görünüşe denir execute()yerinepost()
EpicPandaForce

Buna geçmenin iyi olup olmadığını biliyor musun Context? Biliyorum ki Contextiçeri girmenin AsyncTaskbir sorunu vardı.
Kris B

Bunu normalde Android'de zaman uyumsuz bir şeyde yaptığınız gibi bir ViewModel'de, tutulan parçada, singletonda veya başka bir şeyde çalıştırmanız gerekir.
EpicPandaForce

1
newSingleThreadExecutoryazarlar için daha iyidir, ancak kesinlikle THREAD_POOL_EXECUTORveritabanı okumaları için yazının sonunda kullanmalısınız .
EpicPandaForce

3

Google, Java'nın Concurrency çerçevesini veya Kotlin Coroutines'i kullanmanızı önerir. ancak Rxjava, java eşzamanlılığından çok daha fazla esnekliğe ve özelliğe sahip olacak, bu yüzden biraz popülerlik kazandı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.