用Annotation简化Preference存储

现状

有很多Preference来自于某些对象的字段,这些字段的存储其实非常繁琐,每增加一个字段,需要修改3个地方:

  • key
  • 对象字段
  • 对象内容的存储

目标是搞成单点修改,但是:

  • 受限于java的Annotation限制很多,对于泛型、继承支持不太好,很难优雅的实现default value
  • 不太想做AnnotationProcessor(使用生成代码,可以把key映射成方法名,get的时候不需要key,此时可以做到依靠annotation,单点修改)

最后定成两点修改:

  • 定义enum作为key
  • 定义annotation进行自动化

代码

核心utils

public class PreferenceAnnotationUtils {

  public interface PersistProvider {
    String getKey();

    Object getDef();

    boolean isUser();
  }

  public static <T extends Annotation> void save(Object object,
      SharedPreferences preferences, Function<T, PersistProvider> func,
      Class<T> annotation) {
    Field[] fields = object.getClass().getFields();
    for (Field field : fields) {
      T annotationInstance = field.getAnnotation(annotation);
      if (annotationInstance == null) {
        continue;
      }
      PersistProvider provider = func.apply(annotationInstance);
      if (provider == null) {
        continue;
      }
      try {
        Object value = field.get(object);
        String prefKey =
            provider.isUser() ? KwaiApp.ME.getId() + provider.getKey() : provider.getKey();
        if (value == null) {
          continue;
        }
        if (value.getClass() == String.class) {
          preferences.edit().putString(prefKey, (String) value).apply();
        } else if (value.getClass() == int.class || value.getClass() == Integer.class) {
          if (provider.getDef().getClass() == boolean.class
              || provider.getDef().getClass() == Boolean.class) {
            preferences.edit().putBoolean(prefKey, (Integer) value == 1).apply();
          } else {
            preferences.edit().putInt(prefKey, (Integer) value).apply();
          }
        } else if (value.getClass() == boolean.class || value.getClass() == Boolean.class) {
          preferences.edit().putBoolean(prefKey, (Boolean) value).apply();
        } else if (value.getClass() == float.class || value.getClass() == Float.class) {
          preferences.edit().putFloat(prefKey, (Float) value).apply();
        } else if (value.getClass() == long.class || value.getClass() == Long.class) {
          preferences.edit().putLong(prefKey, (Long) value).apply();
        } else {
          preferences.edit().putString(prefKey, Gsons.KWAI_GSON.toJson(value)).apply();
        }
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      }
    }
  }
}

定义annotation

 public @interface MainPreferencePersist {
  MainPrefKey value();
 }
 public enum MainPrefKey implements PreferenceAnnotationUtils.PersistProvider {
 ...
 }

定义映射

public class Foo{
  @MainPreferencePersist(BAR)
  public boolean mBar;
...
}

使用

Foo foo = getFoo();
PreferenceAnnotationUtils.save(foo, getPref(),
        new Function<MainPreferencePersist, PreferenceAnnotationUtils.PersistProvider>() {
          @Nullable
          @Override
          public PreferenceAnnotationUtils.PersistProvider apply(
              @Nullable MainPreferencePersist input) {
            return input.value();
          }
        }, MainPreferencePersist.class);

其实思路就是ORM的保存,但是要做自动化。

其他库

经提醒,发现线上是有其他库做Preference 的ORM库的,而且有很大的:
- androidannotation:主要关注的是preference的强类型话,定义的是interface
- android-prefs:关注点是把Preference改成一个POJO
二者稍稍修改就能做到自动保存,不过为此引一个库并不划算。

后面又因为种种原因做起来代码生成,最后的

猜你喜欢

转载自blog.csdn.net/pouloghost/article/details/78133512