DataStore는 SharedPreference의 대체 class로 보안을 강화한 Jetpack class중 하나이다.
디바이스에 data를 처리해줄 수 있는 기능을 제공한다.
compose를 이용해서 proto datastore를 이용해 간단한 예제를 연습하려고한다.
DataStore로 만들어 볼 예제
1. EditText에 text를 입력한다.
2. 버튼을 누른다.
3. 버튼을 누르면 디바이스에 해당 text가 저장된다.
처음해보는 분들은 내 github를 참고하여 만들어봐도 좋을거같다!
https://github.com/kof99athena/TPProtoData
step1. gradle에 datastore 를 사용하기 위한 코드 추가
처음에 공식문서만 보고 하다가 적용이 안되서 스택오버플로우를 보니 protobuf에 관련된 플러그인도 추가해야한다는것을 알았다.
난이도가 좀 있는 Jetpack을 사용하려면 빌드부터 꼼꼼하게 챙겨야하는거같다. 🤣
그리고 protobuf의 문법이 잘못되었는지, 앱빌드가 계속 안되서 스택오버플로우를 뒤져보아서 코드를 수정했다..
앱 수준의 gradle
import com.google.protobuf.gradle.*
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
id("com.google.protobuf") version "0.9.4"
}
val protobufVersion = "3.21.7"
dependencies {
implementation("com.google.protobuf:protobuf-javalite:$protobufVersion")
implementation("androidx.datastore:datastore:1.0.0-alpha03")
implementation("androidx.datastore:datastore:1.1.1")
// optional - RxJava2 support
implementation("androidx.datastore:datastore-rxjava2:1.1.1")
// optional - RxJava3 support
implementation("androidx.datastore:datastore-rxjava3:1.1.1")
....
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:$protobufVersion"
}
plugins {
generateProtoTasks {
all().forEach {
it.builtins {
create("java") {
option("lite")
}
}
}
}
}
}
project 수준의 gradle
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.jetbrains.kotlin.android) apply false
id("com.google.protobuf") version "0.9.4" apply false
}
step2. 확장자가 .proto인 파일을 프로젝트에 만들기
project 수준으로 변경한 후, app/main에 proto 패키지를 생성한다.
그 이후에 .proto 파일을 만들고, 공식문서에서 제공하는 스키마를 복붙하여 가져온다.
여기서 변경 해줘야할 부분이 있다!
option java_package: 나의 패키지명
message Settings: 이 Settings는 추후 내가 사용할 데이터와 관련된 자료형이된다! 내가 이름을 직접 지어줘야한다!
그렇기때문에 Settings로 두지말고 이름을 바꿔보자. 나는 MyUserData라는 자료형을 만들어서 사용했다.
브라켓안에는 내가 사용할 변수를 지정하는것이다. (숫자는 변수에 부여하는 고유한 숫자)
syntax = "proto3";
option java_package = "내 패키지명";
option java_multiple_files = true;
message MyUserData {
string name = 1;
}
이 과정까지한후 , 프로젝트가 내 MyUserData 자료형을 인식 할 수 있도록 리빌드한다
이제 MyUserData라는 class가 생긴다.
step 3. 본격 Proto Datastore 만들기
우선 Serializer해줄 Object를 만든다.
Context를 갖고있는 class 에서는 (예를들면 Activity), settingsUserData라는 변수로 해당 데이터를 불러올수있다!
object UserDataSerializer : Serializer<MyUserData> {
override val defaultValue: MyUserData = MyUserData.getDefaultInstance()
override suspend fun readFrom(input: InputStream): MyUserData {
try {
return MyUserData.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception)
}
}
override suspend fun writeTo(t: MyUserData, output: OutputStream) = t.writeTo(output)
val Context.settingsUserData: DataStore<MyUserData> by dataStore(
fileName = "userdata.pb", //로컬에 저장될 protobuf 파일명
serializer = UserDataSerializer
)
}
step4. Main Activity
class MainActivity : ComponentActivity() {
private val Context.settingsUserData: DataStore<MyUserData> by dataStore(
fileName = "userdata.pb", //로컬에 저장될 protobuf 파일명
serializer = UserDataSerializer
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
TPProtoDataTheme {
val dataStore = applicationContext.settingsUserData
val savedUserName = dataStore.data.map { // MyUserData의 data인 name
settingsUserData ->
settingsUserData.name
}.collectAsState(initial = "")
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = savedUserName.value,
modifier = Modifier.padding(innerPadding),
onSave = { userName ->
lifecycleScope.launch {
dataStore.updateData { currentNames ->
currentNames.toBuilder()
.setName(userName)
.build()
}
}
}
)
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier, onSave: (String) -> Unit) {
var text by remember {
mutableStateOf(name)
}
Column(Modifier.padding(all = 32.dp)) {
TextField(value = text, onValueChange = { text = it })
Button(onClick = { onSave(text) }) {
Text(text = "save")
}
}
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
TPProtoDataTheme {
Greeting("Android") {}
}
}
step5. 이제!! 준비해둔 TextField에 userName을 입력해보자!! save button 클릭~
그리고 Device Explorer에 들어가서 내가 저장한 userName이 저장되었는지 확인해보자.
/data/data/내 패키지/files/datastore/userdata.pb
userdata.pb는 내가 지정한 fileName이다!
입력한 userName "Android Cat"이 정상적으로 입력되었다 😆
초기 세팅이 어려울 뿐, 생각보다 더 간단해서 놀랐다!!
이렇게 Proto DataStore로 디바이스 하드웨어에 CURD 기능 처리가 가능하다. 뿌듯~ 😆
'Android Compose' 카테고리의 다른 글
Android Compose Slot API란? (0) | 2024.08.12 |
---|---|
Composable functions with non-default parameters are not supported in Preview unless they are annotated with @PreviewParameter (0) | 2024.07.14 |
XML에서 Compose로 마이그레이션 gradle 세팅하기 (feat. BOM이란?) (0) | 2024.07.14 |
선언형이란? (1) | 2024.07.13 |
Android 컴포즈를 쓰는 이유는? (1) | 2024.07.13 |