20190523のKotlinに関する記事は5件です。

[Kotlin豆知識] KProperty<T, out R>は関数のようにふるまう

発端はEnumから

enumのメンバをそのプロパティから復元するときにこういうコードをよく書く。

enum class Moge(val raw: Int) {
    companion object {
        private val map = values().associateBy(Moge::raw)

        fun fromInt(value: Int) : Moge {
            return map[value] ?: throw IllegalArgumentException("Moge!!!")
        }
}

丁寧に挙動を調べてやると、 Hoge::fuga はHogeのインスタンスを引数にとる関数のような挙動をすることがわかる。

class Hoge(val fuga: Int = 3) 
val fuga = (Hoge::fuga)(Hoge())

fugaをprivateにすると

きちんとコンパイルエラーになってくれる

class Hoge(private val fuga: Int = 3)

// fugaのprivate性はここで検知される
val fuga = Hoge::fuga
fuga(Hoge())

何の意味もないが

KProperty1をムリヤリ外に出してやると、プライベートメンバにアクセスができる。

class Hoge(private val fuga: Int = 3) {
    companion object {
        fun fugaProperty(): KProperty1<Hoge, Int> {
            return Hoge::fuga
        }
    }
}
val fugaProperty = Hoge.fugaProperty()
val fuga = fugaProperty(Hoge())
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[本日のKotlin豆知識] kotlin.reflect.KProperty<T, out R>はTのインスタンスを引数に取りinvokeできる

発端はEnumから

enumのメンバをそのプロパティから復元するときにこういうコードをよく書く。

enum class Moge(val raw: Int) {
    companion object {
        private val map = values().associateBy(Moge::raw)

        fun fromInt(value: Int) : Moge {
            return map[value] ?: throw IllegalArgumentException("Moge!!!")
        }
}

丁寧に挙動を調べてやると、 Hoge::fuga

class Hoge(val fuga: Int = 3) 
val fuga = (Hoge::fuga)(Hoge())

fugaをprivateにすると

きちんとコンパイルエラーになってくれる

class Hoge(private val fuga: Int = 3)

// fugaのprivate性はここで検知される
val fuga = Hoge::fuga
fuga(Hoge())

何の意味もないが

KProperty1をムリヤリ外に出してやると、プライベートメンバにアクセスができる。

class Hoge(private val fuga: Int = 3) {
    companion object {
        fun fugaProperty(): KProperty1<Hoge, Int> {
            return Hoge::fuga
        }
    }
}
val fugaProperty = Hoge.fugaProperty()
val fuga = fugaProperty(Hoge())
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【連載第1回】Kotlin と SpringBoot を利用して、TDDスタイルで「お誕生日会支援ツール」を作ってみる

はじめに

KotlinとSpringBootをベースに、TDDスタイルでWebアプリを作ってみる企画です。
私は認定こども園の運営にも携わっており、現場の業務効率化のために、職員にヒアリングしながら活用できそうなアプリケーションを書いていたりもします。自分だけでこっそりコーディングでも良いのですが、折角なので完成までの足取りを記事にしてみます。
なお、要件や設計は自園の状況やニーズ等に特化させていくつもりですので、必ずしも汎用的なものになるとは限りません。また、あくまでも本連載の主題はKotlin+SpringBootでの開発TipsやTDDスタイルにありますので、トリッキーすぎる手法や個人レベルでは導入の難しいツール等は極力控えるものとします。

作るもの

認定こども園・保育園・幼稚園等では、園児さんの誕生日に合わせてお誕生会を開く施設も多いと思います。毎回の企画をするとき、必要な情報をパッと確認したいときがあります。
「今月誕生日の子は何人?」「それぞれの好き嫌い(或いはアレルギー情報等)はなんだっけ?」「前回の内容を振り返りたい」etc...。そのための情報可視化ツールとして作成していきます。

環境

  • Windows10 or macOS
  • Gradle
  • Kotlin 1.3.31
    • JUnit 4
    • Mockito-Kotlin
  • SpringBoot 2.1.5
  • Thymeleaf
  • Docker
    • MySQL
  • IntelliJ IDEA
  • Git

連載頻度/ボリューム

月1で全6回程度を予定
1. 概要/雛形作成(※今回)
2. 園児マスタ管理機能(※2回予定)
3. 誕生日会記録機能(※2回予定)
4. 実績検索画面/まとめ

IntelliJ IDEA Community のインストール

Jetbrainsから"IntelliJ IDEA Community"をダウンロードしてインストールして下さい。(ライセンスをお持ちの場合、Ultimate版でもOKです)

雛形build.gradle作成

おなじみ SpringInitializer を利用します。
同サイトを利用すると、言語やSpringBootのバージョンを指定するだけで、Webアプリケーションの雛形として活用できる、build.gradle を生成することができます。
(今回は利用しませんが、Mavenにも対応しています)

SpringInitializerにアクセスし、以下の設定で雛形をダウンロードして下さい。

  • Project: Gradle
  • Language: Kotlin
  • Spring Boot: 2.1.5
  • Project Metadata
    • Group: com.example (任意)
    • Artifact: birthdaymanager (任意)
    • Packaging: jar
    • Java Version: 8
  • Dependencies
    • Web
    • MySQL
    • JPA
    • Thymeleaf

雛形がダウンロードできましたら、適当なディレクトリに展開しておきます。

build.gradle編集

IntelliJ IDEA にて雛形を読み込んだ後、build.gradleを編集します。

