Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 1 year has passed since last update.

【Android】画面回転したらデータが消えた【ViewModel】

Posted at

よくラボでViewModelって言葉聞くのですが、
なんの事やらさっぱりだったので個人的にまとめてみました。

ViewModelクラスとは?

役割を一言で言うと 「UIコンポーネントとデータ処理を切り分ける」 です。
アクティビティ(UIコンポーネント)にデータを保持させるのでは無く、
ViewModelクラスにデータを持たせる事で画面の再生成や様々な状態変化に対して
データの保持と同期を行います。


今回は、ViewModelを活用して
画面を回転をしても、保存した値が破棄されず
回転前に保存した値が表示されるような画面を作成します。
FortuneCase – MainActivity.kt [FortuneCase.app.main] 2024_01_15 1_12_10.png
↑横画面にしても「123」と表示されるようにしたい。(右の方)

ViewModelの使い方

ViewModelを継承したクラスを作成

まず、ViewModelを継承したMyViewModelクラスを作成します。
中では、変数やメソッドを宣言します。
今回は、Int型の値を保持するための変数を宣言します。

class MyViewModel :ViewModel() {
    var numHolder : Int = 0 //初期値
}

Activity内での設定

①ViewModelのインスタンスを取得

ActivityでViewModelを使用するには、インスタンスを取得する必要があります。

val myViewModel: MyViewModel
// 構成変更中もViewModelが生き残るようにViewModelProviderとAndroidViewModelFactoryを使用
myViewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application))[MyViewModel::class.java]

②ViewModelの保持する値を更新

取得したインスタンスを使用し、保持している値を更新します。
今回は、EditTextViewに入力された値を保持するように設定します。

//保存ボタンを押された時
binding.saveButton.setOnClickListener {
    //入力された値に更新
    myViewModel.numHolder = binding.edit2.text.toString().toInt()
}

③更新した値を表示する

ボタンを押すとMyViewModelクラスの変数numHolderを表示する設定をします。

//表示ボタンを押された時
binding.displayButton.setOnClickListener {
    //保持している値を表示
    binding.viewModelSavedTextView.text = myViewModel.numHolder.toString()
}

実際に実行!

Activityに保存された場合とViewModelに保存された時を比較します。
どのような違いがあるのでしょうか?

Activityのコード

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    //この変数に格納された値が左の「ここに表示される」に表示される
    private var activityNumHolder = 0
    private lateinit var myViewModel: MyViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        //レイアウトのインフレート
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //ViewModelのインスタンスを取得
        myViewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application))[MyViewModel::class.java]

        //保存ボタン
        binding.saveButton.setOnClickListener {
            activityNumHolder = binding.edit1.text.toString().toInt()
            myViewModel.numHolder = binding.edit2.text.toString().toInt()
        }

        //表示ボタン
        binding.displayButton.setOnClickListener {
            binding.activitySavedTextView.text = activityNumHolder.toString()
            binding.viewModelSavedTextView.text = myViewModel.numHolder.toString()
        }
    }
}

MyViewModelのコード

class MyViewModel :ViewModel() {
    var numHolder : Int = 0 //初期値
}

①デフォルト画面

まずはデフォルト画面を確認しましょう。
「ここに表示される」にActivityとViewModelの変数の値が表示されます。
FortuneCase – MainActivity.kt [FortuneCase.app.main] 2024_01_15 1_11_19.png

②変数の初期値の確認

表示ボタンを押して初期値を確認します。
今回はどちらも初期値は「0」に設定しました。
FortuneCase – MainActivity.kt [FortuneCase.app.main] 2024_01_15 1_11_28.png

③入力した値を表示

以下の手順で入力した値を表示します。
値を入力→保存→表示
どちらも、値を保持し表示することができていますね!
FortuneCase – MainActivity.kt [FortuneCase.app.main] 2024_01_15 1_12_10.png

④画面を横に回転

画面の構成をするとActivityは一度破棄されて、
再度OnCreate()から処理を行います。
値を表示するViewも一度初期化されるためどちらもデフォルト状態になっています。
FortuneCase – MainActivity.kt [FortuneCase.app.main] 2024_01_15 1_12_33.png

⑤値の確認

表示ボタンを押して、保持して値の確認をします。
FortuneCase – MainActivity.kt [FortuneCase.app.main] 2024_01_15 1_12_43.png
Activityで保持している値は、初期値になっており
ViewModelで保持している値は、更新した値になっていますね!

まとめ

ViewModelの超基本知識です!

参考

とにかく簡単にViewModelまとめ

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?