2023. 4. 1. 14:04ㆍAndroid
써야지 써야지하다 이제야 도전해보는 Room 솔직히 지금까지는 크게 필요하지 않아서 사용하지 않았는데... 아니 미뤘는데 필요하게되서 사용하며 공부했던걸 정리해본다.
발생했던 문제점
- 원치 않았던 데이터까지 데이터베이스에 저장됨 -> 잘못된 아이디와 비밀번호가 자꾸 디비에 저장되는 일
일단 시작하기전 build.gradle 세팅
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.google.gms.google-services'
id 'kotlin-kapt'
}
// room
def room_version = "2.5.0"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
나는 사용자가 로그인시 로그인한 아이디 값과 비밀번호 값을 저장해 WebView에 로그인이 필요한 사이트에 자동로그인을 구현하기 위해 해당 코드를 작성하게 되었다.
1. 유저 data class
@PrimaryKey 고유키 값을 말하며 뒤에 있는 autoGenerate를 true로 할 경우 고유키 값이 자동으로 증가하게 된다
@Entity(tableName = "user")
data class User(
@PrimaryKey(autoGenerate = false)
var id: Int = 0,
var loginId: String,
var loginPw: String
)
2. Dao 명령어 작성 interface
자신에게 필요한 구문들을 작성한다. 특별한 것은 없다
@Dao
interface UserDao {
@Query("SELECT * FROM user WHERE id = :id")
fun getUser(id : Int): User
@Query("SELECT * FROM user")
fun getAll() : List<User>
@Insert
fun insert(user: User)
@Query("DELETE FROM user")
fun deleteAllUsers()
}
3. DataBase 작성
기존에는 version = 1을 사용하다 스키마를 변경하게 되면서 2버전으로 올렸다
compaion object를 이용해 하나의 프로젝트에 공유되는 데이터베이스를 만들어줬다.
데이터베이스 이름은 원하는 목적에 맞게 설정
@Database(entities = [User::class], version = 2)
abstract class AppDatabase : RoomDatabase() {
abstract fun UserDao(): UserDao?
companion object {
private var INSTANCE: AppDatabase? = null
fun getDBInstance(context: Context): AppDatabase? {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"User_data"
)
.allowMainThreadQueries()
.build()
}
return INSTANCE
}
}
}
그리고 Activity 혹은 Fragment에서 필요한 부분에 사용하면 된다.
나는 Activity 부분에 사용하였다. 로그인 아이디와 패스워드가 필요해 저장하게 되었다.
lateinit var db : AppDatabase
db = AppDatabase.getDBInstance(this.applicationContext)!!
해당 메소드는 로그인의 데이터가 비어있는지 확인하고 로그인 메소드를 실행한다.
private fun loginData() {
// 로그인 아이디 패스워드 입력후 버튼 눌러서 전송
id = E_id.text.toString()
pw = E_pw.text.toString()
if (id.isEmpty() || pw.isEmpty()) {
showErrorMessage("아이디 또는 비밀번호를 입력하세요.")
return
}
login()
}
로그인 메소드를 보면
db.UserDao()!!.insert(user) 구분에서 로그인에 성공하면 아이디 값과 비밀번호를 저장하는 로직을 실행해줬다
private fun login() {
val user = User(loginId = id, loginPw = pw)
call?.login(token, LoginData(E_id.text.toString(), E_pw.text.toString()))?.enqueue(object : Callback<LoginDTO>{
override fun onResponse(call: Call<LoginDTO>, response: Response<LoginDTO>) {
if (response.isSuccessful) {
val result : LoginDTO? = response.body()
Log.d("Login_Log", "$result")
if (result?.result?.user_key != null) {
Loginkey.setUserKey(this@LoginActivity, result.result.user_key.toInt())
Loginkey.setTokenKey(this@LoginActivity, token)
Log.d("Login_key", "${result.result.user_key.toInt()}")
Log.d("setTokenKey", token)
db.UserDao()!!.insert(user)
Log.d("DataBase 저장 완료", "${db.UserDao()!!.getUser(0)}")
val intent = Intent(this@LoginActivity, MainActivity::class.java)
Toast.makeText(this@LoginActivity, "로그인 성공", Toast.LENGTH_LONG).show()
startActivity(intent)
finish()
} else {
Toast.makeText(this@LoginActivity, "아이디 또는 비밀번호가 잘못되었습니다", Toast.LENGTH_SHORT).show()
Log.d("Login_Log", "user_key null")
}
}
}
override fun onFailure(call: Call<LoginDTO>, t: Throwable) {
Toast.makeText(this@LoginActivity, "로그인 실패", Toast.LENGTH_LONG).show()
Log.d("Login_Log", "${t.message}")
}
})
}
그런데 처음 코드를 작성할 때 로그인에 실패했을 때도 데이터베이스에 실패했던 데이터들이 저장시도가 되어 Primary 키값이 증가하는 현상이 발생하였다.
일단 키값이 증가하는 문제는 잘못된 데이터들이 저장이되면서 증가하는 문제가 발생하는거 같았다 때문에 autoGenerate 값을 false로 바꿔주었다. 또한 앱에 캐시가 남아 저장되는 것 같아서 manifest에서 해당 코드들을 application 단에 추가해줬다
해당 백업 기능은 사용자가 애플리케이션을 지우고 다시 설치했을 때 지우기 전 데이터가 남아있게 만들어 복구하는데 사용한다
android:allowBackup="false"
해당 백업 기능은 사용자의 데이터를 구글 백업 서비스로 자동 백업을 하지 않겠다고 만드는 역할이다
android:fullBackupContent="false"
해당 코드를 입력하고 실행해보니 처음 생겼던 오류들을 해결하게 되었다.