eaglesakuraの技術ブログ

技術的な話題とか、メモとか。

Android Studio Arctic Fox Canary-11の所感

現状の利点

  • Jetpack Compose(Beta, production-ready)が使える

AS 4.1.xからの移行

  • Android Gradle Pluginバージョン変更
  • gradlewバージョン変更

基本的に素直に移行できた。

現状の問題点

Library Projectで問題が出る。 Application Projectでは使えているので、モノリシックなプロジェクト以外は導入がつらそう(Unit Testをgradlewからの実行するのであれば気合で乗り切れるかもしれない)

  • Robolectircが必ずfailする
  • Instrumentation TestをAndroid Studioから実行できない
    • だめくさい

まとめ

まだ人柱レベル。 ComposeはProduction Readyでも、ASはProduction ちょいツライ。 頑張れGoogle、応援してるぞ。

イカれた映画観客を紹介するぜ!!

持ち込んだペットボトルをごっきゅごきゅと音を立てて就活生風の男 / TOHOシネマズ上野 / ラブライブサンシャイン

  • TOHOシネマズは基本的に飲食物は持ち込み禁止のはず
  • ごっきゅごきゅと音を鳴らして飲んでクソうるせー
  • 人間ってあんな音を立てながら飲めるんだな

映画を観ながらソシャゲーする30代くらいの男 / TOHOシネマズ柏 / シン・エヴァンゲリオン

  • 映画はソシャゲーする場所じゃねぇ
  • 水筒に飲み物入れて持ち込むな、持ち込み禁止じゃボケ
  • テメーのコンボにもガチャにも興味ねぇ
  • 画面隠してるつもりか?気になるんじゃボケ
  • 映画のエンドロールはガチャする時間じゃねぇ
  • ガチャしたけりゃ外に出ろ、上映中にスマホ開くなボケ

LINEをしながら「広瀬すず!!」って叫びながら観る高校生4人組 / TOHOシネマズ流山おおたかの森 / バケモノの子

  • 俺の映画体験ぶっちぎりワースト1。
  • しかもグループで来たのに固まって観れなかったから、(俺の)席左右をはさんで会話をする
  • LINEで実況するなクズども
  • 二度と映画館に来るなクズども
  • こいつらのせいで出演者に広瀬すずの名前がいると「あいつらいるのか」とか思うようになった
  • 「映画を観に来る学生集団」が嫌いになった理由

現状とってる回避策

  • 可能な限り平日
  • 可能な限り郊外
  • 可能な限り駅近は避ける
    • 駅直結は学生集団が集まりやすい
  • 可能な限り映画の日は避ける
    • 安い日は学生集団が集まりやすい
  • 可能な限り追加料金の発生する上映回を選ぶ
    • 学生集団は追加料金を出してまで映画を観ない

それでも

  • シン・エヴァンゲリオン鑑賞を邪魔したソシャゲー男は↑を満たしても現れた
  • わざわざ4DX追加料金出したのに
    • 4DX払ってまでソシャゲーやりに来るなよボケ

以上だ!

docker-composeでgoogle/cloud-sdk:emulators(firestore emulator)を利用する

docker-compose記述

version: "3"

services:
  firestore-emulator:
    image: google/cloud-sdk:329.0.0-emulators
    ports:
      - 8004:8004
    command: gcloud beta emulators firestore start --host-port "0.0.0.0:8004"
  • これで docker-compose up で起動できる。
  • ポートは任意(8004は俺の環境)

試行錯誤で見つけた問題点(自分の環境の場合)

  • Docker / WSL2環境では --host-port 127.0.0.1:8004 で接続できた
  • Mac, Linuxでは接続できない
  • --host-port 0.0.0.0:8004 だと接続できた
  • どの場合でも、docker-composeのコンテナ間では通信できるはず

APIサーバーの実行環境の所感 2020

Google App Engine

  • 言語/ランタイムバージョンが限定される
  • 複数バージョンをデプロイして、複数の指定バージョンを簡単に試せる
  • staticファイルの配信が簡単
  • Go1.9時代(第1世代GAE)はいつも使っていた
  • 今はstaticファイルの配信に使う

Google Cloud Run

  • Runtimeが固定されない
  • デプロイが簡単、Dockerfileがそのまま使えて嬉しい
  • インスタンス起動後、10〜20分くらい生きている。その後死ぬ。

Google Cloud Run / Go

  • Go 1.13以降で主に使う
  • スピンアップが早い。コールドスタート早い。ちょっぱや。
  • Golangのサーバーサイド開発者自体を捕獲する難易度が多少高い
  • ライブラリが豊富