  1. "Import Project"をクリック
  2. 雛形を展開したディレクトリの中の"settings.gradle"を開く
  3. "Import Project from Gradle"ダイアログで「OK」をクリック
  4. build.gradleを以下のように編集します。
buildscript {
   ext {
      kotlinVersion = '1.3.31'   // ここを変更
   }
}
(中略)
dependencies {
   testImplementation 'junit:junit:4.12'
}
dependencies {
   testImplementation 'io.kotlintest:kotlintest-runner-junit4:3.2.1'
}
dependencies {
   testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0"
}

これで、JUnitによるテストコードを書く準備ができました。
その他必要になる予定の依存ライブラリは、都度、build.gradleに追記していく形とします。

おわりに

初回は環境構築周りで退屈な内容だったかもしれませんが、ひとまず最低限の準備が整いました。次回からはいよいよコーディングを進めていきます。
(6月下旬〜7月上旬頃の公開を予定しております)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CameraXのCodelab試してみた

概要

I/Oで発表があったCameraX。Codelabsで公開されていたものを試してみました。ちょっとハマったとこがあったので、メモがてら書いておきます。
Getting Started with CameraX

というのも、I/O Extended 2019 Tokyo@GDG にてCodelabsの課題が上がっていたからです笑
当日はセッションに興味がありCodelabには参加しませんでしたが、また機会があれば参加してみたい。

Codelabの流れ

実際のCodelabをみてもらえたらいいと思うんですが、簡単に流れを書いておきます。Codelabのセクションとはちょっと変えてます。

  1. CameraXをgradleに追加
  2. view finder layoutを準備
  3. Cameraのパーミッションを付与
  4. Permission許可&チェックのコードを記述
  5. view finder(use case)を実装
  6. image capture(use case)を実装
  7. image analysis(use case)を実装

ポイント

  • use caseを作る。

    • Preview(view finder): プレビュー
    • ImageCaputure: 画像保存
    • ImageAnalysis: 画像解析
  • 作ったuse caseを、CameraX.bindToLifecycle(this, preview, imageCapture, analyzerUseCase) でlifecycleOwner(Activity)にbindする

ハマったところ

プレビューが縦に潰れる。。

before.kt
val previewConfig = PreviewConfig.Builder().apply {
        setTargetAspectRatio(Rational(1, 1))
        setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
    }.build()

アスペクトをが1:1で設定しているのに、プレビューが縦に崩れる。。。

結局崩れるのはなぜかわからなかったんですが、公式のサンプル
の通りに実際のViewのディスプレイサイズを取得し設定したら治った。

after.kt
val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }
val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)
val screenSize = Size(metrics.widthPixels, metrics.heightPixels)

val previewConfig = PreviewConfig.Builder().apply {
        setTargetAspectRatio(screenAspectRatio)
        setTargetResolution(screenSize)
    }.build()

Capture時に保存された画像は正常だったところを見ると、Viewに反映される際になにか問題があるのかも。時間が許せばもっと探ってみようかな。。

所感

lifecycleにbindでき、自分で面倒を見ないでいいのがすごく楽だと感じました。
もうすこしドキュメント見て、触ってみようと思えました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CameraXのCodelabs試してみた

概要

I/Oで発表があったCameraX。Codelabsで公開されていたものを試してみました。ちょっとハマったとこがあったので、メモがてら書いておきます。
Getting Started with CameraX

というのも、I/O Extended 2019 Tokyo@GDG にてCodelabsの課題が上がっていたからです笑
当日はセッションに興味がありCodelabsには参加しませんでしたが、また機会があれば参加してみたい。

実装の流れ

実際のCodelabsをみてもらえたらいいと思うんですが、簡単に流れを書いておきます。Codelabsのセクションとはちょっと変えてます。

  1. CameraXをgradleに追加
  2. view finder layoutを準備
  3. Cameraのパーミッションを付与
  4. Permission許可&チェックのコードを記述
  5. view finder(use case)を実装
  6. image capture(use case)を実装
  7. image analysis(use case)を実装

ポイント

  • use caseを作る。

    • Preview(view finder): プレビュー
    • ImageCaputure: 画像保存
    • ImageAnalysis: 画像解析
  • 作ったuse caseを、CameraX.bindToLifecycle(this, preview, imageCapture, analyzerUseCase) でlifecycleOwner(Activity)にbindする

ハマったところ

プレビューが縦に潰れる。。

before.kt
val previewConfig = PreviewConfig.Builder().apply {
        setTargetAspectRatio(Rational(1, 1))
        setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
    }.build()

アスペクトをが1:1で設定しているのに、プレビューが縦に崩れる。。。

結局崩れるのはなぜかわからなかったんですが、公式のサンプル
の通りに実際のViewのディスプレイサイズを取得し設定したら治った。

after.kt
val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }
val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)
val screenSize = Size(metrics.widthPixels, metrics.heightPixels)

val previewConfig = PreviewConfig.Builder().apply {
        setTargetAspectRatio(screenAspectRatio)
        setTargetResolution(screenSize)
    }.build()

Capture時に保存された画像は正常だったところを見ると、Viewに反映される際になにか問題があるのかも。時間が許せばもっと探ってみようかな。。

所感

lifecycleにbindでき、自分で面倒を見ないでいいのがすごく楽だと感じました。
もうすこしドキュメント見て、触ってみようと思えました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む