iT邦幫忙

2022 iThome 鐵人賽

DAY 29
0

接續上一篇"Day28 - Jetpack DataStore (上) | Preferences DataStore", 今天要介紹的DataStore的另一種實作方式Proto DataStore。如果還不清楚DataStore的另一種實作方式, 建議可以先回去看上一篇文章。

一、環境設置 - 添加依賴

Proto DataStore

  • build.gradle(App)
plugins {
    ...
    id 'com.google.protobuf' version '0.8.12' apply false
}
  • build.gradle(Module)
plugins {
    ...
    id "com.google.protobuf"
}

// Typed DataStore (Typed API surface, such as Proto)
dependencies {
    implementation "androidx.datastore:datastore:1.0.0"
    implementation "com.google.protobuf:protobuf-javalite:3.14.0"

    // 可選 - 支持RxJava2
    implementation "androidx.datastore:datastore-rxjava2:1.0.0"

    // 可選 - 支持RxJava3 
    implementation "androidx.datastore:datastore-rxjava3:1.0.0"
}

protobuf {
    protoc {
        // 這裡設置的版本要和implementation "protobuf-javalite"的版本一致
        artifact = "com.google.protobuf:protoc:3.14.0"
    }
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java {
                    option "lite"
                }
            }
        }
    }
}

二、Proto DataStore 簡單使用

步驟:

  1. 預定義結構
  2. 重新Rebuild您的項目
  3. 創建Serializer
  4. 簡單操作

(1) 預定義結構

注意!!! Proto DataStore要求在app/src/main/proto/下創建

user_prefs.proto

syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.scc.datastorage.proto";

message UserInfo{
  String name = 1;
  int32 age = 2;
}

建議! 預定義結構的文件以.proto結尾,這有助於防止不同項目之間的命名衝突。

  • syntax:用於指定此文件用的是proto3語法; 如果沒有這行,protocol-buffers編譯器將假設您使用的是proto2注意! 這必是寫在文件的第一個非空、非註釋行才會生效。
  • java_multiple_files:可以為每個生成的類 生成一個單獨的.java文件。
  • java_package:指定生成的類應該使用什麼Java包名稱。

查看更多!
由於這個範例只是簡單使用Proto DataStore,所以沒有介紹太多protocol-buffres語法,如果想要知道更詳細的,可以到這個網站查看https://developers.google.com/protocol-buffers

(2) 重新Rebuild您的項目

完成第一步後一定要做的動作!

  • 注意! 如果你重新Rebuild項目後還是沒有產生第一步創建的預定義結構那可能表示你環境設置有問題。
  • 成功的結果
    由於我們第一步所建立的預定義結構類型為UserInfo,所以當重新Rebuild Project後就會產生出對應的資料類,如下圖所示:

(3) 創建Serializer

定義一個實現Serializer<T>的類,其中T是proto文件中定義的類型。

  • UserInfoSerializer.java
public class UserInfoSerializer implements Serializer<UserInfo> {

    @Override
    public UserInfo getDefaultValue() {
        return UserInfo.getDefaultInstance();
    }

    @Nullable
    @Override
    public UserInfo readFrom(@NonNull InputStream inputStream, @NonNull Continuation<? super UserInfo> continuation) {
        try {
            return UserInfo.parseFrom(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Nullable
    @Override
    public UserInfo writeTo(UserInfo userInfo, @NonNull OutputStream outputStream, @NonNull Continuation<? super Unit> continuation) {
        try {
            userInfo.writeTo(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

(4) 簡單操作

  • UserInfoDataStore.java
public class UserInfoDataStore {
    // 定義DataStore的文件名稱
    private final String FILE_NAME = "user_info.pb";
    private RxDataStore<UserInfo> dataStore;

    public UserInfoDataStore(Context context) {
        if (dataStore == null) {
            dataStore = new RxDataStoreBuilder<UserInfo>(
                context,
                /*name=*/ FILE_NAME,
                new UserInfoSerializer()).build();
        }
    }

    /**
     * 寫入數據 - Name
     */
    public void setName(String value) {
        dataStore.updateDataAsync(currentUserInfo ->
            Single.just(
                currentUserInfo.toBuilder()
                    .setName(value)
                    .build()
            )
        );
    }

    /**
     * 寫入數據 - Age
     */
    public void setAge(int value) {
        dataStore.updateDataAsync(currentUserInfo ->
            Single.just(
                currentUserInfo.toBuilder()
                    .setAge(value)
                    .build()
            )
        );
    }

    /**
     * 讀取數據 - Name
     */
    public String getName() {
        return dataStore.data().map(UserInfo::getName).blockingFirst();
    }

    /**
     * 讀取數據 - age
     */
    public int getAge() {
        return dataStore.data().map(UserInfo::getAge).blockingFirst();
    }
}
  • MainActivity.java
// 獲取DataStore
UserInfoDataStore dataStore = new UserInfoDataStore(this);

//寫入數據
dataStore.setName("Chen");
dataStore.setAge(66);

// 讀取內容
String name = dataStore.getName();
int age = dataStore.getAge();
Log.e("Proto_DataStore_Demo", "讀取到的內容__age:" + age + ", name:" + name);
  • 運行結果

上一篇
Day28 - Jetpack DataStore (上) | Preferences DataStore
下一篇
Day30 - 在實體手機調適APP的方法ADB | 無線
系列文
Android 開發 30天 初學之路筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言