Android本地数据存储: ASimpleCache

一:前言


在上一篇博客Android本地数据存储: Reservoir 博客中,我提到,除了Reservoir库,还可以采用ASimpleCache开源库,来实现本地数据存储。昨天并没有仔细的对比Reservoir和ASimpleCache有啥不同,而是直接选取了Reservoir来进行学习使用,今天休息,真好看下ASimpleCache是如何使用的,有啥特别之处。

come on with me,let's study together。


二:认知ASimpleCache


ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。


2.1 它可以缓存什么东西?

普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 byte数据。


2.2 它有什么特色?

1:轻,轻到只有一个JAVA文件。
2:可配置,可以配置缓存路径,缓存大小,缓存数量等。
3:可以设置缓存超时时间,缓存超时自动失效,并被删除。
4:支持多进程。


2.3 它在android中可以用在哪些场景?

1、替换SharePreference当做配置文件
2、可以缓存网络请求数据,比如oschina的android客户端可以缓存http请求的新闻内容,缓存时间假设为1个小时,超时后自动失效,让客户端重新请求新的数据,减少客户端流量,同时减少服务器并发量。


三:使用ASimpleCache


由上述介绍,我们可以得知,其实ASimpleCache就只有一个类文件,所以在使用时,我们仅需要把这个文件拷贝到我们的项目中,作为工具类即可。

那,接下来,看下如何使用ASimpleCache去存取数据吧。

3.1 初始化ASimpleCache

ASimpleCache在使用前也必须进行初始化操作。

ACache mCache = ACache.get(this);

3.2 通过put、get方法,存取Object数据

首先,我们看下ACache提供了哪些put方法,可以用来存储什么样的数据:



可以看出来,通过put方法,可以存储普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 byte数据,这和之前我们介绍的一样。 再仔细看下这些方法,其中有些方法,提供了一个int saveTime参数,该参数主要表明该缓存可以保存的时间。


首先,我们保存序列化对象的方法代码:

先定义一个序列化的Person类:

public class Person implements Serializable{
    public String name;

    public int age;

    public Date birthday;

    public boolean sex;

    public Person(String name, int age, Date birthday, boolean sex) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                ", sex=" + sex +
                '}';
    }
}


然后,我们看下put object方法:

private static final String PERSON = "ONE_PERSON";

private void saveData() {
        Person person = new Person("无缘", 25, new Date(), true);
        mCache.put(PERSON,person);
}
So just like this,我们已经把person对象保存到了本地磁盘文件中,现在我们找到文件,并打开它看下:

sr com.lnyp.asimplecache.Person袾说r? I ageZ sexL birthdayt Ljava/util/Date;L namet Ljava/lang/String;xp   sr java.util.Datehj?KYt  xpw  OX臈'xt 鏃犵紭


沃日,这是个啥?

别惊慌,其实这就是序列化的Person对象啦。

我们读取它看下,在此之前,先看下ACache提供了哪些get方法吧


从方法名和返回值就可以看出来,ACache提供了一系列的方法,可以直接读取InputStream,byte,Bitmap,Object等等。。。

我们先使用getAsObject去获取我们存储的序列化的对象:

    private void readData() {
        Person person = (Person) mCache.getAsObject(PERSON);
        System.out.println(person);
    }
看下返回结果: 

System.out﹕ Person{name='无缘', age=25, birthday=Sun Aug 23 04:15:22 GMT 2015, sex=true}


来,这个时候我们做个试验,关于saveTime的,看看这个过期时间到底有木有用:

    private void saveData() {
        Person person = new Person("无缘", 25, new Date(), true);
        mCache.put(PERSON,person, 10);//保存10秒,如果超过10秒去获取这个key,将为null
    }

静候十秒,再去读取Person对象,看下输出

I/System.out﹕ null


果然有效啊,是不是很惊喜啊,没错,使用这个方法之后,我们可以很方便的处理一些需求,比如本地的token过期需要重新登录(我最近刚刚做了这么一个功能需求)。。。。


3.3 通过put、get方法,存取List集合数据

仔细看3.2中提到的put和get方法,可以发现并没有提供存取List集合的方法,这其实有些给人的感觉不是那么爽,起码我有点不自在了,要知道Reservoir可是提供了的哦。

不过别急,我们可以变向的去完成List集合的存取,咋办呢?用jsonArray啊!

说白了,就是把List转换为jsonArray,然后put保存,读取的时候,再把jsonArray转换为List就好了。这里,我们需要借助gson。

先提供一个GsonUtil工具类:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.lang.reflect.Type;
import java.util.List;

/**
 * Gson工具类
 * 
 * @author lining
 */
public class GsonUtil
{
    /**
     * 时间格式
     */
    public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 创建GSON
     * 
     * @return
     */
    public static Gson getGson()
    {
        return new GsonBuilder().serializeNulls().setDateFormat(DATE_FORMAT).create();
    }

    /**
     * 将对象转化为字符串
     * 
     * @param obj
     * @return
     */
    public String Object2Json2(Object obj)
    {
        return getGson().toJson(obj);
    }

