fresh digitable

めんどくさかったなってことを振り返ったり振り返らなかったりするための記録

R8でコードシュリンクしつつInstrumentation Testをやる

いろいろハマってしんどかったので雑にまとめておく。

github.com

ことの顛末

  • Instrumentation Testのテストが全然動かない。テストがないとか言われる
  • LogcatをみるとDaggerTestAppComponentDaggerAppComponentにキャストできませんとか言われている。そらそうよ
  • ちょっと書き換えると今度はkotlin.reflect.KProperty0がないとか言ってくる。なんでや
  • キャストするコードは書いていない。明にキャストしたり、安全キャスト(as?)をやったりしてみるがなぜかDaggerAppComponentにキャストされようとしてクラッシュする。Kotlinバイトコードデコンパイルしてみても特に変なところはない。dexにする段階で何か変わってしまったのか?と思ってapkファイルの中のバイトコードを確認すると、check-castという命令が追加されており、ここでDaggerAppComponent型かどうかのチェックがされていた。
  • R8の最適化が効いたのかな?と思って最適化させない命令(-dontoptimize)を付けると今度はkotlin.reflect.KProperty0が無いといわれる。またか。だがdexのバイトコードにはcheck-castがなくなっていた。
  • そうかそれならってことで今度は-keepkotlin.reflect以下のクラスを残すことにした。すると今度は別のクラスが無いという話になったので、一応効いているということが分かった。ないといわれたクラスを片っ端からkeepで残すことにしていったらテストが動くようになった。

敗因

  • R8の最適化が効いてたのが分からなかった
  • テスト用のアプリにクラスが足りないのかと思って(MockKを足したりしたので)いろいろ足してみたけど効果が無くて、本当はテスト対象側にそのクラスが無いといけなかった様子
  • 最初はDaggerの方を疑っていたが結果的に関係なかった
  • testSharedディレクトリを追加したあたりが悪かったのかと思って指定を付けたり外したりしてみていたけど結果的に関係なかった(ちょっとずつ変更しながら動きを見ていればよかった)
  • コードシュリンクしないとビルドできない(かといってMultidexにするほどでもない)

SavedStateHandleを使ってLiveDataの値を保存する

ViewModelが持っているLiveDataの値をインスタンスステートとして保持したいとき、androidxのlifecycle-viewmodel-savedstateライブラリを使う。fragment 1.2.0activity 1.1.0を入れているとその依存関係としてsavedstateも入ってくる*1。この記事ではlifecycle-viewmodel-savedstate 2.2.0での挙動を前提とする。

本当はDIを使ってViewModelSavedStateHandleを注入するところまでが大変なのだが、いろんなブログや本に書いてあるので割愛する。タイトルの通りLiveDataの値を保存したいときはまず、ViewModelに注入されたSavedStateHandleからgetLiveData()を使ってMutableLiveDataを取り出す。

val data: MutableLiveData<Hoge> = savedStateHandle.getLiveData("key_data")

こうすると、SavedStateHandle内部に定義してあるSavingStateLiveDataというクラスのインスタンスが内部キャッシュから返されるか、そこになければ生成される。このSavingStateLiveDatasetValue()の都度、SavedStateHandle.set()相当の処理をやってくれる。つまり、上で書いたdataに対しては

data.value = someHogeValue  // postValue()も大丈夫なはず

をやるだけでよい。これでいつonSaveInstanceState()が呼ばれても大丈夫。いうまでもないが、LiveData以外のプロパティに対しては別途対応が必要になる。

danger-kotlinをやっていこう

DangerfileをKotlin scriptで書けるというので試してみている。今の時点ではver. 0.5.1でWIPとのこと。

github.com

Github Actionsで実際に動かしてみているのだが、これまでDangerで使っていたようなプラグインが使えるようにはなっていないようで、今のところ簡単ではない。それでもkotlin力(ちから)に自信があれば自分でプラグインを書いてもよいと思う。

DangerfileをKotlin scriptで書くにあたり、コードの自動補完が効くようにしたい。開発環境がMacOSLinuxの場合はREADMEに書いてある通りに進めればいいのであろうが、私はWindowsで作業しているので少々難儀した。

READMEにはまず最初にdanger-kotlinをマシンにインストールせよと書いてあるので、Makefileを読みビルドの手順をWindowsに置き換えて実行しようとしたのだが、Windowsだとビルドが通らないようになっていた。その後少々考えて、ダメ元でWSL2の上でJarをビルドし、これに対してパスを通したところ、自動補完が効くようになった*1

あとはKotlin scriptの設定がどこにあるか分からなかった。Android Studio 4.0では設定のOther Settings > Kotlin compilerの下の方に目当てのものがある。

プラグインをどうにかしたい。gradleでjrubyやgemを使えるようにするプラグインはあるので、Kotlin scriptでも何とかして似たようなことができないだろうか。無職になり有り余る時間ができてしまったので挑戦してみてもいいかもしれない。

akihito104.hatenablog.com

*1:インタフェースはちゃんと見えているから自動補完だけなら大丈夫ということだろうか