I once came across this AppExecutors class from some github sample project but I forgot where. I just found it very handy as it does multithreading for me. But I'm not sure if I'm executing the code in my Fragment correctly in the following case:
- Initialise a recyclerView with empty ArrayList.
- Run query to database in DiskIO thread.
- Then update adapter's data and the view in Main thread.
Do I need to explicitly wrap the adapter.refreshData(list);
part with the Main Thread Runnable like what I do below?
AppExecutors.java
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class AppExecutors {
private final Executor mDiskIO;
private final Executor mNetworkIO;
private final Executor mMainThread;
private static volatile AppExecutors mInstance;
private AppExecutors(Executor diskIO, Executor networkIO, Executor mainThread) {
this.mDiskIO = diskIO;
this.mNetworkIO = networkIO;
this.mMainThread = mainThread;
}
public static AppExecutors getInstance() {
if (mInstance == null) {
synchronized (AppExecutors.class) {
mInstance = new AppExecutors();
}
}
return mInstance;
}
private AppExecutors() {
this(Executors.newSingleThreadExecutor(), Executors.newFixedThreadPool(3),
new MainThreadExecutor());
}
public Executor diskIO() {
return mDiskIO;
}
public Executor networkIO() {
return mNetworkIO;
}
public Executor mainThread() {
return mMainThread;
}
public static void xDisk(@NonNull Runnable command) {
getInstance().diskIO().execute(command);
}
public static void xNet(@NonNull Runnable command) {
getInstance().networkIO().execute(command);
}
public static void xMain(@NonNull Runnable command) {
getInstance().mainThread().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);
}
}
}
SomeFragment.java
...
void setUpRecyclerView() {
TimeAllowedAdapter adapter = new TimeAllowedAdapter(getContext(), new ArrayList<>());
rcView.setAdapter(adapter);
rcView.setLayoutManager(new LinearLayoutManager(getContext()));
// then fetch data and refresh list
AppExecutors.xDisk(() -> {
List<TimeAllowed> list = AppDatabase.getDatabase(getContext()).timeAllowedDao().getAllTimeAllowed();
AppExecutors.xMain(() -> {
adapter.refreshData(list);
});
});
}
...