1. ホーム
  2. java

[解決済み] Android 11でAsyncTask APIが非推奨になりました。代替となるAPIは何ですか?

2022-05-10 03:52:08

質問

Google は Android 11 で Android AsyncTask API を非推奨とし、その代わりに 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 . これは、Activityの静的な内部クラスです。私は何かで動作するように探しています 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) ;
        }     


    }

どのように解決するのですか?

<ブロッククオート
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);
            });
        });
    }
}

Stringはどのように渡すのですか?こんな感じ。

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