- blog - https://blog.dr1009.com/ - R8 compatibility FAQ - https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md
JavaからKotlinに書き換えてハマる話Kotlin Fest Reject Conference 2019 [非公式]@DeNA
View Slide
自己紹介Name : Koji WakamiyaWork : Studyplus, inc.Github : @koji-1009Twitter : @D_R_1009Blog : https://blog.dr1009.com/Kotlin歴は2年ちょっと2
MISSION「学ぶ喜びをすべての人へ」多くの人がStudyplusを通じて学習のきっかけを見つけ、学習を楽しく継続できることを実現する。3
StudyplusアプリのKotlin化● コミット履歴によると2017年12月ごろにKotlinを追加○ 当時のminSDKは15○ 2019年9月現在は21● 話者がスタディプラスに参加したのは2018年9月○ 本日の話は2018年9月から2019年9月に体験した物事がベースになってます4
JavaからKotlinへの書き換え状況● 2018年7月末○ Java : 75,000行○ Kotlin : 20,000行5
JavaからKotlinへの書き換え状況● 2019年8月末○ Java : 19,000行○ Kotlin : 72,000行6
JavaからKotlinへの書き換え状況● 2019年9月9日(本日)○ Java : 15,000行○ Kotlin : 74,000行7
JavaからKotlinへの書き換え状況82018年7月2019年8月末2019年9月9日
お品書き● 2つのインスタンス化メソッドとNonNull● 共通データクラス(神データクラス)● 使い回されるデータクラス● onActivityResult● R89
2つのインスタンス化メソッドとNonNull状況:AFragment.newInstance(Hoge hoge);AFragment.newInstance(Hoge hoge, Fuga fuga);問題:1. hogeがNonNull/Nullableのケースが存在する2. fugaをNonNullとして扱わなければならないが、レアケースでしか利用されない10
2つのインスタンス化メソッドとNonNull防ぐためには?:1. インスタンス化メソッドの引数は必ずクラス内の利用箇所全てを確認する2. lateinit varによる対応は市場クラッシュを引き起こすので、valの利用を必ず検討する11
共通データクラス(神データクラス)状況:1. 複数のSNS連携完了を伝えるデータクラスが1つにまとめられている2. 複数の型要素があるJsonをパースするため、全要素を持つ1つのデータクラスが作成されている問題:1. 防御的にNullableで宣言して、動作を見ながら確認する必要が生じる2. GsonからMoshiへ移行した際に、JsonDataExceptionの恐れがある12
共通データクラス(神データクラス)防ぐためには?:1. @NonNull/@Nullableアノテーションをデータクラスにつける2. 抽象クラスを利用するなど、全部入りクラス作成を避ける13
使い回されるデータクラス状況:複数のビジネスロジックがデータクラスを使いまわした結果、複数のコンストラクタがあるデータクラスが作成されていた問題:1. 複数のクラスに応じたプロパティ追加の結果、NonNullの保証がない2. 複数のコンストラクタが存在する14
使い回されるデータクラスどう対応するか:基本的にKotlin Data Classの利用を行うが、いくつかアプローチがある1. secondary constructorを利用する2. 利用クラスをKotlin化し、名前付き引数を利用する3. Java + @JvmOverloadsの利用も可能だが、引数のパターンによっては単に複雑性をますため注意15
onActivityResult状況:onActivityResult処理が含まれているActivityをKotlin化したところ、dataがnullのケースでクラッシュが発生問題:1. onActivityResultは古いAPIのためアノテーションが付与されていない2. Nullableな値をNonNullとしてメソッドをoverrideしても、エラーは発生しない16
onActivityResultどう対応するか:1. あらかじめJavaのonActivityResultメソッドをアノテーション付きのメソッドに書き換えてからKotlin化する2. Kotlin化されたコードのonActivityResultメソッドを置換機能で全て修正する※support lib 27.1.1のDiffUtil.ItemCallbackを、support libのpathがおかしい状態で追加した時にも同じような問題が発生することがある(28.0.0以降ではNonNull扱いとなっているため問題なし)17
R8状況:R8対応が必要になるケースが増えた(AGP3.4以上でデフォルト有効化、Kotlin Coroutines 1.3系やOkHttp4系などのビルドクラッシュ)問題:1. Gson使っていると(そのままでは)ダメa. https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.mdb. ビルド時ではなく実行時に問題が見つかるため、発見が難しい18
R8どう対応するか:0. 対応しない(各種ライブラリ対応を待つ)1. .proファイルの指定を頑張る2. データクラスのKotlin化 + Moshi-Codegenへ移行する※なおKotlin Coroutinesを利用している場合には、Dispatchers.Main初期化遅延問題のためR8移行が望ましい19