Image
Android Jetpack/Datastore

[Android Datastore] 4. Proto Datastore 사용 방법 한 번에 정리하기

환경세팅

안드로이드에서 Proto Datastore을 사용하기 위해서는 Type Safety를 위한 처리를 해주어야 하기 때문에 Preference Datastore보다 복잡하다.

 

Gradle 파일 세팅

1. 모듈 수준의 gradle 파일에 플러그인을 추가한다.

plugins {
    ..
    id("com.google.protobuf") version "0.8.17"
}

 

2. 모듈 수준의 gradle에 라이브러리를 추가한다. 하나는 datastore 라이브러리이고 다른 하나는 protocol buffer을 위한 java 라이브러리이다.

dependencies {
    ..
    implementation("androidx.datastore:datastore:1.0.0")
    implementation("com.google.protobuf:protobuf-javalite:3.19.4")
}

 

3. protobuf 블록을 module 수준의 gradle에 추가한다. 이 내부의 generateProtoTask는 Protocol Buffer을 사용하기 위해 Code Generation 작업을 해준다.

protobuf {
    protoc {
        // The artifact spec for the Protobuf Compiler
        artifact = "com.google.protobuf:protoc:3.19.4"
    }

    generateProtoTasks {
        all().forEach { tasks ->
            tasks.builtins {
                id("java") {
                    option("lite")
                }
            }
        }
    }
}

 

자 여기까지 Proto Datastore을 사용하기 위한 준비를 마쳤다. 이제 본격적으로 사용해보도록 하자.

 

 

Proto Datastore 사용하기

1. Proto Datastore을 사용하기 위해서는 먼저 Proto Datastore 내부에 Type Safe하게 저장할 수 있는 객체를 만드는 작업이 필요하다. app/src/main/proto directory를 생성하고 내부에 .proto 파일을 만든다. 

 

그림1. proto 파일 만들기

 

 

2. .proto 파일 내부에는 3가지가 필요하다.

  • 첫째 syntax 를 설정하여 protocol buffer 3버전을 사용한다는 것을 명시한다.
  • 둘째 proto가 생성될 패키지명을 추가하고 java_multiple_files 옵션을 true로 한다.
  • 마지막으로 가장 중요한 message는 Proto Datastore에 입력될 데이터의 구조이다. 이 데이터 구조는 Code Generation이 되면서 클래스로 변환된다. 

예제는 다음과 같다.

syntax = "proto3"; // syntax 를 설정하여 protocol buffer 3버전을 사용한다는 것을 명시

option java_package = "[패키지명]"; // 클래스가 생성될 package 명 명시
option java_multiple_files = true;

message OnBoardingState { // 데이터 구조 정의
  bool isAddTodo = 1;
  bool isChangeSequenceDone = 2;
  bool isPermissionGranted = 3;
}

 

 

3. .proto 파일을 작성한 후 Rebuild를 눌러 빌드가 되면 message가 java class로 Auto Generation된다. 위 2번에서 생성한 .proto 파일에 의해 생성된 클래스는 [그림2]와 같다.

 

그림2. proto 파일 java 파일로 생성

 

 

4.  다음은 Datastore가 [그림2]의 클래스를 직렬화, 역직렬화 할 수 있도록 Serializer을 생성해야 한다. Proto Datastore의 Serializer은 직렬화, 역직렬화를 하도록 하는 인터페이스로 readFrom을 통해 역직렬화가 수행되고 writeTo를 통해 직렬화가 수행된다. 이 Serializer은 직접 구현해야 한다. 

 

Serializer 내부의 구현은 우리가 3번에서 생성한 클래스에 의해 가능하다. 자동 생성된 클래스는 그 자체로 직렬화, 역직렬화 할 수 있는 메서드들을 가지고 있다. parseFrom은 InputStream을 인자로 받아 역직렬화를 하는 메서드이며, writeTo는 객체를 직렬화 하여 OutputStream에 넣는 작업을 하는 메서드이다.

 

위에서 작성한 OnBoardingState를 위한 Serializer의 구현체는 다음과 같다.

object OnBoardingStateSerializer : Serializer<OnBoardingState> {
    override val defaultValue: OnBoardingState = OnBoardingState.getDefaultInstance()

    override suspend fun readFrom(input: InputStream): OnBoardingState {
        try {
            return OnBoardingState.parseFrom(input)
        } catch (exception: InvalidProtocolBufferException) {
            throw CorruptionException("Cannot read proto.", exception)
        }
    }

    override suspend fun writeTo(
        t: OnBoardingState,
        output: OutputStream
    ) = t.writeTo(output)
}

val Context.storeOnBoardingState: DataStore<OnBoardingState> by dataStore(
    fileName = "onboardingSettings.pb",
    serializer = OnBoardingStateSerializer
)

 

 

5. 마지막으로 Datastore을 사용하기 위해 dataStore의 파일 이름을 설정하고 이 dataStore을 사용할 때 사용할 Serializer을 설정한다. 

val Context.storeOnBoardingState: DataStore<OnBoardingState> by dataStore(
    fileName = "onboardingSettings.pb",
    serializer = OnBoardingStateSerializer
)

 

6. 위와 같이 설정을 마쳤으면 Context가 있는 곳에서 storeOnBoardingState 라는 변수로 dataStore을 사용할 수 있게 된다.

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        storeOnBoardingState.data
        ..
    }
}
반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com