`

Android 利用缓存机制实现文件下载

 
阅读更多

http://www.cctime.com/html/2011-11-29/201111291037553094_2.htm

http://blog.csdn.net/life02/article/details/7588502

在下载文件或者在线浏览文件时,或者为了保证文件下载的正确性,需要使用缓存机制,常使用SoftReference来实现。

SoftReference的特点是它的一个实例保存对一个Java对象的软引用,该软引用的存在不妨碍垃圾收集线程对该Java对象的回收。也就是说,一旦SoftReference保存了对一个Java对象的软引用后,在垃圾线程对这个Java对象回收前,SoftReference类所提供的get方法返回Java对象的强引用。另外,一旦垃圾线程回收该Java对象之后,get方法将返回null。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

一般的缓存策略是:

一级内存缓存、二级文件缓存(数据库也算作文件缓存)、三级网络数据

一、网络下载的缓存策略

关于网络下载文件(图片、音频、视频)的基本策略:

1.不要直接下载到目标文件,应使用temp文件作中转,以确保文件的正确性与完整性,流程如下:

a)以网络目标文件名 A 生成唯一的本地目标文件名 B

b)以本地目标文件名 B 生成唯一的本地临时文件名 T

c)下载文件到 T 中

d)下载完毕,校验文件 T 的正确性与完整性

e)若不正确或不完整则 delete 文件 T,并返回 false

f)校验完毕后,将文件 T 重命名 或 复制到 B 文件

g)最后的清理现场,删除临时文件 T,成功后,返回 true

2.尽力提供文件正确性与完整性的校验:

a)正确性:比如 MD5/Hash Code 比对、文件格式的比对。

b)完整性:比如 文件大小是否一致、图片的数据是否正确(图片文件头中提供了相关信息)

3.考虑对于下载到本地的文件是否需要再做二次加工,可以思考以下情况:

a)比如网络源始图片的大小为800*600,而我们需要作为缩略图的大小为160*145,所以考虑对下载后的文件进行裁剪,再保存,对于源始文件则直接删除。

二、文件缓存策略:

1.需要唯一的缓存文件的对应I/O key,一般可以使用 hashcode。

2.若是同一个文件,以不同的时间,可以考虑,先清本地缓存,再下载新的缓存到本地。

3.同一文件也可以加上时间戳后,再生成唯一hashcode。

4.生成文件缓时,也许需要作以下全面的考虑:

a)sdcard是否已经没有空间(这个需求是存在的,但几乎没有人会考虑到,一旦发生,必crash)。

b)缓存的清理策略。每日、每周定时清理?到达一个阀值后,自动清理?(若无清理策略,把垃圾数据一直当个宝一相存着,是很SB的)。

c)缓存真正需要的数据。不要觉外存是无限的,所以就可以什么都存,要知道,多则繁,繁则乱。曾经有一同事,每天存几百MB的用户数据(所有用户的性别、 age、联系方式等等),而PM需要的只是一个每日数户的活跃数据报表,于是最后改为缓存每天的用户分析报表数据即可(才10几KB)。

d)给缓存文件加密。最简单就是去掉文件的扩展名,这也算加密,当然,你可以把服务端文件加密,然后在内存中解密。这就看项目的需求而定,我的经验也不足,一般就是改改扩展名之类的。

网络图片在开发过程中,一般都将图片缓存到本地sd卡中(经常要使用的图片),方便下次直接引用而不再次请求网络耗费资源。而如果是自己开发搜索功能里有涉及到图片的显示,可以直接Map<String, SoftReference<Drawable>>,即软引用。

软引用重要代码代码:

package com.test.load;

 

import java.lang.ref.SoftReference;

import java.net.URL;

import java.util.HashMap;

import java.util.Map;

 

import android.graphics.drawable.Drawable;

import android.os.Handler;

import android.os.Message;

 

public class ThreadImgLoader {

  private Map<String, SoftReference<Drawable>> imageCache=new HashMap<String, SoftReference<Drawable>>();

  

   public Drawable loadDrawable(final String imgUrl, final ImageCallback callback){

      if (imageCache.containsKey(imgUrl)) {

        SoftReference<Drawable> sf=imageCache.get(imgUrl);

        if (sf.get()!=null) {

           return sf.get();

        }

      }

      final Handler handler=new Handler(){

        public void handleMessage(Message msg) {

           callback.imageLoaded((Drawable) msg.obj);

        }

      };

      new Thread(){

        public void run() {

           Drawable drawable=loadImgFromUrl(imgUrl);

           if (drawable!=null) {

              imageCache.put(imgUrl, new SoftReference<Drawable>(drawable));

              Message msg=handler.obtainMessage(0, drawable);

              handler.sendMessage(msg);

           }

        }

      }.start();

      return null;

   }

  

   public Drawable loadImgFromUrl(String imgUrl) {

      try {

        return Drawable.createFromStream(new URL(imgUrl).openStream(), "src");

      } catch (Exception e) {

        return null;

      }

   }

  

   public interface ImageCallback{

      public void imageLoaded(Drawable drawable);

   }

}

 下面是缓存到SD卡的重要代码,当然你也可以搜索一下,这方面的东西很多。WeakHashMap也是使用了软引用,你可以去看它的源代码:

package com.test;

 

import java.io.File;

import java.io.FileOutputStream;

import java.io.OutputStream;

import java.util.WeakHashMap;

 

import android.graphics.Bitmap;

import android.graphics.Bitmap.CompressFormat;

import android.graphics.BitmapFactory;

import android.os.Environment;

 

public class MyImgCache extends WeakHashMap<String, Bitmap> {

   private static MyImgCache myImgCache=new MyImgCache();

   private static final String CACHE_FILE="/MyXiaoCaiImg";

   public static MyImgCache getInstance(){

      return myImgCache;

   }

  

   public boolean isBitmapExist(String url) {

      boolean isexist=false;

      String name=changeUrlName(url);

      String filePath=isMakeFile();

      File file=new File(filePath, name);

      if (containsKey(url)) {

        isexist=true;

      }else if (file.exists()) {

        String path=file.getAbsolutePath();

        System.out.println(path);

        Bitmap bitmap=BitmapFactory.decodeFile(path);

        if (bitmap!=null) {

           put(url, bitmap, false);

           isexist=true;

        }

      }

      return isexist;

   }

 

   private String changeUrlName(String url) {

      String name = url.replaceAll(":", "_");

      name = name.replaceAll("//", "_");

      name = name.replaceAll("/", "_");

      name = name.replaceAll("=", "_");

      name = name.replaceAll(",", "_");

      name = name.replaceAll("&", "_");

      return name;

   }

  

   private String isMakeFile() {

      String rootpath = null;

      if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

        rootpath = Environment.getExternalStorageDirectory().toString();

      }

      String filepath = rootpath + CACHE_FILE;

      File file = new File(filepath);

      if (!file.exists()) {

        file.mkdirs();

      }

      return filepath;

   }

 

   public Bitmap put(String key, Bitmap value) {

      String name=changeUrlName(key);

      String filePath=isMakeFile();

      File file = new File(filePath, name);

      OutputStream outputStream = null;

      try {

        outputStream = new FileOutputStream(file);

        value.compress(CompressFormat.JPEG, 100, outputStream);

        outputStream.flush();

        outputStream.close();

        outputStream = null;

      } catch (Exception e) {

        e.printStackTrace();

      }

      return super.put(key, value);

   }

 

   public Bitmap put(String key, Bitmap value, boolean b) {

      if (b) {

        return this.put(key, value);

      }else {

        return super.put(key, value);

      }

   }

 

}

 

分享到:
评论

相关推荐

    Android VideoCache视频缓存的方法详解

    项目中遇到视频播放,需要加载网络url,不可能每次都进行网络加载,当然了,就需要用到我们的缓存机制 AndroidVideoCache AndroidVideoCache是一个视频/音频缓存库,利用本地代理实现了边下边播,使用起来非常简单...

    Android项目 Gallery实现异步加载网络图片 并只加载当前停止页面图.rar

    3. **缓存机制**:采用LruCache或DiskLruCache技术,对已加载的图片进行缓存,提高再次访问时的加载速度。 4. **图片适配**:支持多种图片格式,自动根据设备屏幕尺寸和分辨率进行图片适配,保证显示效果。 5. **可...

    新版Android开发教程.rar

    ----------------------------------- Android 编程基础 1 封面----------------------------------- Android 编程基础 2 开放手机联盟 --Open --Open --Open --Open Handset Handset Handset Handset Alliance ...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    3.3.1跨域缓存机制的主要实现 19 3.3.2.页面回退管理的实现 22 3.4本章小结 22 第四章 页面自适应机制设计 23 4.1页面兼容策略 23 4.2 页面自适应策略 24 4.2.1设备自适应 24 4.2.2.浏览器自适应 25 4.3 模块实现 25...

    Android分页获取sqlite数据

    适合初学者 知识点: 1、listView分页加载 2、利用SparseArray实现ViewHolder的缓存 3、java反射机制读取sqlite查询结果 4、sqlite数据库分页读取 5、文件拷贝操作

    基于Android的聊天室应用 ChatRoom 1.0

    一、端点连接机制:基于客户端到服务器端的socket连接,在服务器端利用android系统提供的线程池处理用户的并发访问。 二、消息发送原理:在服务器端缓存所有当前在线用户,对于接收到的文字消息或语音消息循环发送到...

    Android开发资料合集--续

    2、利用startActivityForResult与onActivityResult方法 16 11、使程序完全退出 18 12、列出所有音乐文件 18 13、使用Intent ACTION 调用系统程序 19 显示网页: 19 显示地图: 19 路径规划: 19 拨打电话: 19 发送 SMS/...

    基于Android的聊天室应用 ChatRoom 1.2

    一、端点连接机制:基于客户端到服务器端的socket连接,在服务器端利用android系统提供的线程池处理用户的并发访问。 二、消息发送原理:在服务器端缓存所有当前在线用户,对于接收到的文字消息或语音消息循环发送...

    安卓java读取网页源码-AndroidStudy:Android进阶内容整理

    安卓java读取网页源码 AndroidStudy Android进阶内容整理 blog地址链接: ...Android事件分发机制完全解析,带你从源码的角度彻底理解(上) 2.公共技术点之 View 事件传递 3.EventBus 源码解析 EventBus gre

    黑马程序员 安卓学院 万元哥项目经理 分享220个代码实例

    |--利用FinalHttp实现多线程断点续传 |--加密之MD5 |--动画Animation详解 |--动画之view左右抖动 |--动画之移动动画 |--动画之组合动画 |--动画之缩放动画ScaleAnimation |--反序列化对象 |--发送短信 读天气 调音量...

    Android项目源码开源的 Material Design 豆瓣客户端.zip

    通过大量的文档阅读、源代码分析和调试,经过大约一周的时间,最终实现了较为理想的效果。 屏幕旋转 Android 在屏幕旋转时,会销毁视图和 Activity 并重建,此时如何保存视图状态和已加载的数据、正在进行的网络...

    基于Android的聊天室应用

    一、端点连接机制:基于客户端到服务器端的socket连接,在服务器端利用android系统提供的线程池处理用户的并发访问。 二、消息发送原理:在服务器端缓存所有当前在线用户,对于接收到的文字消息或语音消息循环发送到...

    JAVA上百实例源码以及开源项目

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    JAVA上百实例源码以及开源项目源代码

    凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 简单 EJB的真实世界模型(源代码) 15个目标文件 摘要:Java源码,初学实例,基于EJB的真实...

    java开源包3

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包10

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包4

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包1

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包11

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

Global site tag (gtag.js) - Google Analytics