4
1

More than 1 year has passed since last update.

【Android/Kotlin】SharedPreferencesで 保存、呼び出し、削除 ができるようになる DataBinding も使ってみる

Last updated at Posted at 2023-04-21

SharedPreferences とは

Androidアプリで簡単な永続データを保存するための仕組み。

Androidアプリは通常、起動するたびに初期化されるため、データを保存するには、起動中に取得したデータを保存する必要がある。
そこでSharedPreferencesの仕組みを使えば、アプリケーションが再起動されたときにも保存されたデータにアクセスができる。

SharedPreferencesは、名前と値のペアのセットを格納する。
名前は文字列で、値には整数、ブール値、浮動小数点数、文字列などのデータ型が使用できる。

SharedPreferencesの使用手順

  • SharedPreferencesオブジェクトをインスタンス化する
  • SharedPreferences.Editorオブジェクトを使用して、値を保存する
  • SharedPreferencesオブジェクトを使用して、保存された値を読み取る

実際にSharedPreferencesを使ってみる

手順

  • build.gradleに依存関係を追加
  • xmlでレイアウト作成
  • ViewModel追加
  • ActivityでVIewModelを呼び出せるようにする
  • ActivityでDataBindingの定義
  • ViewModelでクリックイベントを検知する
  • SharedPreferencesでデータの保存、呼び出し、削除の処理を追加する

build.gradleに依存関係を追加

android {
	dataBinding{
		enabled = true // 追加
	}
}


dependencies {
		androidTestImplementation 'androidx.test.ext:junit:1.1.5' // 追加
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' // 追加
}

xmlでレイアウト作成

<?xml version="1.0" encoding="utf-8"?>
<layout 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">
    <data>
        <--これから作成するViewModelを指定する->
        <variable
            name="vm"
            type="com.example.study.MainViewModel" />
    </data>
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/save_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="保存"
        android:onClick="@{() -> vm.saveBtn()}"
        app:layout_constraintBottom_toTopOf="@+id/read_btn"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/read_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="呼び出し"
        android:onClick="@{() -> vm.readBtn()}"
        app:layout_constraintBottom_toTopOf="@+id/delete_btn"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/save_btn" />

    <Button
        android:id="@+id/delete_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="削除"
        android:onClick="@{() -> vm.deleteBtn()}"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/read_btn" />

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

こんな感じの画面ができる
pref.png

ViewModel追加 ActivityでVIewModelを呼び出せるようにする

class MainViewModel(application: Application): AndroidViewModel(application) {

    class Factory(private val application: Application) : ViewModelProvider.Factory {
        @Suppress("UNCHECKED_CAST")
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            when (modelClass) {
                MainViewModel::class.java-> return MainViewModel(application) as T
                else -> throw RuntimeException()
            }
        }
    }
}

ActivityでDataBindingの定義

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private val mainViewModel: MainViewModel by lazy {
        ViewModelProvider(this, MainViewModel.Factory(application))[MainViewModel::class.java]
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater).also {
            it.lifecycleOwner = this
            it.vm = mainViewModel
        }
        setContentView(binding.root)
    }
}

ViewModelでクリックイベントを検知する

class MainViewModel(application: Application): AndroidViewModel(application) {

    class Factory(private val application: Application) : ViewModelProvider.Factory {
        @Suppress("UNCHECKED_CAST")
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            when (modelClass) {
                MainViewModel::class.java-> return MainViewModel(application) as T
                else -> throw RuntimeException()
            }
        }
    }

   // 以下を追加
    private var _isSaveBtnClicked = MutableLiveData(false)
    val isSaveBtnClicked: LiveData<Boolean> get() = _isSaveBtnClicked

    private var _isReadBtnClicked = MutableLiveData(false)
    val isReadBtnClicked: LiveData<Boolean> get() = _isReadBtnClicked

    private var _isDeleteBtnClicked = MutableLiveData(false)
    val isDeleteBtnClicked: LiveData<Boolean> get() = _isDeleteBtnClicked

    fun saveBtn() {
        Log.d("###ボタンクリック", "保存")
        _isSaveBtnClicked.value= true
    }

    fun readBtn() {
        Log.d("###ボタンクリック", "呼び出し")
        _isReadBtnClicked.value= true
    }

    fun deleteBtn() {
        Log.d("###ボタンクリック", "削除")
        _isDeleteBtnClicked.value= true
    }

}

SharedPreferencesでデータの保存、呼び出し、削除の処理を追加する

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private val mainViewModel: MainViewModel by lazy {
        ViewModelProvider(this, MainViewModel.Factory(application))[MainViewModel::class.java]
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater).also {
            it.lifecycleOwner = this
            it.vm = mainViewModel
        }
        setContentView(binding.root)

        mainViewModel.isSaveBtnClicked.observe(this){
            // 保存ボタンがクリックされた場合
            if(it){
                saveSharedPref()
            }
        }

        mainViewModel.isReadBtnClicked.observe(this){
            // 呼び出しボタンがクリックされた場合
            if(it){
                readSharedPref()
            }
        }

        mainViewModel.isDeleteBtnClicked.observe(this){
            // 削除ボタンがクリックされた場合
            if(it){
                deleteSharedPref()
            }
        }
    }

    private fun saveSharedPref() {
        val sharedPref = setSharedPref()

        val editor = sharedPref.edit()
        editor.putString("DataString", "文字列")
        editor.putInt("DataInt", 123)
        editor.putBoolean("DataBoolean", true)

        editor.apply() // 状態を更新
    }

    private fun readSharedPref() {
        val sharedPref = setSharedPref()

        // 読み出し
        val dataString = sharedPref.getString("DataString", null)
        Log.d("###DataString", dataString.toString())

        val dataInt = sharedPref.getInt("DataInt", 0)
        Log.d("###DataInt", dataInt.toString())

        val dataBoolean = sharedPref.getBoolean("DataBoolean", false)
        Log.d("###DataInt", dataBoolean.toString())
    }

    private fun deleteSharedPref() {
        val sharedPref = setSharedPref()

        val editor = sharedPref.edit()
        editor.remove("DataString")
        editor.remove("DataInt")
        editor.remove("DataBoolean")

        editor.apply() // 状態を更新
    }

    private fun setSharedPref(): SharedPreferences {
        return getSharedPreferences(
            getString(R.string.preference_file_key), Context.MODE_PRIVATE
        )
    }

}

ログで動作確認

  • 呼び出しボタンクリック
    デフォルト値が入っている
D/###ボタンクリック: 呼び出し
D/###DataString: null
D/###DataInt: 0
D/###DataInt: false
  • 保存ボタンクリック + 呼び出しボタンクリック
    saveSharedPref メソッドで追加した値が入っている
D/###ボタンクリック: 保存
D/###ボタンクリック: 呼び出し
D/###DataString: 文字列
D/###DataInt: 123
D/###DataInt: true
  • 削除ボタンクリック+呼び出しボタンクリック
    データが削除されてデフォルト値が入っている
D/###ボタンクリック: 削除
D/###ボタンクリック: 呼び出し
D/###DataString: null
D/###DataInt: 0
D/###DataInt: false

おわりに

ログイン情報を保持するのに使いました。おさらいで記事にしてみました。
がんばるぞい!

4
1
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
4
1