Paging Library

10月9日水曜日、晴れ

Android Architecture Components というフレームワークがある。これを使うと画面を回転させたり設定が変わったりしてアクティビティオブジェクトが再生成されても(finish を呼び出すまでは)データが保持されるだとか(ViewModel の機能)、データの変更が UI の更新と同期するいわゆるデータバインディングを補助する LiveData だとかいったコンポーネントが追加されている。

この中に Paging Library というものがあって、いま担当しているアプリのメイン画面をこれで置き換えてみよう、という提案をしている。(そして二度のプレゼンを通して今日、許可を取りつけた)

通ったのはいいんだけれど、 LiveData に DataSource に PagedList に Builder に……、とにかく登場人物が多くてなかなか理解が進まない。プレゼンのために一週間ほど時間をかけてサンプルを作ったりしている僕でこれなのだから、完成コードだけ見せられても(そのレビューを押しつけられる)チームメンバーはもっと辛いだろう。

そういうわけで、いきなりの全体でなくて小さなところから積み上げていく感じのサンプルが作れないかと考えて先ほど取り掛かってみた──ところ関係ないところでつまづいた。

LivePagedListBuilder を使わずに PagedList.Builder で、固定長の DataSource を参照する PagedList を作ろうとしたんだけれど、 setFetchExecutor と setNotifyExecutor を呼びだして有効な Executor を設定せねばならない、と。(それぞれバックグラウンドでのデータ取得と取得結果をフォアグラウンドで UI に反映する役目)

Android のソースコードにはこんな TODO が書かれている。

       @WorkerThread
       @NonNull
       public PagedList<Value> build() {
           // TODO: define defaults, once they can be used in module without android dependency
           if (mNotifyExecutor == null) {
               throw new IllegalArgumentException("MainThreadExecutor required");
           }
           if (mFetchExecutor == null) {
               throw new IllegalArgumentException("BackgroundThreadExecutor required");
           }

ええい、デフォルトを定義しておいてくれ!(LivePagedListBuilder は、これらを内部定義の Executor で設定してくれる。でもパッケージの外からはこれらにアクセスできない。いじわる)

仕方ないのでじゃあ Executor を定義してみるか──と思いたち(こういうことを始めるからどんどん時間が過ぎる)、書き上げたのがこちら。

Kotlin では Object wait/notifyAll 方式の待ち合わせができなくなっているって知らなかった。(代わりに java.util.concurrent.lock の Lock インターフェースを使うようだ)(ReentrantLock は Lock インターフェースの実装)

Lock インターフェースからは newCondition() メソッドを介して条件変数が取り出せるようになっている。条件変数って pthread で見たやつだ! 待ち合わせが待機と不可分操作になっているやつ。

……ということは、古き良き wait/notifyAll 方式の待ち合わせには、なにか問題が、あるんだろうねえ……(待ち合わせとシグナルが不可分操作にならないとか? あるいは synchronized と Object の組み合わせに何か問題が?)

思いがけず知識に揺さぶりがかかり、基礎を自分で組み立てることって(車輪の再発明と言われようと)大事だなあと思いを新たにしている。

この記事が気に入ったらサポートをしてみませんか?