首页 > 技术文章 > Android通过反射打造可以存储任何对象的万能SharedPreferences

feng-de-wei-xiao 2015-07-21 10:59 原文

我们通常使用SharedPreferences存储一些需要保存在本地,但又不至于存储在数据库里的一些数据,一般我们用它来存储一些用户名,密码等数据是非常方便的,那么如果我们想要存储的信息有10几条,我们就得写10几行重复的代码把他们存进去,取出来的时候还得写10几行代码将他们一条一条取出来,那么有没有什么办法可以只需要一行代码就可以将他们存进去,一行代码就将他们取出来?答案是有的,这篇文章我们就介绍如何通过反射来实现。

1.将我们想要保存的数据封装成一个实体类 Person.java 其中属性我们都用Public来修饰

public class Person {
    //String类型属性 姓名
    public String name;
    //int类型属性 年龄
    public int age;
    //float类型属性 身高
    public float height;
    //boolean类型属性 是否已婚
    public boolean isMarried;
    //String类型属性 证件号
    public String id;
}

2.通过反射,将Person类中的属性取出来

public class SharedPreferencesUtils {
    /**
     * 根据传入的对象,取出其中用public修饰符修饰的属性
     * @param clazz 想要拿到属性的类的字节码文件
     * @return 所有用pulic修饰的属性的一个list表
     */
    public static <T> List<Field> getPublicFields(Class<?> clazz){
        if (clazz.equals(Object.class)) {
            return null;
        }
        //用来存储clazz中用public修饰的属性的list
        List<Field> list = new ArrayList<Field>();
        //获得clazz中所有用public修饰的属性
        Field[] fields = clazz.getFields();
        //将fields加入到list中
        for(int i=0 ; i<fields.length ; i++){
            list.add(fields[i]);
        }
        return list;
    }

我们先来测试一下属性有没有被取出来,我们在MainActivity.java中添加如下代码进行测试

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //调用我们刚刚写好的方法来获取Person类中的属性
        List<Field> publicFields = SharedPreferencesUtils.getPublicFields(Person.class);
        for(Field f : publicFields){
            String name = f.getName();
            Log.i("TAG", name+"\n");
        }
    }
}
我们来看一下Log打印的信息
我们可以看到,Person中的属性我们都已经拿到了
 
3.将对象存储到SharedPreferences中
public static void putObjectToShare(String shareName , Object obj){
        //获得SharedPreferences实例
        SharedPreferences sharedPreferences = mContext.getSharedPreferences(shareName,Activity.MODE_PRIVATE);
        //获得Editor
        Editor edit = sharedPreferences.edit();
        //存储数据之前先将之前的旧数据清掉
        edit.clear();
        //调用commit提交数据(这里为了清掉数据)
        edit.commit();
        
        List<Field> publicFields = getPublicFields(obj.getClass());
        for(Field f : publicFields){
            String name = f.getName();
            try {
                //获得当前属性的类型和值
                //类型的话如果是基本类型,会自动装箱
                Object type = f.get(obj);
                //判断各种类型,调用各种类型的put方法将数据存储进去
                if (type instanceof String) {
                    edit.putString(name, (String) type);
                }else if (type instanceof Integer) {
                    edit.putInt(name, (Integer) type);
                }else if (type instanceof Float) {
                    edit.putFloat(name, (Float) type);
                }else if (type instanceof Long) {
                    edit.putLong(name, (Long) type);
                }else if (type instanceof Boolean) {
                    edit.putBoolean(name, (Boolean) type);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //调用commit,提交数据
            edit.commit();
        }
    }

5.我们来测试一下,修改MainAcitvity.java中的代码

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //实例化一个Person实例,这是我们想要存储到SharedPreferences中的对象
        Person p = new Person("zhangsan",23,175.0f,false,"001");
        //将p存储到SharedPreferences的“zhangqi”名下
        SharedPreferencesUtils.getInstance(this).putObjectToShare("zhangqi",p);;
        //从SharedPreferences的“zhangqi”名下取出之前存储过的Person实例
        Person savedPerson = SharedPreferencesUtils.getInstance(this).getObjectFromShare("zhangqi",Person.class);
        Log.e("zhangqi",""+savedPerson.toString());
    }
}
我们看一下Log中打印的savedPerson的信息

推荐阅读