为什么要用cache?
我们可以通过传递类似上次更新时间这样的参数来制定查询某些数据。同样,在下载图片的时候,server那边最好能够减少图片的大小,而不是让我们下载完整大小的图片。
之前我们在软件开发中,cache都是自己来写,不管是图片缓存还是其他从网络获取的数据,有了HttpResponseCache,它帮助我们可以很好的解决cache这个问题(我现在感觉他只适合cache一些小的数据,如果大量的图片cache还是自己缓存到SD卡上面去比较好)。
HttpResponseCache的好处:
- 明显一点节约电,减少了网络请求。
- 开发者不用自己在去写cache机制了。
- 最根本的一点就是,如果开发者在开发中不是使用的HttpClient, HttpDefaultClient..., 而是用 HttpURLConnection的话, 你根本不用改本來的 Code。
这个我们就不多说了,直接看示例:
在开发中你不用写其他任何东西,只要在Application层将其启动就好了 其他的全部交给HttpURLConnection处理就行。
public class HttpCacheApplication extends Application { @Override public void onCreate() { super.onCreate(); new Thread() { @Override public void run() { enableHttpResponseCache(); } }.start(); } private void enableHttpResponseCache() { try { long httpCacheSize = 10 * 1024 * 1024;// 10M File httpCacheDir = new File(getCacheDir(), "http"); Class.forName("android.net.http.HttpResponseCache") .getMethod("install", File.class, long.class) .invoke(null, httpCacheDir, httpCacheSize); } catch (Exception e) { Log.e("===>", e.getMessage(), e); } } }
接下来我们来看看HttpUrlConnection是怎么处理的,怎么缓存的。
public class MainActivity extends Activity { private final String TAG = getClass().getSimpleName(); ImageView img; Button msg; TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); img = (ImageView) findViewById(R.id.imageView1); tv = (TextView)findViewById(R.id.textView1); msg = (Button) findViewById(R.id.button1); msg.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new InternetTask().execute(); } }); findViewById(R.id.button2).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { MainActivity.this.finish(); } }); } class InternetTask extends AsyncTask<String, String, Boolean> { Bitmap bitmap; String jsonStr; @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); img.setImageBitmap(bitmap); tv.setText(jsonStr); } @Override protected Boolean doInBackground(String... params) { // Test download image try { URL url = new URL("http://news.baidu.com/resource/img/logo_news_137_46.png"); HttpURLConnection conn = (HttpURLConnection) (url .openConnection()); conn.connect(); InputStream is = conn.getInputStream(); BitmapFactory.Options ops = new BitmapFactory.Options(); bitmap = BitmapFactory.decodeStream(is, null, ops); is.close(); conn.disconnect(); } catch (Exception e) { Log.e(TAG, e.getMessage(), e); } // Test download JSON data try { URL url = new URL("http://www.baidu.com/"); HttpURLConnection conn = (HttpURLConnection) (url .openConnection()); conn.connect(); BufferedReader reader = new BufferedReader( new InputStreamReader(conn.getInputStream(), "UTF-8")); jsonStr = reader.readLine(); InputStream is = conn.getInputStream(); is.close(); conn.disconnect(); } catch (Exception e) { Log.e(TAG, e.getMessage(), e); } return true; } } }
我们看下效果:
看下缓存文件,每个文件会产生两个文件,一个是数据文件,一个是http header 信息
Cache Files Locally [缓存文件到本地]
- 避免下载重复的数据是很重要的。可以使用缓存机制来处理这个问题。缓存static的资源,例如完整的图片。这些缓存的资源需要分开存放。
- 为了保证app不会因为缓存而导致显示的是旧数据,请从缓存中获取最新的数据,当数据过期的时候,会提示进行刷新。
long currentTime = System.currentTimeMillis()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); long expires = conn.getHeaderFieldDate("Expires", currentTime); long lastModified = conn.getHeaderFieldDate("Last-Modified", currentTime); setDataExpirationDate(expires); if (lastModified < lastUpdateTime) { // Skip update } else { // Parse update }
使用这种方法,可以有效保证缓存里面一直是最新的数据。可以使用下面的方法来获取外部缓存的目录:
Context.getExternalCacheDir();
下面是获取内部缓存的方法,请注意,存放在内存中的数据有可能因内部空间不够而被清除。
Context.getCache();
不管是存放在哪里的文件都会在app卸载的时候被清除。