https://developer.android.com/training/data-storage/shared-preferences?hl=ko
키-값 데이터 저장 | Android 개발자 | Android Developers
키-값 데이터 저장 저장하려는 키-값 컬렉션이 비교적 작은 경우 SharedPreferences API를 사용해야 합니다. SharedPreferences 객체는 키-값 쌍이 포함된 파일을 가리키며 키-값 쌍을 읽고 쓸 수 있는 간단
developer.android.com
https://www.youtube.com/watch?v=4rYMfpbpwPA&list=PL_XkuR-7VWcuee4kxHgChRvQCmHxcJnfS&index=13
위 영상 참고해서 실습했음
데이터를 앱에 저장하는 방법
- 파일 I/O (내부 또는 외부 저장소)
접근 권한을 획득하고 파일을 열었다 닫았다 하는 수고가 필요 - 관계형 데이터베이스
간단한 데이터를 저장할 것이라면 구축과 관리에 많은 시간과 노력이 요구됨
SQLite 등을 이용해 복잡한 관계형 데이터를 저장할 수 있음 - SharedPreference
내부적으로는 XML 파일로 저장됨
파일을 열고 닫을 필요 없이 핸들러만 만들어서 간편하게 사용 가능
Key = Value 형태로 저장 가능
SharedPreferences 사용법
1) sharedPreferences 객체 생성
- getPreferenes : 하나의 Activity에서만 사용 가능, 특정 Activity만의 설정값을 저장할 때 사용
- getSharedPreferences : 앱의 모든 context에서 호출 가능, 주로 앱의 전역 데이터값을 저장할 때 사용
- getDefaultSharedPreferences
val sharedPreferences = getSharedPreferences(key, mode)
getSharedPreferences(key, mode) : 핸들러를 받아옴
mode 종류
- MODE_PRIVATE
- MODE_WORLD_READABLE (deprecated)
- MODE_WORLD_WRITEABLE (deprecate)
- MODE_MULTI_PROCESS
작성한 앱에서만 접근 가능하게 하는 MODE_PRIVATE 사용
WORLD가 붙은 모드는 다른 앱에서도 사용이 가능하게 할 수 있다고 알아두기
2) editor 생성
edit() 메소드 사용
val editor = sharedPreferences.edit()
editor를 써서 기록할 데이터를 메모리에 올림
3) 데이터 쓰기 (메모리 상의 값에 대한 쓰기 작업)
editor.putInt(key, value)
editor.putBoolean(key, value)
4) 실제 파일에 쓰기 작업
- apply() : 호출 후 곧바로 리턴되어 스레드를 블록시키지 않음
- commit() : 호출 시 스레드 블록되어 커널에서 파일 저장 완료 후 함수는 리턴되고
스레드는 다시 작동하며 처리 결과를 true/ false로 반환
결과값이 필요없다면 apply를 사용하는 것이 반응성 면에서 좋음
editor.apply()
▽ 출처
실습
1) activity_main.xml
▽ 코드
<!-- 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/game_setting_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Game Settings"
android:textSize="30dp"
android:layout_marginStart="20dp"
android:layout_marginTop="40dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/graphic_quality_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Graphic Quality"
android:layout_marginTop="30dp"
app:layout_constraintStart_toStartOf="@id/game_setting_tv"
app:layout_constraintTop_toBottomOf="@+id/game_setting_tv"/>
<RadioGroup
android:id="@+id/graphic_quality_rg"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:checkedButton="@id/graphic_quality_Medium_rb"
app:layout_constraintTop_toBottomOf="@id/graphic_quality_tv"
app:layout_constraintStart_toStartOf="@id/graphic_quality_tv">
<RadioButton
android:id="@+id/graphic_quality_low_rb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="Low"/>
<RadioButton
android:id="@+id/graphic_quality_Medium_rb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="Medium"/>
<RadioButton
android:id="@+id/graphic_quality_high_rb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="High"/>
</RadioGroup>
<TextView
android:id="@+id/music_volume_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Music Volume"
android:layout_marginTop="30dp"
app:layout_constraintStart_toStartOf="@id/game_setting_tv"
app:layout_constraintTop_toBottomOf="@+id/graphic_quality_rg"/>
<SeekBar
android:id="@+id/music_volume_sb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_marginTop="20dp"
app:layout_constraintTop_toBottomOf="@id/music_volume_tv"/>
<TextView
android:id="@+id/sfx_volume_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SFX Volume"
android:layout_marginTop="30dp"
app:layout_constraintStart_toStartOf="@id/game_setting_tv"
app:layout_constraintTop_toBottomOf="@+id/music_volume_sb"/>
<SeekBar
android:id="@+id/sfx_volume_sb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_marginTop="20dp"
app:layout_constraintTop_toBottomOf="@id/sfx_volume_tv"/>
<TextView
android:id="@+id/enable_vertical_sync_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enable Vertical Sync"
android:layout_marginTop="30dp"
app:layout_constraintStart_toStartOf="@id/game_setting_tv"
app:layout_constraintTop_toBottomOf="@+id/sfx_volume_sb"/>
<Switch
android:id="@+id/vsync_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:checked="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/enable_vertical_sync_tv"
app:layout_constraintBottom_toBottomOf="@id/enable_vertical_sync_tv"/>
<Button
android:id="@+id/save_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save"
android:layout_marginTop="30dp"
app:layout_constraintTop_toBottomOf="@id/enable_vertical_sync_tv"
app:layout_constraintEnd_toStartOf="@id/load_btn"
app:layout_constraintStart_toStartOf="parent"/>
<Button
android:id="@+id/load_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Load"
android:layout_marginTop="30dp"
app:layout_constraintTop_toBottomOf="@id/enable_vertical_sync_tv"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/save_btn"/>
</androidx.constraintlayout.widget.ConstraintLayout>
2) MainActivity.kt
package com.example.sharedpreferencetest
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.widget.Toast
import com.example.sharedpreferencetest.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.saveBtn.setOnClickListener {
savePref()
}
binding.loadBtn.setOnClickListener {
loadPref()
}
}
private fun savePref(){ // save 버튼 터치시 동작
val sharedPreferences = getSharedPreferences(KEY_PREFS, MODE_PRIVATE) // sharedPreferences 객체 생성
val editor = sharedPreferences.edit() // editor 생성
// 메모리 상에 데이터 쓰기
editor.putInt(KEY_GRAPHIC, binding.graphicQualityRg.checkedRadioButtonId)
editor.putInt(KEY_MUSIC,binding.musicVolumeSb.progress)
editor.putInt(KEY_SFX,binding.sfxVolumeSb.progress)
editor.putBoolean(KEY_VSYNC,binding.vsyncSwitch.isChecked)
// 실제 파일에 쓰기 작업
editor.apply()
// 확인용 토스트 메시지
Toast.makeText(this,"Game settings has saved",Toast.LENGTH_SHORT).show()
}
private fun loadPref(){ // load 버튼 터치시 동작
val sharedPreferences = getSharedPreferences(KEY_PREFS, Context.MODE_PRIVATE) // sharedPreferences 핸들러 받아옴
if(sharedPreferences.contains(KEY_GRAPHIC)){ // 저장된 값이 있다면 값 가져오기
val graphicValue = sharedPreferences.getInt(KEY_GRAPHIC,0)
val musicValue = sharedPreferences.getInt(KEY_MUSIC,50)
val sfxValue = sharedPreferences.getInt(KEY_SFX,50)
val vsyncValue = sharedPreferences.getBoolean(KEY_VSYNC,true)
// 저장해놓은 값으로 UI 변경
binding.graphicQualityRg.check(graphicValue)
binding.musicVolumeSb.progress = musicValue
binding.sfxVolumeSb.progress = sfxValue
binding.vsyncSwitch.isChecked = vsyncValue
// 확인용 토스트 메시지 출력
Toast.makeText(this,"Game setting has loaded",Toast.LENGTH_SHORT).show()
}
}
// SharedPreference는 key = value값으로 저장하기 때문에
// savePref와 loadPref에서 동시에 사용하는 key값을 companion object로 미리 설정
companion object{ // static 정도로 생각
private const val KEY_PREFS = "game_settings"
private const val KEY_GRAPHIC = "graphic_quality"
private const val KEY_MUSIC = "music_volume"
private const val KEY_SFX = "sfx_volume"
private const val KEY_VSYNC = "vertical"
}
}
결과 화면
1) 시작 화면
2) 세팅 변경 후 save
3) 앱을 나갔다가 load
간단한 값들을 저장할 때 유용하게 사용됨
jwt 저장 등
'Native App > 👽Android' 카테고리의 다른 글
web Crawling - Jsoup (0) | 2022.06.27 |
---|---|
kakao login api 사용 - 2 (0) | 2022.06.19 |
kakao login api 사용 - 1 (0) | 2022.06.16 |
#01 Coroutine (0) | 2022.06.04 |
우분투 환경에 안드로이드 스튜디오 설치 (0) | 2022.01.24 |
댓글