[Android/Kotlin]AndroidStudio4.1でViewModelを使う

なんか前のやり方でできなくなってたので

# 環境
 - Android Studio 4.1
 - Kotlin
 - Mac

# 結論
### ライブラリ
```xml:build.gradle(app)
plugins {
    id 'kotlin-android-extensions'
}

dependencies {
    // ViewModel
    implementation "androidx.activity:activity-ktx:1.1.0" // Activityから使う時
    implementation "androidx.fragment:fragment-ktx:1.2.5" // Fragmentから使う時
}
```
バージョンは
[Activity - AndroidDeveloper](https://developer.android.com/jetpack/androidx/releases/activity?hl=ja)
[Fragment - AndroidDeveloper](https://developer.android.com/jetpack/androidx/releases/fragment?hl=ja)
から安定版を使用
いやなんでこれデフォルトで入ってないんだよ

`extensions`は`synthetic`でfindViewByIdの代わりにする時のやつ
[Kotlin Android Extensionsを試してみた - Qiita](https://qiita.com/rei-m/items/c808fd0b6b83303bd3a2)
今まではデフォルトで入ってたのに4.1で消えた
今後は[ViewBinding](https://developer.android.com/topic/libraries/view-binding?hl=ja)が推奨らしいのでそっちにしましょう
この記事は修正がめんどくさいのでそのままですが

### Activity
```kotlin:MainActivity.kt
val viewModel: SampleViewModel by viewModels() 
```
Activityから呼ぶ時は`by viewModels()`

### Fragment
```kotlin:SampleFragment.kt
val viewModel: SampleViewModel by activityViewModels() // Activityと同じViewModel使う時はこっち
val viewModel: SampleViewModel by viewModels() // こっちだと新しいインスタンスを作成っぽい
```
Fragmentから呼ぶ時は二通り、好きな方を使う
Activityと同じインスタンスを使いたければ`by activityViewModels()`

### ViewModel
```kotlin:SampleViewModel.kt
class SampleViewModel: ViewModel() {
    // 中身
}
```
ViewModelは変わらず、ViewModel()を継承するだけ

# コード全文
[とにかく簡単にViewModelまとめ](https://qiita.com/KIRIN3qiita/items/7d833e2c010c0b2c02d9)リスペクトで、ActivityとViewModelそれぞれの変数からtextViewに表示してボタンを押したら値を+1するサンプル
ViewModelって何？の説明もリスペクト元の記事に短くまとまってるのでどうぞ
[Github](https://github.com/yuki-kamikita/ViewModelSample)

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textActivity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        app:layout_constraintBottom_toTopOf="@+id/textViewModel"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textViewModel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textViewModel" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

```kotlin:MainActivity.kt
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.viewModels // by viewModels()用
import kotlinx.android.synthetic.main.activity_main.*

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

        val viewModel: SampleViewModel by viewModels() // ViewModelのインスタンスを作成
        var activityVariable: Int = 0 // Activityに保存する変数

        // 画面作成時に表示
        textActivity.text =  activityVariable.toString() // Activityの変数を表示
        textViewModel.text = viewModel.viewModelVariable.toString() // ViewModelの変数を表示

        // ボタンを押したら+1する
        button.setOnClickListener {
            // 変数の値を+1
            activityVariable++
            viewModel.viewModelVariable++

            // 表示
            textActivity.text =  activityVariable.toString()
            textViewModel.text = viewModel.viewModelVariable.toString()
        }
    }
}
```

```kotlin:SampleViewModel.kt
import androidx.lifecycle.ViewModel

class SampleViewModel: ViewModel() {
    var viewModelVariable: Int = 0 // ViewModelに保存する変数
}
```







# 参考にした記事
[Android Jetpack(AndroidXライブラリ)の最近の更新](https://qiita.com/FKbelm/items/4824fcf8e7eb7c879f81)
[[Android]lifecycleライブラリ2.2.0からViewModelProviders.ofが非推奨になっちゃった件](https://minpro.net/viewmodelproviders-of-deprecated)