私はKotlinに、Javaからの切り替えAndroidの開発者だし、私はそれは非常に有望に見えるので、非同期コードを処理するためにコルーチンを使用することを計画しています。
Javaで戻る、私が使用した非同期コード処理するために、Executor
離れてUIスレッドから、別のスレッドでのコードの時間のかかる部分を実行するためのクラスを。私が持っていたAppExecutors
私は、私の中に注入されたことをクラスxxxRepository
のセットを管理するためのクラスをExecutor
。それはこのように見えました:
public class AppExecutors
{
private static class DiskIOThreadExecutor implements Executor
{
private final Executor mDiskIO;
public DiskIOThreadExecutor()
{
mDiskIO = Executors.newSingleThreadExecutor();
}
@Override
public void execute(@NonNull Runnable command)
{
mDiskIO.execute(command);
}
}
private static class MainThreadExecutor implements Executor
{
private Handler mainThreadHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(@NonNull Runnable command)
{
mainThreadHandler.post(command);
}
}
private static volatile AppExecutors INSTANCE;
private final DiskIOThreadExecutor diskIo;
private final MainThreadExecutor mainThread;
private AppExecutors()
{
diskIo = new DiskIOThreadExecutor();
mainThread = new MainThreadExecutor();
}
public static AppExecutors getInstance()
{
if(INSTANCE == null)
{
synchronized(AppExecutors.class)
{
if(INSTANCE == null)
{
INSTANCE = new AppExecutors();
}
}
}
return INSTANCE;
}
public Executor diskIo()
{
return diskIo;
}
public Executor mainThread()
{
return mainThread;
}
}
それから私は私の中で、このようないくつかのコードを書くことができましたxxxRepository
:
executors.diskIo().execute(() ->
{
try
{
LicensedUserOutput license = gson.fromJson(Prefs.getString(Constants.SHAREDPREF_LICENSEINFOS, ""), LicensedUserOutput.class);
/**
* gson.fromJson("") returns null instead of throwing an exception as reported here :
* https://github.com/google/gson/issues/457
*/
if(license != null)
{
executors.mainThread().execute(() -> callback.onUserLicenseLoaded(license));
}
else
{
executors.mainThread().execute(() -> callback.onError());
}
}
catch(JsonSyntaxException e)
{
e.printStackTrace();
executors.mainThread().execute(() -> callback.onError());
}
});
それは非常に良い仕事をし、Googleも、彼らの多くのGithubのAndroidレポ例で同様の何かを持っています。
だから私は、コールバックを使用していました。しかし、今私は、ネストされたコールバックの疲れと私はそれらを取り除くしたいと思います。そうするために、私は自分で書くことができますxxxViewModel
例えば:
executors.diskIo().execute(() ->
{
int result1 = repo.fetch();
String result2 = repo2.fetch(result1);
executors.mainThread().execute(() -> myLiveData.setValue(result2));
});
どのようにあるUSAGEは Kotlinのコルーチンの使用状況は異なりますか?私が見たものから、彼らの最大の利点は、シーケンシャルコードスタイルで非同期コードを使用することができることです。しかし、私はちょうどそれを行うことができる午前Executor
あなたが右上記のコードサンプルから見ることができるように、。だから私はここで何をしないのですか?私はからスイッチに何を得るでしょうExecutor
コルーチンに?
私のアプリケーションでコルーチンを使用しながら、さてさて、私は自分で答えを見つけました。リマインダーのために、私はの違いを探していた用法。私は順番に非同期のコードを実行することができたExecutor
と私はそれがコルーチンの最大の利点であったことをどこでも見たので、コルーチンに切り替えてからの大きな利点は何ですか?
まず、あなたはそれがあることを私の最後のサンプルから見ることができるxxxViewModel
非同期タスクは、上で実行されていたものをスレッドその選択されます。これは私の意見設計上の欠陥です。ViewModelにはそれを知っていて、さらに少ないスレッドを選択するの責任を持つべきではありません。
今コルーチンで、私はこのような何かを書くことができます。
// ViewModel
viewModelScope.launch {
repository.insert(Title(title = "Hola", id = 1))
myLiveData.value = "coroutines are great"
}
// Repository
suspend fun insert(title: Title)
{
withContext(Dispatchers.IO)
{
dao.insertTitle(title)
}
}
私たちは、それはDispatcherはタスクではなく、ビューモデルを管理しているものを選ぶという機能を一時停止していることを見ることができます。それはリポジトリにこのロジックをカプセル化するように私はこの非常に良くを見つけます。
また、コルーチンキャンセルはよりもはるかに簡単であるExecutorService
キャンセル。ExecutorService
本当にキャンセルのために作られていません。それは持っているshutdown()
方法を、それは、すべてのタスクをキャンセルさせていただきますExecutorService
、我々はキャンセルする必要はありません1つだけ。私たちの範囲は場合はExecutorService
、私たちのviewmodelのよりも大きい、我々はねじ込みます。コルーチンと、それはあなたもそれを気にする必要はありませんので、簡単です。あなたが使用している場合viewModelScope
(あなたがすべきである)、それはのviewmodelの中で、この範囲内のすべてのコルーチンがキャンセルされますonCleared()
自体によって、方法。
結論として、コルーチンはよりAndroidのコンポーネントとはるかに統合持ちExecutorService
、より良いとクリーンな管理機能を、はい、彼らは軽量です。私はそれは、Android上のキラー引数であるとは思わない場合でも、それは、より軽量のコンポーネントを持っていることはまだ良いことです。