Android AsyncTask API กำลังลดลงใน Android 11 ทางเลือกคืออะไร?


21

แก้ไข : คำถามนี้ไม่ซ้ำกันว่า

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

หากคุณกำลังบำรุงรักษา codebase ที่เก่ากว่าด้วยงานอะซิงโครนัสใน 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) ;
        }     


    }

5
"เลิกใช้แล้ว" หมายความว่า Google แนะนำให้คุณย้ายไปใช้อย่างอื่น ไม่ได้หมายความว่าชั้นเรียนจะถูกลบในเวลาใด ๆ ในไม่ช้า โดยเฉพาะอย่างยิ่งAsyncTaskไม่สามารถลบออกได้โดยไม่ทำลายความเข้ากันได้ย้อนหลัง
CommonsWare

การทำสำเนาที่เป็นไปได้ของIsyncTask เลิกใช้แล้วในขณะนี้ด้วย AsyncTaskLoader
สไตล์ -7

2
@ Style-7 มันไม่ได้เป็น
EpicPandaForce

ไม่มีสิ่งเช่น "ชั้นในคงที่" คุณหมายถึงคลาสที่ซ้อนกันคงที่
beroal

คำตอบ:


22
private WeakReference<MyActivity> activityReference;

กำจัดที่ดีว่ามันเลิกเพราะWeakReference<Context>มักจะสับและไม่ได้เป็นวิธีการแก้ปัญหาที่เหมาะสม

ตอนนี้ผู้คนจะมีโอกาสล้างรหัสของพวกเขา


AsyncTask<String, Void, MyPojo> 

ตามรหัสProgressนี้ไม่จำเป็นจริง ๆ และมีStringinput + MyPojooutput

นี่เป็นเรื่องง่ายที่จะสำเร็จโดยไม่ต้องใช้ 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 หรือการร้องขอหลายครั้งคุณสามารถพิจารณาการกำหนดค่า Executor ต่อไปนี้:

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

executor.postฉันได้รับข้อผิดพลาดใน ไม่สามารถแก้ไขวิธีการได้
Kris B

@KrisB เห็นได้ชัดว่ามันถูกเรียกexecute()แทนpost()
EpicPandaForce

คุณรู้หรือไม่ถ้าตกลงContextในเรื่องนี้ ฉันรู้ว่าผ่านContextเข้าไปAsyncTaskเป็นหนึ่งในปัญหาของมัน
Kris B

คุณยังคงต้องเรียกใช้สิ่งนี้ใน ViewModel, fragment ที่เก็บไว้, ซิงเกิลตัน, หรืออะไรก็ตามตามที่คุณต้องการด้วย async ใน Android
EpicPandaForce

1
newSingleThreadExecutorดีกว่าสำหรับการเขียน แต่คุณควรใช้THREAD_POOL_EXECUTORในตอนท้ายของการโพสต์เพื่ออ่านฐานข้อมูล
EpicPandaForce

3

Google แนะนำให้ใช้เฟรมเวิร์กการทำงานพร้อมกันของ Java หรือ Kotlin Coroutines แต่ท้าย Rxjava มีความยืดหยุ่นและฟีเจอร์ต่าง ๆ มากขึ้นจากนั้นการทำงานพร้อมกันของ Java จึงได้รับความนิยมค่อนข้างมาก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.