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

Gsonはデフォルトではnullなフィールドをシリアライズしない

調べたのでメモ。

題名の通り、GsonはオブジェクトをJSONに変換する際、デフォルトではnullのフィールドをシリアライズしない。

nullのフィールドをシリアライズしたい場合、 GsonBuilder#serializeNulls() を使用する。

サンプルコード

MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val data = Data("nonnull", "nullable", null)

        val gson1 = Gson()
        val json1 = gson1.toJson(data)
        Log.d(TAG, json1)
        // => {"nonNullProp":"nonnull","nullableProp1":"nullable"}

        val gson2 = GsonBuilder().serializeNulls().create()
        val json2 = gson2.toJson(data)
        Log.d(TAG, json2)
        // => {"nonNullProp":"nonnull","nullableProp1":"nullable","nullableProp2":null}
    }

    data class Data(
        val nonNullProp: String,
        val nullableProp1: String?,
        val nullableProp2: String?
    )

    companion object {
        private const val TAG = "MainActivity"
    }
}

参考URL

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

android abd shell で Permission denied がでて見れないざます

android開発していた必ず一度はハマっことがあるのではないでしょうか?

abd shellで /data/dataとcdするとそのあとなにもできない。

./adb shell
generic_x86:/ $ cd /data
generic_x86:/data $ cd data
generic_x86:/data/data $ ls
ls: .: Permission denied
1|generic_x86:/data/data $

そんなときはこれ

1|generic_x86:/data/data $ run-as (パッケージ名)
generic_x86:/data/data/(パッケージ名) $ ls
cache code_cache databases files shared_prefs

見れた。よかったよかった。。


パッケージ名はMainActivitiyの一番上の

package xxxxxxx

または
android manifestの

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xxxxx">

ここら辺をみればわかります。 ※xxxxxのぶぶんですね。
だいたい。 com.example.システム名 とかになってんじゃないですかね?

例)
package="com.example.hoge" なら、コマンドは
run-as com.example.hoge ですね。

では。

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

android PreferenceFragmentCompatのEditTextPreferenceを改行させないようにする方法

なかなか調べても出てこなかったので、
EditTextPreferenceで改行ができてしまい、すこし操作性が悪かったので
改行をできなくするようにする方法です。

というよりはDialogで呼ばれるEditTextのレイアウトを指定する方法です。

preferences.xml

<EditTextPreference
      android:dialogLayout="@xml/prefernce_custom_edittext"
      android:key="userName"
      android:title="ユーザー名" />

android:dialogLayoutを設定します。

prefernce_custom_edittext.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <EditText
        android:id="@android:id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="18dp"
        android:paddingRight="18dp"
        android:inputType="text|textNoSuggestions" />

</LinearLayout>

これで普段扱っているように自由にカスタマイズできます。

スクリーンショット 2019-04-11 14.24.58.png

改行できない!よかったよかった!

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

【Kotlin】コンストラクタ − プライマリとセカンダリ

プライマリコンストラクタとセカンダリコンストラクタについて解説します。

公式リファレンス:Classes and Inheritance - Kotlin Programming Language

対象読者

基本的なクラスの定義方法を知っている方。

プライマリコンストラクタ

基本的なクラスの定義は次のようになります。

class MyClass( ... ) { ... }

( ... ) がコンストラクタの定義です。

クラス定義のブロック { ... } の外に定義するコンストラクタを
(後で出てくるセカンダリコンストラクタと区別して)
プライマリコンストラクタと呼びます。

省略なし

実は先ほどの書式は省略形です。
省略しなければ次のようになります。

class MyClass constructor( ... ) { ... }

プライマリコンストラクタに可視性やアノテーションを指定する場合はこの省略しない書式を使います。

class MyClass @Deprecated("Use YourClass class.") private constructor() {}

もっと省略

プライマリコンストラクタに引数がない場合は () を省略することができます。

class MyClass { ... }

ちなみに constructor と書く書式の場合、引数がなくても () は省略できません。

セカンダリコンストラクタ

Kotlin では引数にデフォルト値を設定できるため、
多くの場合コンストラクタは1つで事足りることでしょう。
ですが、複数のコンストラクタを定義することもできます。

プライマリコンストラクタ以外のコンストラクタは
セカンダリコンストラクタと呼ばれます。
セカンダリコンストラクタはクラス定義のブロック { ... } の内に定義します。

