android開発中によく使うkotlin構文 

kotlinでandroid開発始めたてで、自分用のメモです。(kotlin歴2週間)
もっといい感じの使い方は恐らくあるとは思いますが、ライブラリの使い方とかサンプルコードを参考にAndroid Stdioで書いてて、勝手に補完されるので理解しておこうってレベルです。

※ちなみにJavaはあんまわからない人ですのでJavaと比べてとかはわかってないです。

[リファレンス - Kotlin Programming Language](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/) が最強なのでこれ全部読めばいいと思う

## 変数

```variable.kt
val num = 5 // 変更不可
var i = 0   // 変更化
var name : String = "" // 型付き

// ?を使うと「nullでなければ実行、そうでなければnullを返す」
// こうしないとnullが入れれない
var kanaName : String? = "abc"

// チェインしてもかける
val longLen = kanaName?.length?.toLong()

// Nullだったら例外が発生する
val longLenNull = kanaName!!.length()
```

## 関数

```fun.kt

    /**
     * 10足して返す関数を定義
     * @args i 足したい数字
     * @return i + 10
     */
    fun add(i: Int): Int {
        return i + 10
    }

    // よく使う関数
    // applyで自分自身になにかやる時に使う。let,with,runあたりも使うらしい
    private fun onItemsLoaded(items: List<Item>) {
        view?.apply {
            setItems(items)
        }
    }
    // lazy
    // キャッシュ。2回目にアクセスがあった場合は最初に呼ばれたものと同じものを返す
    private val service by lazy { ServiceGenerator.getClient()!!.create(ItemService::class.java) }



```

## interface class
https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/interfaces.html

> インタフェースは抽象メソッドの宣言と同様に、メソッドの実装を含めることができます。抽象クラスと違って、インタフェースは状態を持てません。インタフェースはプロパティを持つことができますが、これらは abstract であること、またはアクセサの実装を提供することが必要です。

```
interface LoginInterface {
    @POST("/api/login")
    fun login(@Query("mail") mail: String,
              @Query("password") password: String): Call<Login>
}
```

今のところApiを叩く部分にしか使ってない。
[square/retrofit: Type-safe HTTP client for Android and Java by Square, Inc.](https://github.com/square/retrofit)

## data class

[データクラス - Kotlin Programming Language](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/data-classes.html)

> 何もしない、データを保持するためだけのクラスを作成することはよくあります。そのようなクラスでは、いくつかの標準機能は、データから機械的に推論できます。Kotlinでは、これは データクラス と呼ばれ、 data としてマークされています。

```
data class User(val name: String, val age: Int)
```

Apiを叩いてJSONをパースしたあとの結果を保存するときによく使う。data classは継承できないのが注意

## open class

[クラスと継承 - Kotlin Programming Language](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/classes.html)

> 他のクラスがこのクラスから継承することができます。

```
open class BaseService {
    fun buildSignature() : String {
        var token: String = PreferenceManagerToken().getToken()
        return md5("$token")
    }
}

class ItemService() : BasePresenter() {

    service.item(buildSignature()).enqueue(object : Callback<List<Item>> {
        // hoge
    }
}

```

認証を必要としたApiを呼ぶ時にいい感じに変換したtokenをくっつけて呼びたい時とかに使います。


## object class

[オブジェクト式と宣言 - Kotlin Programming Language](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/object-declarations.html)

シングルトン。

```SingletonContext.kt
class SingletonContext : Application() {

    init {
        instance = this
    }

    companion object {
        private var instance: SingletonContext? = null

        fun applicationContext() : Context {
            return instance!!.applicationContext
        }
    }
}
```

## @マークについて
[Kotlinの@[アットマーク]について](https://qiita.com/AAkira/items/99028e20fcfe1a79af95) を参照

## ガード節

こうすることでifのネストが減って見やすくなるから好き

```a.kt
fun hoge(name: String?) {
    name ?: return
    // hogehoge
}
```

https://qiita.com/magie-pooh/items/b1179af28f5e0d50b62a

## realmについて

番外編。kotlinの構文とは関係ないけど
[Realm: Create reactive mobile apps in a fraction of the time](https://realm.io/)

```setup.kt
// どっかで最初に有効にしておく
Realm.init(this)
val config = RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build()
Realm.setDefaultConfiguration(config)
```

```realm.kt
open class User: RealmObject() {

    @PrimaryKey
    var id : Int? = null
    @Required
    var mail  : String = ""
}

// こんな感じ
view?.apply {
    var realm = Realm.getDefaultInstance()
    realm.executeTransaction {
       val obj = realm.createObject(User::class.java, user.id)
       obj.mail = user.mail
    }
}
```

## 拡張クラスについて

既存のクラスを拡張できる機能。realmで何か取り出すみたいなのを毎回長ったらしいのを書くのが嫌なので作った。

```realmExtention.kt
/**
 * 保存されてる最初の1件を取ってくる
 *
 * args Model::class.java
 * return RealmObject
 * 例) realm.first(User::class.java)
 */
fun <T : RealmObject> Realm.first(type: Class<T>): T? {
    return this.where(type).findFirst()
}

/**
 * 保存されてる指定されたIDを取ってくる
 *
 * args Model::class.java
 * return RealmObject
 * 例) realm.findId(User::class.java, 1)
 */
fun <T : RealmObject> Realm.findId(type: Class<T>, id: Int): T? {
    return this.where(type).equalTo("id", id).findFirst()
}

/**
 * 保存されてるデータを削除する
 *
 * args Model::class.java
 * return なし
 * 例) realm.deleteAll(User::class.java)
 */
fun <T : RealmObject> Realm.deleteAll(type: Class<T>) {
    var realm = Realm.getDefaultInstance()
    realm.executeTransaction {
        this.where(type).findAll().deleteAllFromRealm()
    }
}

```

## 参考資料

- [Kotlinアンチパターン](https://www.slideshare.net/RecruitLifestyle/kotlin-87339759)