SharedPreferences 的另一种场景的用法

SharedPreferences 的另一种场景的用法

昨天,下班在家想做什么来着,然后想用SharedPreferences存点数据,但是不知道咋地突然想到,SharedPreferences是应用启动时一次性加到内存里的.适合少量的存储,多的话还是用数据库吧.实际项目中都是数据库,我私下写写demo就不搞那么麻烦了=.=

然后,问题来了,如果我要使用SharedPreferences,如何在比较小的单位里存储更多的信息.

好了,正题.

1. 昨天谷歌提供了国内的 android developer官网!!!

{=.=} 激动!!!

你的书签地址还是 https://developer.android.com/index.html ???{大雾}

国内速度更快!!!地址:https://developer.android.google.cn/index.html{快快加书签!!!}

2. 最近同事推荐了款 Markdown 编辑器,感觉比我之前用的 MarkdownPad2好用

分享下,名字: Haroopad

顺便丢个自己的GitHub仓库,收集了一些开发必须的工具,需要的可以去看看,顺便 watch fuck star...

开发日常应该必备吧(今天发现的hosts不错,YouTube也可以看,已经提供了七牛云下载) https://github.com/didikee/Dev_Tools

3. 我擦,真 正题...

思路:

想起之前看源码的时候谷歌用二进制存储boolean值,然后我想了想,貌似可以用String存一些值.

例如:"10101101": 可以解读为:true false true false true true false true

但是,"1"也是一个字符,它不限于"1",也可以是2或3甚至*或者%等等字符就可以.

1. 定义 Value:

Value:是一些char类型的值,代表一些含义.我简单的定义了四种:

public abstract class SPValue {
    public static final char TRUE=‘1‘;//true
    public static final char FALSE=‘0‘;//false
    public static final char DEFAULT=‘-‘;//默认的时候会是‘-‘
    public static final char ERROR=‘=‘;//发生错误的时候可能会用‘=‘
}

2. 定义 Key:

Key:是由 0 ~ Integer.MaxValue() ,其实就是String的脚标index.

public abstract class SPKey {
    //抽象类,给子类继承
}

3. 提供 get 和 put 功能

定义功能接口:

public interface ISPDao {
    char getValue(int key);
    void putValue(int key,char value);
}

最后是实现类:

public final class SPDao implements ISPDao {

    private final Context context;
    public static final String SPDAO = "spDao";
    public static final String SPKEY = "spKey";

    public SPDao(Context context) {
        this.context = context;
    }

    @Override
    public char getValue(int key) {
        SharedPreferences sp = context.getSharedPreferences(SPDAO,
                Context.MODE_PRIVATE);
        String allValues = sp.getString(SPKEY, "");
        Log.e("test","get: "+allValues);
        String defaultStr = String.valueOf(SPValue.DEFAULT);
        int maxIndex = allValues.length() - 1;
        if (key > maxIndex) {
            SharedPreferences.Editor editor = sp.edit();
            String tempAdd = "";
            for (int i = maxIndex + 1; i <= key; i++) {
                tempAdd += defaultStr;
            }
            editor.putString(SPKEY, allValues + tempAdd);
            editor.apply();
            return SPValue.DEFAULT;
        } else {
            return allValues.charAt(key);
        }
    }

    @Override
    public void putValue(int key, char value) {
        SharedPreferences sp = context.getSharedPreferences(SPDAO,
                Context.MODE_PRIVATE);
        String allValues = sp.getString(SPKEY, "");
        Log.e("test","put start: "+allValues);
        String defaultStr = String.valueOf(SPValue.DEFAULT);
        SharedPreferences.Editor editor = sp.edit();
        int maxIndex = allValues.length() - 1;
        if (key > maxIndex) {
            String tempAdd = "";
            for (int i = maxIndex + 1; i <= key; i++) {
                tempAdd += defaultStr;
            }
            Log.e("test","put end1: "+allValues+ tempAdd);
            editor.putString(SPKEY, allValues+tempAdd);
        } else {
            char oldChar = allValues.charAt(key);
            Log.e("test","oldCar: "+oldChar);
            StringBuilder sb=new StringBuilder(allValues);
            sb.setCharAt(key,value);
            Log.e("test","put end2: "+ sb.toString());
            editor.putString(SPKEY, sb.toString());
        }
        editor.apply();
    }

}

说明:中间的if作用是,如果你要获取脚标 4 的char值,但是目前String长度只有 3 ,那么我就填充String 到index 4,填充的值"DEFAULT"
值.同理,我在put的时候也会做这样的处理.
最后就是Key的值其实是0开始,建议是连续的,因为不是连续的话,那么必然会有一些index的占位是无意义的,至于我最开始的思路是相违背的.

4.最后提供一个检测 key 是否重复定义的工具类
思路: 用反射得到所有的定义的key,然后比较是否重复,重复的话意味着同一个脚标index同时代表了两种含义,这是不被允许的.
代码:

public class SPDaoChecker {

    private static final String CHANGE="$change";
    private static final String SERIAL_VERSION_UID="serialVersionUID";