class MyClass {
    constructor( ... ) { ... } // セカンダリーコンストラクターの1つ
    constructor( ... ) { ... } // セカンダリーコンストラクターの1つ
}

constructor( ... ) の後の { ... } は、空なら省略できます。

セカンダリコンストラクタでは引数がなくても () を省略することはできません。

他のコンストラクタを呼び出す

セカンダリコンストラクタは他のコンストラクタを呼び出すことができます。
そのためには、constructor( ... ) の後に : this( ... ) を付けます。

class MyClass(int: Int) {
    // プライマリコンストラクタが呼び出されたときに実行される処理。
    init {
        println(int)
    }

    constructor(short: Short) : this(short + 1)
    // ↑引数が Int 型であるコンストラクタ(プライマリコンストラクタ)を呼び出す。
    constructor(byte: Byte) : this((byte + 1).toShort()) // 引数
    // ↑引数が Short 型であるコンストラクタ(もう1つのセカンダリコンストラクタ)を呼び出す。
}

fun main() {
    MyClass(0) // > 0
    MyClass(0.toShort()) // > 1
    MyClass(0.toByte()) // > 2
}

セカンダリコンストラクタは必ず、直接的または間接的に、プライマリコンストラクタを呼び出さなければなりません。

プライマリコンストラクタの () 省略すると

プライマリコンストラクタの説明において、次のように述べました。

プライマリコンストラクタに引数がない場合、() を省略することができます。

これは、セカンダリコンストラクタがない場合には正しいです。

ですが、セカンダリコンストラクタがある場合には
() を省略するとプライマリコンストラクタがなくなります

プライマリコンストラクタがない場合、
セカンダリコンストラクタには : this( ... ) がなくても構いません。

class MyClass {
    constructor(int: Int) : this() // コンパイルエラー!
    constructor(int: Int) // 他のセカンダリコンストラクタを呼び出す必要がなければ `: this( ... )` を書かない
    constructor(short: Short) : this(short.toInt())
}

fun main() {
    MyClass() // コンパイルエラー!
}

コンストラクタ引数の var val

コンストラクタ引数に var もしくは val を付けることで、
その引数をプロパティにすることができます。

class MyClass(
    val userId: String,
    var age: Int
)

これは次と等価です。

class MyClass(
    userId: String,
    age: Int
) {
    val userId: String = userId
    var age: Int = age
}

ただしこれができるのはプライマリコンストラクタだけです。

考えてみればこれは当然です。
どのセカンダリコンストラクタからインスタンスを生成したかによってプロパティの有無が変わっては困ります。

まとめ

  • クラス定義のブロックの外に書くのがプライマリコンストラクタ、内に書くのがセカンダリコンストラクタ。
  • プライマリコンストラクタでは constructor の記述は省略できる。
    • プライマリコンストラクタに可視性やアノテーションを指定する場合は省略できない。
  • プライマリコンストラクタを明示しなかった(constructor( ... ) も書かなかった)場合、
    • セカンダリコンストラクタがなければ引数なしのプライマリコンストラクタが作られる。
    • セカンダリコンストラクタがあればプライマリコンストラクタは作られない。
  • セカンダリコンストラクタは : this( ... ) でプライマリコンストラクタや他のセカンダリコンストラクタを呼び出すことができる。
  • プライマリコンストラクタがある場合、セカンダリコンストラクタは直接的もしくは間接的にそれを呼び出す必要がある(: this( ... ) を書く必要がある)。
  • コンストラクタ引数に var val を付けてプロパティにできる。
    • これができるのはプライマリコンストラクタだけ。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Kotlinでnull+nullするとNonNullになる

ある時、null + nullするとNonNullになったので少し調べました。

val hoge: String = null // エラー
val hoge: String = null + null // エラーじゃない

+を参照すると次のようになっていました。

public operator fun String?.plus(other: Any?): String

次のような場面で遭遇しました。
MapgetはNullableなので、強制アンラップしたり、例外にしたりでしたが、conf2のようなパターンでは突然NonNullになっています。nullnullにいつの間にかならないように注意しないと行けなさそうです。なんか不思議な感じ。

val config = mapOf("aaa" to "bbb")
val conf1: String = config["hoge"] ?: throw Exception() // -> throw Exception
val conf2: String = config["hoge"] + config["fuga"] // -> conf2 = nullnull
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む