Java版RemoteMediatorのコーディングとその利用方法
Kotlin版の紹介が終了したので、Java版に話を移します。
JavaではListenableFutureRemoteMediatorを継承
Java版のPhoneRemoteMediatorはリスト4のようになります。
@OptIn(markerClass = ExperimentalPagingApi.class)
public class PhoneRemoteMediator extends ListenableFutureRemoteMediator<Integer, Phone> { // (1)
private final AppDatabase _db;
public PhoneRemoteMediator(AppDatabase db) {
_db = db;
}
@NotNull
@Override
public ListenableFuture<MediatorResult> loadFuture(@NonNull LoadType loadType, @NonNull PagingState<Integer, Phone> pagingState) { // (2)
//戻り値変数を用意。
ListenableFuture<MediatorResult> returnVal;
PhoneDAO phoneDAO = _db.createPhoneDAO();
ExecutorService executorService = Executors.newSingleThreadExecutor();
try {
//loadTypeで処理を分岐。
switch(loadType) {
//データクリアの場合。
case REFRESH:
ListenableFuture<Integer> deleteResultFuture = phoneDAO.deleteAll();
deleteResultFuture.get();
returnVal = Futures.immediateFuture(new MediatorResult.Success(false)); // (3)
break;
//データの末尾を検知した場合。
case PREPEND:
returnVal = Futures.immediateFuture(new MediatorResult.Success(true)); // (4)
break;
//データの先頭を検知した場合。
default:
//データベース内のidの最大ちからstartKeyとendKeyを決定。
ListenableFuture<Long> lastIdFuture = phoneDAO.findLastId();
Long lastIdL = lastIdFuture.get();
long lastId = 0;
if(lastIdL != null) {
lastId = lastIdL;
}
long startKey = lastId + 1;
long endKey = startKey + pagingState.getConfig().pageSize - 1;
//ネット上から追加のリストを取得しデータベースに格納。
PhoneListFetcher phoneListFetcher = new PhoneListFetcher(startKey, endKey);
Future<List<Phone>> phoneListFuture = executorService.submit(phoneListFetcher);
List<Phone> phoneList = phoneListFuture.get();
ListenableFuture<List<Long>> insertResultFuture = phoneDAO.insertPhoneList(phoneList);
insertResultFuture.get();
//ネット上からリストサイズを取得してリスに続きがあるかどうかを判定。
PhoneListSizeFetcher phoneListSizeFetcher = new PhoneListSizeFetcher();
Future<Integer> listSizeFuture = executorService.submit(phoneListSizeFetcher);
int listSize = listSizeFuture.get();
MediatorResult result;
if (endKey < listSize) {
result = new MediatorResult.Success(false);
}
else {
result = new MediatorResult.Success(true);
}
returnVal = Futures.immediateFuture(result); // (5)
break;
}
}
catch(Exception ex) {
returnVal = Futures.immediateFuture(new MediatorResult.Error(ex)); // (6)
}
return returnVal;
}
}
基本的には、リスト2のコードをJavaに置き換えた内容になっています。ただし、大きな違いがリスト4の(1)にあるように、RemoteMediatorではなくListenableFutureRemoteMediatorを継承することです。その理由は非同期処理に対応するためで、前回のリスト5でPhonePagingSourceの親クラスをListenableFuturePagingSourceとしたのと同様です。
それに伴い、load()メソッドもその名称が変わり、(2)のようにloadFuture()となります。また、その戻り値もMediatorResultをListenableFutureでラップしたListenableFuture<MediatorResult>となります。
そのため、戻り値のreturnValに値を格納する各コードは(3)(4)(5)および(6)のように、Futures.immediateFuture()を実行してListenableFutureでラップしています。このコードパターンも、前回のリスト5と同様です。
リポジトリではPagerコンストラクタの第3引数にとして渡す
最後に、リポジトリでのRemoteMediatorを利用するコードパターンのJava版を紹介します。これは、リスト5のようになります。
@OptIn(markerClass = ExperimentalPagingApi.class)
public Pager<Integer, Phone> getAllPhoneListPager() {
PhoneDAO phoneDAO = _db.createPhoneDAO();
PagingConfig pagingConfig = new PagingConfig(ITEMS_PER_PAGE);
PhoneRemoteMediator phoneRemoteMediator = new PhoneRemoteMediator(_db);
Pager<Integer, Phone> phoneListPager = new Pager<>(pagingConfig, null, phoneRemoteMediator, () -> phoneDAO.findAll());
return phoneListPager;
}
これも、リスト5のコードをJavaコードに置き換えたコードとなっており、特に問題ないと思います。
まとめ
Android Jetpackについて紹介していく本連載の第14回は、いかがでしたでしょうか。
今回は、ページングライブラリを利用して、ネット上にあるリストデータをデータベースにキャッシュしながらページングする方法を紹介しました。次回は、ナビゲーションを紹介します。
