おじゃまぷよ系エンジニアメモ

主にスマホネイティブ関連Tips。たまにWebも書きたい。お腹はぷよぷよ

kotlinでAndroidアプリを試しに作った

よくお世話になるクローディアのアプリのAndroid版をkotlinで書き直し中 最近あまりネイティブアプリを書くことがなくなってきたのでリハビリを兼ねて作ってみました。

とにかく最近のトレンドを追いかけるために

  • retrofit
  • databinding
  • realm
  • rxJava

この辺りは入れてみようと思いましたが、realmだけまだ入れてない。。。
Dagger2もまだ使ったことないので使ってみたかったが後回し
設計もいまトレンドのMVPでActivityを極力Viewの操作のみに専念し
PresenterがRepository層のクラスを使ってAPI通信を行ったり、PreferenceFileに書き込みを行ったりということをしています。少々雑ですが…
更に細かくやると、UseCase層も作ってそこにRepositoryとのやりとりをまとめたほうが抽象度は上がるのでしょうが、個人でやるにはそこまではやりすぎ感があったので
Presenterが色んなRepositoryとやりとりして結果をViewに知らせる形にしました。
テストコードもビジネスロジックはPresenter側に押し込めるのでPresenterを抑えておけばとりあえず大丈夫なはず。
View側のテストはInstrumentテストで頑張ればいいかなぁという感じ。
RepositoryとViewはInterfaceで実装を抽出してPresenterに渡しているのでmockを差し込むのもやりやすくて良かったです。

kotlinで良かったところ

kotlinの良い所は他でも多く語られていますね
NullSafeや拡張関数etc...
もちろんこれもれも非常によかったのですがMVPにすると地味によかったと思うところはdefault引数を定義できるとこです。
基本的にDefault引数で実オブジェクトを注入しておき、テストコードのときだけmockに差し替えるという風にできるので プロダクトコードが綺麗に保てて良かったです。

// Presenterのコンストラクターのデフォルト引数でインスタンス注入する
open class TimeLineFragmentPresenter(val fragment: ITimeLineFragmentBase, croudiaAPI: CroudiaAPIService = ServiceCreator.build(), accessTokenService: IAccessTokenService = AccessTokenService()) : APIExecutePresenterBase(croudiaAPI, accessTokenService) {
}

//Activity or Fragment側は
val presenter = TimeLineFragmentPresenter(this) // すっきり

テストコードの時は

    @Before
    fun setUp() {
        //mockを差し込む
        target = TimeLineFragmentPresenter(mock(ITimeLineFragmentBase::class.java), mock(CroudiaAPIService::class.java), mock(IAccessTokenService::class.java))
    }

課題

retrofit × rxJavaの組み合わせで、短時間で切れるアクセストークンを綺麗にリフレッシュしながら叩きにくい…
okhttpとboltsを使って書いてた時はrefresh中はwait()してリフレッシュ完了するまでThreadをブロック…って実装できたんですが、retrofit × rxJavaのときまだうまく実装できない

databindのadapterを作ってPicassoで画像を落としてくる処理をdatabindに任せたい

そもそももうちょっとソース綺麗にする

最後に

rxswift使ってiOSの方も同じ設計で作れる気がするので 実際にswift,kotlinでどのぐらいビジネスロジックを共有できるか実験してみたいところ

github.com