一個小巧而強大的 Key-Value 管理框架

leavesC發表於2019-03-16

DoKV

DoKV 是一個小巧而強大的 Key-Value 管理框架,其設計初衷是為了解決 Android 平臺下各種繁瑣且醜陋的配置類程式碼

一、介紹

之所以說小巧,是因為 DoKV 的實現僅依賴於一個註解、一個介面、四個類。當然,其實現基礎不僅僅如此,還需要 APT 技術的支援,需要依賴於 APT 來自動生成某些中間程式碼,關於 APT 的知識我在以前的一篇部落格中也有所介紹,點選檢視:APT

一個小巧而強大的 Key-Value 管理框架

之所以說強大,是因為通過使用 DoKV 後,你基本是可以拋棄如下型別的程式碼了

        SharedPreferences sharedPreferences = getSharedPreferences("SharedPreferencesName", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString("IP", "192.168.0.1");
        editor.commit();
        String userName = sharedPreferences.getString("userName", "");
        String ip = sharedPreferences.getString("IP", "");
複製程式碼

通常,我們的應用都會有很多配置項需要進行快取,比如使用者資訊、設定項開關、伺服器IP地址等。如果採用原生的 SharedPreferences 來實現的話,則很容易就寫出如上所示那樣醜陋的程式碼,不僅需要維護多個資料項的 key 值,而且每次存入和取出資料時都會有一大片重複的程式碼,不易維護

那 DoKV 的表現如何呢?

很簡單!!!

假設你的應用包含了一個 User 類用於快取使用者資訊,首先,為該類加上一個註解:@DoKV

/**
 * 作者:leavesC
 * 時間:2019/03/17 0:12
 * 描述:
 * GitHub:https://github.com/leavesC
 * Blog:https://www.jianshu.com/u/9df45b87cfdf
 */
@DoKV
public class User {

    private String name;

    private int age;

    private String sex;

    private Book book;

    private List<String> stringList;

	···

}
複製程式碼

build 下工程,DoKV 就會自動為你生成一個以 類名+DoKV結尾 的 Java 類(UserDoKV),之後你就可以通過以下這種形式來進行資料存取了,而你無需關心其內部是如何儲存的(當然,其內部的快取機制是可以由你來自定義的)

        //快取整個物件
        User user = new User();
        user.setAge(24);
        user.setName("leavesC");
        UserDoKV.get().setUser(user);

        //獲取快取的物件
        User user1 = UserDoKV.get().getUser();

        //更新本地已快取的資料的某個設定項
        //如果之前沒有快取過,則會自動 new 一個物件並自動賦值
        //因為 DoKV 要求註解類必須包含一個無參建構函式,並且包含的欄位有對應的 Get 和 Set 方法
        UserDoKV.get().setName("leavesCZY");
        UserDoKV.get().setAge(28);

        //移除快取資料
        UserDoKV.get().remove();
複製程式碼

上文說過,DoKV 是依賴於 APT 技術的,其實際原理就是開發者通過繼承 AbstractProcessor 來定義目的碼的生成規則,由編譯器根據此規則來生成目的碼,所以 DoKv 的執行效率就如同構造一般的 Java 類,不存在什麼依靠反射使效能降低的情況

UserDoKV 類的定義如下所示:

public class UserDoKV extends User {
    
    private static final String KEY = "leavesc.hello.dokv.model.UserDoKV";

    private UserDoKV() {
    }

    public static UserDoKV get() {
        return new UserDoKV();
    }

    private IDoKVHolder getDoKVHolder() {
        return DoKV.getInstance().getDoKVHolder();
    }

    private String serialize(String _KEY, User _User) {
        return getDoKVHolder().serialize(_KEY, _User);
    }

    private User deserialize(String _KEY) {
        return getDoKVHolder().deserialize(_KEY, User.class);
    }

    public User getUser() {
        return deserialize(KEY);
    }

    private User getUserNotNull() {
        User variable = deserialize(KEY);
        if (variable != null) {
            return variable;
        }
        return new User();
    }

    public String setUser(User instance) {
        if (instance == null) {
            remove();
            return "";
        }
        return serialize(KEY, instance);
    }

    public void remove() {
        getDoKVHolder().remove(KEY);
    }

    @Override
    public String getName() {
        User variable = getUser();
        if (variable != null) {
            return variable.getName();
        }
        return super.getName();
    }

    @Override
    public void setName(String _name) {
        User _user = getUserNotNull();
        _user.setName(_name);
        serialize(KEY, _user);
    }

	//省略類似的 Get/Set 方法
}
複製程式碼

二、引入

為了獲得更高的自由度, DoKV 預設將資料持久化的實現方案交由外部來實現,即由使用者來決定如何將物件序列化儲存到本地,此時你就可以選擇只依賴以下兩個引用

dependencies {
    implementation 'leavesc.hello:dokv:0.1.6'
    annotationProcessor 'leavesc.hello:dokv-compiler:0.1.6'
}
複製程式碼

然後,外部將 IDoKVHolder 例項傳給 DoKV 即可

	   DoKV.init(new IDoKVHolder() {

            //序列化
            @Override
            public String serialize(String key, Object src) {
                return null;
            }

            //反序列化
            @Override
            public <T> T deserialize(String key, Class<T> classOfT) {
                return null;
            }

            //移除指定物件
            @Override
            public void remove(String key) {

            }
        });
複製程式碼

如果你不想自己實現 IDoKVHolder ,DoKV 也提供了一個預設實現,此時你就只要多引用如下一個依賴即可,其內部是通過 Gson + MMKV 來實現序列化方案

dependencies {
    implementation 'leavesc.hello:dokv-impl:0.1.6'
}
複製程式碼

進行初始化,之後就可以自由地玩耍了

DoKV.init(new MMKVDoKVHolder(Context));
複製程式碼

三、結尾

本開源庫的 GitHub 主頁在這裡:DoKV

APK 下載體檢:DoKV

我的部落格主頁:leavesC

相關文章