    /**
     * 将对象转化为字符串(泛型实现)
     * 
     * @param obj
     * @return
     */
    public static <T> String t2Json2(T t)
    {
        return getGson().toJson(t);
    }

    /**
     * 将字符转化为对象
     * 
     * @param <T>
     * @param jsonString
     * @param clazz
     * @return
     */
    public static <T> T json2T(String jsonString, Class<T> clazz)
    {
        return getGson().fromJson(jsonString, clazz);
    }

    /**
     * 将字符串数组转化为对象集合
     * 
     * @param <T>
     * @param jsonStr
     * @param type
     * @return
     */
    public static <T> List<T> json2Collection(String jsonStr, Type type)
    {
        return getGson().fromJson(jsonStr, type);
    }

}
有了这个工具类,我们试着把List存储起来:

    private void saveDatas() {
        Person person1 = new Person("无缘1", 25, new Date(), true);
        Person person2 = new Person("无缘2", 22, new Date(), false);
        Person person3 = new Person("无缘3", 21, new Date(), true);

        List<Person> persons = new ArrayList<Person>();
        persons.add(person1);
        persons.add(person2);
        persons.add(person3);

        String personArray = GsonUtil.getGson().toJson(persons);
        System.out.println(personArray);

        mCache.put(PERSONS, personArray);
    }
在磁盘中找到该文件,打开看下:

[{"name":"无缘1","birthday":"2015-08-23 04:55:41","age":25,"sex":true},{"name":"无缘2","birthday":"2015-08-23 04:55:41","age":22,"sex":false},{"name":"无缘3","birthday":"2015-08-23 04:55:41","age":21,"sex":true}]

这就是我们保存的东东了,接下来,我们读取该jsonarray,并把它转换为Lsit:

    private void readDatas() {
        JSONArray result = mCache.getAsJSONArray(PERSONS);

        Type mType = new TypeToken<List<Person>>(){}.getType();

        List<Person> persons = GsonUtil.getGson().fromJson(result.toString(), mType);
        for (Person person:persons){
            System.out.println(person);
        }
    }

来,看下输出的内容:

System.out﹕ Person{name='无缘1', age=25, birthday=Sun Aug 23 04:55:41 GMT 2015, sex=true}
System.out﹕ Person{name='无缘2', age=22, birthday=Sun Aug 23 04:55:41 GMT 2015, sex=false}
System.out﹕ Person{name='无缘3', age=21, birthday=Sun Aug 23 04:55:41 GMT 2015, sex=true}

怎么样,是不是实现了哦。

当然,除了这个思路,你还可以自己去修改ACache源代码,添加putList和getAsList方法哦,这个请大家自己去研究了。。。


3.4 删除和清空缓存数据

和Reservoir一样,既然可以存取数据,当然也可以删除和清空缓存数据了。ACache也提供了remove和clear两个方法,分别用来删除指定key的缓存和清空所有缓存。

    private void deleteData() {
        mCache.remove(PERSON);
    }

    private void clearData() {
        mCache.clear();
    }

四:强大的ASimpleCache

为啥ASimpleCache是强大的呢,因为除了存储基本的数据外,它还提供了直接存取InputSream、Bitmap、Drawable的功能。这可是了不得的,也是Reservoir没有提供的哦。

当然,存取Bitmap等特殊数据的方法和存取Object是一样一样的,此处不便多说,可以看下官方提供的例子:

public class SaveBitmapActivity extends Activity {

	private ImageView mIv_bitmap_res;

	private ACache mCache;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_save_bitmap);
		// 初始化控件
		initView();

		mCache = ACache.get(this);
	}

	/**
	 * 初始化控件
	 */
	private void initView() {
		mIv_bitmap_res = (ImageView) findViewById(R.id.iv_bitmap_res);
	}

	/**
	 * 点击save事件
	 * 
	 * @param v
	 */
	public void save(View v) {
		Resources res = getResources();
		Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.img_test);
		mCache.put("testBitmap", bitmap);
	}

	/**
	 * 点击read事件
	 * 
	 * @param v
	 */
	public void read(View v) {
		Bitmap testBitmap = mCache.getAsBitmap("testBitmap");
		if (testBitmap == null) {
			Toast.makeText(this, "Bitmap cache is null ...", Toast.LENGTH_SHORT)
					.show();
			mIv_bitmap_res.setImageBitmap(null);
			return;
		}
		mIv_bitmap_res.setImageBitmap(testBitmap);
	}

	/**
	 * 点击clear事件
	 * 
	 * @param v
	 */
	public void clear(View v) {
		mCache.remove("testBitmap");
	}
}

是吧,so easy,有了ASimpleCache,再也不用担心Bitmap无处存放啦。当然了,一般情况下,缓存Bitmap等数据,我们会利用更强大的开源库,如Android-Universal-Image-Loader、Xutils等,此处只是给你提供了另一种选择方案。


ASimpleCache gitub地址:https://github.com/yangfuhai/ASimpleCache 

上述示例源码下载地址(免费): http://download.csdn.net/detail/zuiwuyuan/9037833

posted on 2015-08-23 13:23  如果蜗牛有爱情  阅读(319)  评论(0编辑  收藏  举报

导航