Google Cloud Run / Kotlin

  • Kotlinしゅき。
  • 今日試した
  • Ktor使ってスピンアップ2.3秒、以後8ms程度が最速値(Hello Worldのテキストを返すだけ)
  • まあ許せなくもない気もする
  • Cloud Schedulerを用いて1分に1回pingすることで0円インスタンスを1個キープできそう

Firebase Hosting

  • マイクロサービスアーキテクチャで作ったときにCloud Runのサービスルーティングに使う
  • staticファイルの配信としては個人的には使いにくい

Windows環境のRobolectricでUri.toFile() KTXが正常に動作しない

問題点

  • Windowsファイルシステムはドライブレター(C:とか)やパスセパレータ(¥)がLinux/Macと異なる
  • Uri.fromFile()を実行したとき、ドライブレターやバッククォート(日本語だと円マーク)を含んだ文字列がURLエンコードされる

KTXUri.toFile()を行うとどうなるか

  • toFile()は単純に Uri.path 値をFileにラップして返すだけである
  • Windows環境でRobolectricを使用し、Uri.fromFile().pathを取得するとnullになる
  • 結果、File(null)が渡されることとなり、 UnitTestを実行しているカレントディレクトリ と解釈され、ほとんどの場合はその後のテストが落ちる

どうしたか?

  • Uri.path をチェックし、問題があるようならURLデコードを行ってからFileにラップするような拡張関数を書いてやる

こんなの

internal const val SCHEME_FILE = "file://"

fun Uri.toFileCompat(): File {
    val path = this.path ?: ""
    return if (path.isEmpty()) {
        // Windows path.
        val path = toString().substring(SCHEME_FILE.length)
        File(URLDecoder.decode(path, "UTF-8"))
    } else {
        toFile()
    }
}

楽観的な話

  • そのうち公式も直すんじゃねかな?

WindowsのNTFSはtree()が遅い

起きた事象

  • WindowsAndroid StudioのGradle Sync(像のアイコン押すと走るやつ)が異様に遅い
  • 普通に gradlew 実行だけでも遅い
  • MacUbuntuだと早い
  • 具体的にはこのくらい
    • Windows: gradlew 40秒, WSL2も同じくらい
      • NVMe PCIe 4.0接続しているので、ストレージ自体の接続速度に問題は無いと思われる
    • Mac: gradlew 5秒
    • Ubuntu: gradlew 3秒

遅かった理由

  • CIのキャッシュキーにするため、特定ファイル名のハッシュ値を計算していた
  • ハッシュ計算を(やり忘れないように)gradleのビルドスクリプトの中で(常に)起動していた
  • ファイル一覧を列挙するとき、(実装を面倒くさがって)fileTree()によるリポジトリの全探索を行った
  • 結果として、NTFSの上でファイルツリーの単純全検索が走ることとなった
  • 特に build/ 配下の検索が走ってしまったのが痛かったと思われる

改善

  • ハッシュ計算処理を改善したところ圧倒的改善を行えた

反省点

  • 開発環境にWindowsを使うならファイル全検索はやめよう
  • Linuxファイルシステムは早いので気づかないかもしれない
    • それでも全検索はモノグサしすぎだったかもしれない

結論

Protocol BuffersのAndroid向け実装としてSquare Wireを採用した所感

Wire

square.github.io

Protocol Buffersを採用した理由

  • 大量のデータを扱う処理で、画面外の情報を一時的にファイルやDBに退避したい
    • ついでにIntentで渡したりするのも簡単にやりたい
  • モデルの定義を簡素化したい
  • 銀の弾丸を求めて色々検証した結果、Protocol Buffers+Wireプラグインに落ち着いた

Protocol Buffers公式プラグイン(javaliteとか)の採用を見送った理由

  • AndroidのBundleやIntentにモデルを直接putできない
    • 自分でByteArrayにエンコード/デコードしなければならない
    • やってやれないことはないけどそこまで手間をかけたくない
  • javalite実装が3.0.0(2016年頃)で止まっている
    • Firestoreとかでまだ使われているから、何かあればメンテするとは思われるが。

Wireプラグインを採用した理由

  • Proto3に対応している
  • Android Parcelizeをimplしたモデルを出力してくれる
    • 実装を見ると、ByteArrayにエンコード(Protocol Buffers形式として)してputしている
    • kotlin-parcelizeを使うことで簡単にIntentに乗せられる
  • コミット履歴からみて、アクティブにメンテされている

Wireプラグインの問題

  • Moshi Adapterを提供してる(JSONシリアライズもできる)ように見えるが、必要なClassが出力されずに例外を投げた

追記: Wire プラグインの不具合