我是一名从Java转到Kotlin的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());
}
});
它的效果非常好,甚至谷歌在其许多Github Android示例中也有类似的东西。
所以我一直在使用回调函数,但是现在我已经厌倦了嵌套的回调函数,我想摆脱它们。为此,我可以在我的xxxViewModel
中编写以下代码:
executors.diskIo().execute(() ->
{
int result1 = repo.fetch();
String result2 = repo2.fetch(result1);
executors.mainThread().execute(() -> myLiveData.setValue(result2));
});
在使用上,Kotlin的协程和Executor
有何不同?从我所看到的,它们最大的优势是能够以顺序代码的方式使用异步代码。但是,正如您可以从上面的代码示例中看到的那样,我也可以用Executor
做到这一点。那么我错过了什么?如果我从Executor
转换到协程,我会得到什么好处呢?