文件缓存

在网络通畅的情况下,获取网络数据显示是非常容易的。但是当网络不通畅的时候,或者说是完全没有网络时该怎么办呢?不可能直接给用户一个白板界面吧。

通常的处理方式是将某些界面的数据写入缓存,获取数据时首先查看缓存文件里面是已经有这些数据,有则直接用,没有的话在去连接网络获取数据并写入缓存,比方说新闻类APP一般情况下都是将第一页的数据写入缓存。

缓存的位置的话就是看情况而定了,一般情况都是写入文件缓存。就是data-》data->下的对应应用程序的文件中。这个文件会随程序的卸载而释放控件。

下面就是实际Demo:

首先是缓存类:里面就是将数据读入文件和写入文件操作:缓存文件名采用了给定的url地址中的一些字符来作为标识。

package com.scxh.android1503.http.cache;


import com.scxh.android1503.util.Logs;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class ConfigCache {
    public static String mSdcardDataDir = "";

    public static String getUrlCache(String url) {
        if (url == null) {
            return null;
        }
        Logs.e("读缓存数据");
        String result = null;
        File file = new File(mSdcardDataDir + "/" + getCacheDecodeString(url));
        if (file.exists() && file.isFile()) {
            result = readTextFile(file);
        }
        return result;
    }

    public static void setUrlCache(String data, String url) {
        File file = new File(mSdcardDataDir + "/" + getCacheDecodeString(url));
        //创建缓存数据到磁盘,就是创建文件
        Logs.e("写缓存数据");
        writeTextFile(file, data);

    }

    public static String getCacheDecodeString(String url) {
        //1. 处理特殊字符
        //2. 去除后缀名带来的文件浏览器的视图凌乱(特别是图片更需要如此类似处理,否则有的手机打开图库,全是我们的缓存图片)
        if (url != null) {
            return url.replaceAll("[.:/,%?&=]", "+").replaceAll("[+]+", "+");
        }
        return null;
    }

    public static void writeTextFile(File file, String data) {
        FileOutputStream os = null;
        try {
            os = new FileOutputStream(file);
            os.write(data.getBytes("UTF-8"));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static String readTextFile(File file) {
        FileInputStream instream = null;
        StringBuilder sb = null;
        try {
            instream = new FileInputStream(file);
            InputStreamReader inputreader = new InputStreamReader(instream);
            BufferedReader buffreader = new BufferedReader(inputreader);
            String line;
            sb = new StringBuilder();
            //分行读取
            while ((line = buffreader.readLine()) != null) {
                sb.append(line);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (instream != null) {
                try {
                    instream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

}

之后还有一个测试Activity:给了一个Http地址,返回的是JSON字符串。写入缓存的也是这些JSON字符数据。xml布局是一个按钮和一个显示JSON数据的TextView控件。这里就没有贴出了。


package com.scxh.android1503.http.cache;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.TextHttpResponseHandler;
import com.scxh.android1503.R;
import com.scxh.android1503.util.Logs;

import cz.msebera.android.httpclient.Header;


public class HttpCacheActivity extends Activity {
    private String CONFIG_URL = "http://c.m.163.com/nc/article/headline/T1348647909107/0-20.html";
    private TextView mCacheTxt;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_http_cache_layout);
        mCacheTxt = (TextView) findViewById(R.id.cache_textview);

        ConfigCache.mSdcardDataDir = getFilesDir().getAbsolutePath();
    }

    public void onCacheClickLisenter(View v){
        getConfig();
    }

    void getConfig() {
        //首先尝试读取缓存
        String cacheConfigString = ConfigCache.getUrlCache(CONFIG_URL);
        //根据结果判定是读取缓存,还是重新读取
        if (cacheConfigString != null) {
<span style="white-space:pre">	</span>    toast.makeText(this,"文件取数据",Toast.LENGTH_SHORT).show();
            showConfig(cacheConfigString);
        } else {
            //如果缓存结果是空,说明需要重新加载
            //缓存为空的原因可能是1.无缓存;2. 缓存过期;3.读取缓存出错
            AsyncHttpClient client = new AsyncHttpClient();

            client.get(CONFIG_URL, new TextHttpResponseHandler() {

                @Override
                public void onFailure(int i, Header[] headers, String s, Throwable throwable) {
                    //根据失败原因,考虑是显示加载失败,还是再读取缓存
                    Toast.makeText(HttpCacheActivity.this, "连接网络出错", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onSuccess(int i, Header[] headers, String s) {
                    //成功下载,则保存到本地作为后面缓存文件
                    ConfigCache.setUrlCache(s, CONFIG_URL);
                    //后面可以是UI更新,仅供参考
                    showConfig(s);
<pre name="code" class="java">                    toast.makeText(this,"文件取数据",Toast.LENGTH_SHORT).show();
} }); } } public void showConfig(String msg){ Logs.e(msg); mCacheTxt.setText(msg); }}

 
 
最后就呈现了这样的结果。第一次从网络获取数据之后。第二次就直接从文件中读取数据。当没有网络的情况下也是从文件中读取数据。

当然也不是什么数据都要缓存起来,缓存某一些数据即可达到运行流畅和提示网络连接的作用即可。




你可能感兴趣的:(文件缓存)