    /**
     * check your SPKeys
     * @param clz class extend SPKey
     * @return
     */
    public static boolean check(Class clz){
        ArrayList<Integer> charList=new ArrayList();
        Field[] fields = clz.getFields();
        for (Field field : fields) {
            String name = field.getName();
            if (SERIAL_VERSION_UID.equalsIgnoreCase(name)
                    || CHANGE.equalsIgnoreCase(name)){
                continue;
            }
            boolean accessible = field.isAccessible();
            if (!accessible)field.setAccessible(true);
            int value= -1;
            try {
                value = field.getInt(clz.newInstance());
            } catch (Exception e){
                Log.d("test","e: "+e.getClass().getSimpleName()+"msg: "+e.getMessage());
                return false;
            }
            if (charList.contains(value)){
                return false;
            }else {
                charList.add(value);
            }
            Log.d("test","name: "+name+"value: "+value);

        }
        return true;
    }
}

好了,差不多说完了,有什么不对的地方轻拍,你也不会打我的对不对?嘿嘿

时间: 2024-08-05 13:04:23

SharedPreferences 的另一种场景的用法的相关文章

(转)extern关键字两种场景的使用

第一种场景 -- extern extern关键字的作用是声明变量和函数为外部链接,即该变量或函数名在其它文件中可见.用其声明的变量或函数应该在别的文件或同一文件的其它地方定义. 例如语句:extern int a;仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间.变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误.通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明.例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需

一直被用错的6种SQL 错误用法

一直被用错的6种SQL 错误用法 1.LIMIT 语句 2.隐式转换 3.关联更新.删除 4.EXISTS语句 5.条件下推 6.提前缩小范围 sql语句的执行顺序: FROM ON JOIN WHERE GROUP BY HAVING SELECTDISTINCT ORDER BY LIMIT 1.LIMIT 语句 分页查询是最常用的场景之一,但也通常也是最容易出问题的地方.比如对于下面简单的语句,一般 DBA 想到的办法是在 type, name, create_time 字段上加组合索引.

STM32 一种参数检查用法介绍

STM32 一种参数检查用法介绍 assert_param()是一个在代码中很常见的写法,这个函数的功能一般是对函数参数的合法性进行检查,这里以一个例子进行分析: assert_param(IS_GPIO_ALL_PERIPH(GPIOx)) 函数的参数是IS_GPIO_ALL_PERIPH(GPIOx),原型为: #define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || ((PERIPH) == GPIOB) || ((PERIPH)

最适合使用RxJava处理的四种场景

下面我们开始介绍RxJava最适合使用的四种场景,代码示例基于RxJava1 场景一: 单请求异步处理 由于在Android UI线程中不能做一些耗时操作,比如网络请求,大文件保存等,所以在开发中经常会碰到异步处理的情况,我们最典型的使用场景是RxJava+Retrofit处理网络请求 MyService myService = retrofit.create(MyService.class);myService.getSomething() .subscribeOn(Schedulers.io

慎用缺省构造函数的一种场景

本文通过示例来谈谈慎用缺省构造函数的一种设计场景.--以JAVA为例展开讨论. 为了便于讨论,我们假定需要建模一个Student,包括姓名和出生地两个属性.我们看到不少下面的代码: public class Student { private String name = null; private String birthPlace = null; public Student() { } public void setName(String name) { this.name = name;

Eclipse中SVN的安装步骤(两种)和用法

一.给安装EclipseSVN,最常见的有两种方式:手动方式和使用安装向导方式.详细过程例如以下: 方式一:手动安装 1.从官网下载site-1.6.9.zip文件,网址是:subclipse.tigris.org2.从中解压出features与plugins目录,拷贝到E:/MyEclipse/myPlugin/svn里面,其他的*.xml文件不要.3.在E:/MyEclipse/MyEclipse X.X/dropins下新建文件svn.link,内容是:path=E://MyEclipse

Spring-- Ioc 容器Bean实例化的几种场景

Bean实例化的几种场景 1.BeanDefinitionRegistryPostProcessor实例化:标准BeanFactoryPostProcessor的扩展,BeanFactoryPostProcessor的作用是用来进一步定义注册的BeanDefinition,IoC容器本质就是Bean管理,所以BeanFactoryPostProcessor本身也是Bean,要对BeanFactoryPostProcessor的BeanDefinition进一步定义就通过BeanDefinitio

C++中三种new的用法

转载自:http://news.ccidnet.com/art/32855/20100713/2114025_1.html 作者: mt 1 new operator,也叫new表达式:new表达式比较常见,也最常用,例如: string* ps = new string("abc"); 上面这个new表达式完成了两件事情:申请内存和初始化对象. 2 operator new,也叫new操作符.这两个英文名称起的也太绝了,很容易搞混,那就记中文名称吧.new操作符类似于C语 言中的ma

do...while和while...do的两种场景比较

场景:脚本每5分钟执行一次,从数据库中每次查询1000数据进行处理,直到处理结束.两种用while和do...while两种方式实现的伪代码如下: 1. while...do $count = mysql.query('select count (*) from tb where status=1'); $round = ($count % 1000) == 0 ? ($count / 1000) +1: ($count / 1000) while($round > 0){ $dbRes = m