Android Studio 上の IDEA Vim でエスケープキーが効かなくなった際のメモ

Android Studio(IntelliJ IDEA) で IDEA Vim が突然エスケープ(escape) キーが効かなくなってしまった場合のメモ。

Insert mode から抜けられなくなったと思いIDEの再起動やPCの再起動をしてみたが状況は変わらず、、、。

結論としては単なる勘違いで、CTRL+ALT+v で IDEA Vim を disabled にしてしまっていただけでした。

戻すには CTRL+ALT+v で IDEA Vim を enabled にしてあげればOK。

Microsoft Office 2010 が動かなくなった(KB4461627)

2019-01-05にPCを再起動したところ、Excel を起動すると、起動後スプレッドシート自体が表示されるがしばらく Excel が操作不能という状態が続き、その後 Excel が突然落ちるという、再現可能な現象が発生した。

windows update が問題だったらしく、Excel 2010 (KB4461627)、2019 年 1 月 2日の更新プログラム をアンインストールすることで解決した。

Firebase Cloud Messaging(FCM)のHTTP legacy protocolでsendするメモ

fcm_regacy_http.kt

import okhttp3.*

private const val URL = "https://fcm.googleapis.com/fcm/send"
private val MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8")
private val CLIENT = OkHttpClient()

fun send(serverKey: String, jsonString: String): Response =
        newCall(serverKey, jsonString).execute()

fun send(serverKey: String, jsonString: String, callback: Callback) {
    newCall(serverKey, jsonString).enqueue(callback)
}

private fun newCall(serverKey: String, jsonString: String): Call =
        CLIENT.newCall(Request.Builder()
                .url(URL)
                .header("Authorization", "key=$serverKey")
                .post(RequestBody.create(MEDIA_TYPE_JSON, jsonString))
                .build()
        )

Autosizing TextViews

TextView のフォントサイズの自動調整機能Android 8.0 (API level 26) から導入され、Support Library 26.0 以降でも採用されています。

XML

<TextView
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:maxLines="2"
    android:text="じゅげむじゅげむごこうのすりきれかいじゃりすいぎょのすいぎょうまつうんらいまつふうらいまつくうねるところにすむところ・・・"
    app:autoSizeMinTextSize="1px"
    app:autoSizeTextType="uniform" />

注意

  • support library が慮ってくれるので android.support.v7.widget.AppCompatTextView とか明示しないように。
  • app:autoSizeMinTextSize を設定しないと自動調整が行われないっぽいです。

Auto sizing が効いてない場合の表示:

f:id:beyondseeker:20180212205052p:plain

Auto sizing が効いている場合の表示:

f:id:beyondseeker:20180212205100p:plain

Data BindingでDelegates.observableを使う際に非nullの初期値を強制されたくない件

Data Binding Library で notifyPropertyChanged を利用する際、普通にやると下記のように非 null の初期値が強制されてしまう。

class MyModel : BaseObservable() {
    @get:Bindable
    var myText: String by Delegates.observable("") { _, _, _ -> notifyPropertyChanged(BR.myText) }
}

しかし、lazy のように get 時には非 null だが初期値は null にしたいというケースがある。

でも、下記のようにできるとラクチンっすね。

class MyModel : BaseObservable() {
    @get:Bindable
    var myText: String by dataBindingObservable(BR.myText)
}

ということで、以下のようなコードで対応する。

// 上記から dataBindingObservable(BR.myText) って呼ばれるやつ。
fun <T> BaseObservable.dataBindingObservable(brId: Int): ReadWriteProperty<Any?, T> = lazyObservable { _, _, _ -> notifyPropertyChanged(brId) }

/**
 * @see kotlin.properties.Delegates.observable
 */
inline fun <T> lazyObservable(crossinline onChange: (property: KProperty<*>, oldValue: T?, newValue: T) -> Unit):
        ReadWriteProperty<Any?, T> = object : LazyObservableProperty<T>() {
    override fun afterChange(property: KProperty<*>, oldValue: T?, newValue: T) = onChange(property, oldValue, newValue)
}

/**
 * @see kotlin.properties.ObservableProperty
 */
abstract class LazyObservableProperty<T> : ReadWriteProperty<Any?, T> {
    private var value: T? = null

    protected open fun beforeChange(property: KProperty<*>, oldValue: T?, newValue: T): Boolean = true

    protected open fun afterChange(property: KProperty<*>, oldValue: T?, newValue: T) {}

    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return value ?: throw IllegalStateException("Property ${property.name} should be initialized before get.")
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        val oldValue = this.value
        if (!beforeChange(property, oldValue, value)) {
            return
        }
        this.value = value
        afterChange(property, oldValue, value)
    }
}

おまけ。

// notifyChange() を使いたい場合
fun <T> BaseObservable.dataBindingObservable(): ReadWriteProperty<Any?, T> = lazyObservable { _, _, _ -> notifyChange() }

// 初期値と brId を指定したい場合
fun <T> BaseObservable.dataBindingObservable(initialValue: T, brId: Int): ReadWriteProperty<Any?, T> = Delegates.observable(initialValue) { _, _, _ -> notifyPropertyChanged(brId) }

// 初期値を指定して notifyChange() を使いたい場合
fun <T> BaseObservable.dataBindingObservable(initialValue: T): ReadWriteProperty<Any?, T> = Delegates.observable(initialValue) { _, _, _ -> notifyChange() }

kotlinで値がprimitive wrapperのためにlateinitできない場合

'lateinit' modifier is not allowed on properties of primitive types とか怒られるので by Delegates.notNull() で凌ぎましょう。

例:

import kotlin.properties.Delegates

var i: Int by Delegates.notNull()

fun main(args: Array<String>) {
    i = 10
    println("i = $i")
}

結果:

i = 10

Data Binding Library と Google Analytics for Firebase の依存関係の件

Data Binding Library と Google Analytics for Firebase が古いライブラリを参照してるのでメモ。

手元にある support library の version として "27.0.2" を採用しているプロジェクトで、普通にビルドすると lint で下記のように怒られる。

Incompatible Gradle Versions

../../build.gradle: All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions 27.0.2, 25.2.0. Examples include com.android.support:animated-vector-drawable:27.0.2 and com.android.support:support-media-compat:25.2.0

gradlew :modules:app:dependencies とかやると下記のような依存関係がわかる。

com.android.databinding:library:1.3.1
  - com.android.support:support-v4:21.0.3

com.google.firebase:firebase-analytics:11.8.0
  - com.google.android.gms:play-services-basement:11.8.0
    - com.android.support:support-v4:25.2.0

ぐぬぬ、、、

本質的な解決じゃないけど下記のように設定してlintエラーを回避するくらいしかできんよな、、、(´・ω・`)

implementation "com.android.support:support-v4:27.0.2"