DoKV is a small but powerful key-value management framework designed to solve the tedious and ugly configuration class code on the Android platform

Introduce a,

Small because the implementation of DoKV relies on only one annotation, one interface, and four classes. Of course, its implementation basis is not only such, but also need the support of APT technology, need to rely on APT to automatically generate some intermediate code, about APT knowledge I have introduced in a previous blog, click to see: APT

Powerful because by using DoKV, you can basically throw away the following types of code

        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"."");
Copy the code

Typically, our applications have many configuration items that need to be cached, such as user information, Settings switch, server IP address, and so on. With native SharedPreferences, it’s easy to write ugly code like the one shown above, with multiple key values to maintain and a large layer of code that repeats every time data is saved and retrieved

So how did DoKV do?

Easy!!

Suppose your application contains a User class to cache User information. First, annotate the class with @dokv

/ * * * the author: leavesC * time: 2019/03/17 0:12 * description: * 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;

    privateList<String> stringList; ...}Copy the code

With a build, DoKV will automatically generate a Java class (UserDoKV) that ends with the class name +DoKV, and you can then access the data in the following manner, without worrying about how it is stored internally (although the internal caching mechanism can be customized by you).

        // Cache the entire object
        User user = new User();
        user.setAge(24);
        user.setName("leavesC");
        UserDoKV.get().setUser(user);

        // Get the cached object
        User user1 = UserDoKV.get().getUser();

        // Update a setting item for locally cached data
        // An object is automatically new and assigned if it has not been cached before
        // Because DoKV requires that the annotation class must contain a no-argument constructor and contain fields with corresponding Get and Set methods
        UserDoKV.get().setName("leavesCZY");
        UserDoKV.get().setAge(28);

        // Remove cached data
        UserDoKV.get().remove();
Copy the code

As mentioned above, DoKV relies on APT technology. The actual principle is that developers inherit AbstractProcessor to define the generation rule of object code, and the compiler generates object code according to this rule. Therefore, the execution efficiency of DoKV is just like constructing common Java classes. Is there any reflection that degrades performance

The UserDoKV class is defined as follows:

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

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

    private IDoKVHolder getDoKVHolder(a) {
        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(a) {
        return deserialize(KEY);
    }

    private User getUserNotNull(a) {
        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(a) {
        getDoKVHolder().remove(KEY);
    }

    @Override
    public String getName(a) {
        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);
    }

	// omit similar Get/Set methods
}
Copy the code

Second, the introduction of

In order to achieve more freedom, DoKV defaults to external implementation of data persistence. That is, the user decides how to serialize the object locally. In this case, you can choose to rely only on the following two references

dependencies {
    implementation 'leavesc. Hello: dokv: 0.1.6'
    annotationProcessor 'leavesc. Hello: dokv - compiler: 0.1.6'
}
Copy the code

The external then passes the IDoKVHolder instance to DoKV

	   DoKV.init(new IDoKVHolder() {

            / / the serialization
            @Override
            public String serialize(String key, Object src) {
                return null;
            }

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

            // Remove the specified object
            @Override
            public void remove(String key) {}});Copy the code

If you don’t want to implement IDoKVHolder yourself, DoKV also provides a default implementation. In this case, you can simply refer to the following dependency, which internally implements the serialization scheme via Gson + MMKV

dependencies {
    implementation 'leavesc. Hello: dokv - impl: 0.1.6'
}
Copy the code

Initialize, and then you’re free to play

DoKV.init(new MMKVDoKVHolder(Context));
Copy the code

Third, the end

The GitHub home page for this open source library is here: DoKV