eaglesakuraの技術ブログ

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

CircleCIの無料プランでメモリが足りずにgradleタスクが失敗する場合の対処

タスクを分割する

  • 重いタスクがあったら、細分化してやる
# 変更前(全タスクが一度に実行)
./gradlew test
# 変更後(個別に実行)
./gradlew :app_domain:test
./gradlew :app:test

config.ymlを見直す

  • メモリ量は4GB以内で調整
        environment:
          _JAVA_OPTIONS: -Dfile.encoding=UTF-8
          GRADLE_OPTS: "-Xmx3g"
          TZ: Asia/Tokyo

KILL THEM ALL

# タスク実行前にdaemonをKILL
pkill -KILL -f java
./gradlew :app_domain:test
# また実行前にdaemonをKILL
pkill -KILL -f java
./gradlew :app:test

daemonなしでは生きられない

  • --no-daemon オプションを指定すると、gradle-kotlinビルドプラグインがクラッシュする

daemonは醜く太る

  • daemonを起動しっぱなしにすると、ビルドのたびにメモリが圧迫される
  • Android Studioでも同様の現象があるので、開発中にOOMが出たら再起動してみよう。多分治る。

太ったdaemon KILL THEM ALL

  • pkill -KILL -f java ですべて粛清する
  • また1から世界を作ろう

メモリが足りないなら

Kotlinの拡張関数とUtilクラスの使い分け ver 2018.09

最初にやるべきこと

  • Jetpack-KTXを探す
  • 公式拡張関数を探す

拡張関数(プロパティ)を使う場合

  • 単体で存続できるケースは拡張関数を許可する
  • 仮にこの拡張関数が属するライブラリと離婚することになっても、この処理は容易に移行できる
// DO
val Context.debugMode: Boolean
    get() = packageManager.getApplicationInfo(packageName, 0)?.let { appInfo ->
        return appInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE == ApplicationInfo.FLAG_DEBUGGABLE
    } ?: false

if(context.debugMode) {
  ...
}

Utilクラスにまとめる場合

  • 自身のライブラリや、他のライブラリへの依存がある場合はUtilクラスにまとめる
// DO NOT
fun Context.getMyInfo(): MyInfo {
  return MyInfo(this)
}

val myInfo = context.getMyInfo()
// DO
val myInfo = HogeUtil.getMyInfo(context)

拡張関数(プロパティ)とクラスの使い分けに迷ったら

  • 文脈として自然であると考えられるなら、拡張関数を許可する
    • 拡張関数のほうがIntellisenseとの親和性が高い

同じ名前の拡張関数を見つけたら?

  • 公式(もしくはメンテナンス頻度が高いもの)を優先する

kotlin-coroutines 0.26.1での破壊的更新

coroutines 0.26.1の変更点

  • 多くのクラスやトップレベルfunctionやプロパティがdeprecatedになった

変更から見える方針

  • トップレベルの関数やプロパティを、いずれかのobject等に所属させることが主な目的に見える

主なDeprecated

  • UI, CommonPool 等の標準Dispatcherが非推奨
    • Dispatchers.Main, Dispatchers.Default が追加された
  • launch{}, async{} 等のトップレベル関数が非推奨
    • GlobalScope.launch, GlobalScope.async が追加された
  • isActive が拡張関数になった
    • ビルドが通らないので、ガイドに従って書き換える

互換性

  • Deprecated属性になっただけで、0.24のときのような内部の破壊的仕様変更はされていない
  • 様子見しつつ、移行して行こう。

移行時の注意

  • GlobalScope.launchCoroutineScope.launch を使い分ける
    • CoroutineScope.thisが届く範囲のlaunch/async等はそのまま動作する
    • 「とりあえずlaunchって書けば非同期になるよ」みたいなことが言えなくなる
  • Android Studioの場合、 Alt + Enter で移行先を示してくれる
    • UIDispatchers.Main にしてくれたり、いろいろ
    • デフォルト引数が設定されている場合、勝手にデフォルト値が転記されてしまうので、全自動は無理
    • CommonPoolは補完されないので手動で Dispatchers.Default にする
  • withContext{} で渡されるthisのスコープが変わった
    • ブロック内でフィールド変数にアクセスしてる場合、スコープ範囲外でエラーになる
    • this@HogeFuga.fieldName = Hoge みたいに書き換える

悲観的推測

  • GlobalScopeの場合とCoroutineScope.thisのLaunchでJobの親子関係が異なるかもしれない?
    • ちゃんと移行しないと、 job.cancel() の挙動とかに影響あるかも
  • 0.24 -> 0.25のときのように破壊的変更が次期バージョンでRevertされる恐れもある

Google Play Services Gradle Plugin 4.1.0の問題点

既知の問題点

  • Gradle Pluginバージョンは com.android.tools.build:gradle:3.3.0-alpha10
  • google-services.jsonを検索しない
    • 考えうる限りいろんなpathにおいたけど反応なし
    • ログも --debug オプションで見たが吐き出されない
  • 完全にnot workingらしい
  • 4.0.2は期待通り動作する

諦めた

  • アップデートに期待する

AS3.3 canary-11の問題点

問題点

  • Find Action(Ctrl + Shift + A)が正常動作しない
  • たまに正常動作する
  • だいたい正常動作しない
  • Crash Reportが吐き出されてるので、どっかのPluginと競合している
    • Reportは送った
  • 以前はFlutter Pluginと競合していたので、uninstall済み
  • Dartも怪しかったのでuninstallしたが、改善されず

諦めた

  • C12に期待する

QRコードをスキャンする仕様で注意すべきこと

QRコードもカメラも物理デバイスである

  • QRコードは対象物の物理サイズにも留意して作成する
  • 小さすぎると、カメラに映ってもオートフォーカスが正常動作しない場合がある
    • レンズが汚れていると更に辛い
  • フロントカメラは概ね低スペックなので、バックカメラよりも気を使う

実例

  • Nexus9のフロントカメラで18mm角だとスキャンに成功する
  • 16mm角前後だとスキャンに成功する個体・失敗する個体に別れ始める

今後のために

  • 物理的な大きさと距離について、無制限ではないという点に留意して仕様を考える

VIVITA社に転職しました

FROM

以前のエントリーの通り、8月31日で TOPGATE社 を退職しました。

TO

9月1日から、 VIVITA 所属となり、子どもたちがアイディアを形にするための環境づくりを行います。

Androidアプリ開発やサーバー開発といった形で参加する予定です。

ほしいものリスト

(/ω・\)チラッ

http://amzn.asia/66X0Vi3