荒川沿いに住む人も、そうでない人も、
無料で公開されているのでぜひ。
前日までの、軌跡や状況をわかりやすく確認することができます。
荒川沿いに住む人も、そうでない人も、
無料で公開されているのでぜひ。
前日までの、軌跡や状況をわかりやすく確認することができます。
ふと、こんな書き方ではないのでは? と思ってしまいました。
object DbConstants {
const val TABLE_USER_ATTRIBUTE_EMPID = "_id"
const val TABLE_USER_ATTRIBUTE_DATA = "data"
}
以下、stackoverflow より。
通常クラスにしたり。
public class DbConstants {
companion object {
val TABLE_USER_ATTRIBUTE_EMPID = "_id"
val TABLE_USER_ATTRIBUTE_DATA = "data"
}
}
トップレベルのプロパティにしたり。
package com.project.constants
const val URL_PATH = "https:/"
GitHub を眺めてみます。
👉 Search · Constants.kt
これが良さげでは?
ファイル名は、Constants.kt 。
@file:JvmName("Constants")
package org.videolan.resources
const val PREF_FIRST_RUN = "first_run"
const val EXTRA_FIRST_RUN = "extra_first_run"
const val EXTRA_UPGRADE = "extra_upgrade"
@JvmField val EXTRA_SEARCH_BUNDLE = "${ACTION_REMOTE_GENERIC}extra_search_bundle"
@JvmField val ACTION_PLAY_FROM_SEARCH = "${ACTION_REMOTE_GENERIC}play_from_search"
@JvmField val ACTION_REMOTE_SWITCH_VIDEO = "${ACTION_REMOTE_GENERIC}SwitchToVideo"
みんなは、どう書いてますか。
教えてねー。
fun ContentResolver.observeQuery(
uri: Uri,
projection: Array<String>? = null,
selection: String? = null,
selectionArgs: Array<String>? = null,
sortOrder: String? = null,
notifyForDescendants: Boolean = false
): Flow<Query> {
val query = ContentResolverQuery(this, uri, projection, selection, selectionArgs, sortOrder)
return flow {
emit(query)
val channel = Channel<Unit>(CONFLATED)
val observer = object : ContentObserver(mainThread) {
override fun onChange(selfChange: Boolean) {
channel.offer(Unit)
}
}
registerContentObserver(uri, notifyForDescendants, observer)
try {
for (item in channel) {
emit(query)
}
} finally {
unregisterContentObserver(observer)
}
}
}
👉 FlowContentResolver.kt#L43-L90
👉 copper/FlowContentResolver.kt at trunk · cashapp/copper
Kotlin coroutines Flow や RxJava Observable を使ったリアクティブクエリ用の ContentProvider のラッパーです。
implementation 'app.cash.copper:copper-flow:1.0.0'
ContentResolver で query() を observeQuery() に変更することで、リアクティブ版を実現します。
contentResolver.observeQuery(uri).collect { query ->
query.run()?.use { cursor ->
// ...
}
}
query() とは異なり、observeQuery() は Query オブジェクトを返します。このオブジェクトは、カーソルの基礎となるクエリを実行するために run() を呼び出す必要があります。これにより、値をキャッシュする中間オペレータがリソースをリークすることなく、コンシューマーがカーソルのライフタイム全体にアクセスできるようになります。
cursor を直接処理する代わりに、含まれる値をセマンティックタイプに変換するためのオペレータを提供しています。
contentResolver.observeQuery(uri)
.mapToOne { cursor ->
Employee(cursor.getString(0), cursor.getString(1))
}
.collect {
println(it)
}
Employee(id=bob, name=Bob Bobberson)
mapToOne オペレータは、1 つの行を返すクエリを受け取り、ラムダを起動してカーソルを希望の型にマッピングします。クエリがゼロまたは1行を返す場合は、コルーチン成果物には mapToOneOrNull オペレータがあり、RxJava成果物には mapToOptional 演算子があります。
クエリがリストを返す場合は、同じラムダでmapToListを呼び出します。
contentResolver.observeQuery(uri)
.mapToList { cursor ->
Employee(cursor.getString(0), cursor.getString(1))
}
.collect {
println(it)
}
[Employee(id=alice, name=Alice Alison), Employee(id=bob, name=Bob Bobberson)]
安定の神Jake産です。