API AsyncTask không dùng nữa trong Android 11. Các lựa chọn thay thế là gì?


21

EDIT : Câu hỏi này không phải là một bản sao

  1. Chỉ vài ngày trở lại AOSP cam kết về khấu hao đã được thực hiện.
  2. Câu hỏi khác là về việc sử dụng AsyncTaskLoader trên AsyncTask.


Google đang phản đối API AsyncTask của Android trong Android 11 và đề nghị sử dụng java.util.concurrentthay thế. bạn có thể kiểm tra cam kết ở đây

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

Nếu bạn đang duy trì một cơ sở mã cũ hơn với các tác vụ không đồng bộ trong Android, bạn có thể sẽ phải thay đổi nó trong tương lai. Câu hỏi của tôi là những gì nên được thay thế phù hợp của đoạn mã được hiển thị dưới đây bằng cách sử dụng java.util.concurrent. Nó là một lớp bên trong tĩnh của một Hoạt động. Tôi đang tìm kiếm một cái gì đó sẽ làm việc vớiminSdkVersion 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
"Không dùng nữa" có nghĩa là Google đang khuyến nghị bạn chuyển sang một thứ khác. Điều đó không có nghĩa là lớp học sẽ sớm bị xóa. Đặc biệt, AsyncTaskkhông thể được loại bỏ mà không phá vỡ tính tương thích ngược.
CommonsWare


2
@ Style-7 thì không.
EpicPandaForce

Không có thứ gọi là "lớp bên trong tĩnh". Bạn có nghĩa là một lớp lồng nhau tĩnh.
ngày

Câu trả lời:


22
private WeakReference<MyActivity> activityReference;

Điều tốt là nó không được chấp nhận, bởi vì WeakReference<Context>nó luôn luôn là một hack, và không phải là một giải pháp thích hợp .

Bây giờ mọi người sẽ có cơ hội để vệ sinh mã của họ.


AsyncTask<String, Void, MyPojo> 

Dựa trên mã này, Progressthực sự không cần thiết, và có Stringđầu vào + MyPojođầu ra.

Điều này thực sự khá dễ thực hiện mà không cần sử dụng 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);
            });
        });
    }
}

Làm thế nào để vượt qua trong Chuỗi? Thích như vậy:

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

Ví dụ này đã sử dụng một nhóm luồng đơn, tốt cho việc ghi DB (hoặc các yêu cầu mạng được tuần tự hóa), nhưng nếu bạn muốn một cái gì đó cho DB đọc hoặc nhiều yêu cầu, bạn có thể xem xét cấu hình Executor sau:

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

Tôi đang nhận được một lỗi trên executor.post. Phương pháp không thể giải quyết
Kris B

@KrisB rõ ràng nó được gọi execute()thay vìpost()
EpicPandaForce

Bạn có biết nếu bạn chấp nhận Contextđiều này không? Tôi biết rằng truyền Contextvào AsyncTasklà một trong những vấn đề của nó.
Kris B

Bạn vẫn cần chạy cái này trong ViewModel, giữ lại đoạn, singleton hoặc bất cứ thứ gì khác, như bạn thường làm với mọi thứ không đồng bộ trong Android.
EpicPandaForce

1
newSingleThreadExecutorlà tốt hơn để viết, nhưng bạn chắc chắn nên sử dụng THREAD_POOL_EXECUTORở cuối bài để đọc cơ sở dữ liệu.
EpicPandaForce

3

Google khuyến nghị sử dụng khung đồng thời của Java hoặc Corlinines của Kotlin. nhưng Rxjava kết thúc để có tính linh hoạt và tính năng cao hơn nhiều so với java đồng thời nên đã trở nên khá phổ biến.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.