Android的缓存机制——图片的缓存

本文探讨了Android应用中的缓存机制,包括如何利用本地存储避免重复计算,新下载数据时的缓存策略,以及如何通过设定缓存过期时间来管理空间和时间。介绍了使用AsyncTask方法在后台下载图片并利用缓存显示的实践案例,同时讨论了应用缓存机制的进一步考虑,如缓存容量、清理策略和长期维护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

缓存的目的是避免重复计算,特别是对消耗时间和资源的计算。Android中的缓存机制是利用本地存储实现的。

1.新下载数据的时候,将数据缓存到本地。
2.再次下载之前,先判断该资源是否已经被缓存,如果是,则优先使用本地资源,如果没有被缓存,则从网上下载资源,并进行缓存。
这里需要额外考虑两个因素:空间和时间。比如以缓存文本为主的应用,由于问恩本身占用极小的空间,其缓存大小可以根据用户的磁盘空间大小来确定;以缓存图片为主的应用,由于图片占用空间较大,更加需要用户参与指定空间大小。
3.对于时间限制,可以通过设定缓存的过期时间来实现,为下载到缓存的数据设定时间戳,在读取改缓存的时候,比较时间戳,超过时间限制的则需要更新改缓存。在清空应用缓存的时候也需要谨慎,在存储空间已满,用户注销的时候可以考虑清空改用户的整个缓存,而在普通升级应用的情况下并不需要清空整个缓存。
下面我们用AsyncTask方法,在后台下载图片,利用缓存机制显示。

public class PictureShowActivity extends Activity{

    //新建URL
    URL url;
    //获取SD卡根目录
    String sdcardPATH = Environment.getExternalStorageDirectory() + "/";
    //设置缓存的目录
    String cachePath = sdcardPATH + "pictureCache";
    Button showPicture;
    ImageView pictureView;
    EditText urlText;
    HashMap<String, String> cacheMap = new HashMap<String, String>();
    File file;
    String urlString;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        //设置布局文件
        setContentView(R.layout.activity_picture_show);
        //绑定控件
        pictureView = (ImageView)findViewById(R.id.pictureView);
        urlText = (EditText)findViewById(R.id.urlText);
        showPicture = (Button)findViewById(R.id.showPicture);
        //添加按钮监听
        showPicture.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                //获取图片地址
                urlString = urlText.getText().toString();
                //输入检测
                if(urlString != null && urlString.length() >0){
                    //检测图片地址
                    urlString = (urlString.startsWith("http://")) ? urlString : "http://" + urlString;
                    if(cacheMap != null && cacheMap.containsKey(urlString)){
                        //获取保存的地址
                        String cacheFile = cacheMap.get(urlString).toString();
                        //验证该地址的文档是否存在
                        if(checkFileExists(cacheFile)){
                            //存在则显示缓存中的内容
                            Drawable d = Drawable.createFromPath(cacheFile);
                            pictureView.setImageDrawable(d);
                        }else{
                            //不存在则显示缓存中的内容
                            downFile(urlString);
                        }
                    }else{
                        //存在则直接显示
                        downFile(urlString);
                    }
                }
            }
        });
    }
    //下载文件
    public void downFile(String url){
        //调用异步下载方法
        new DownloadFileTask().execute(url);
    }

    //判断文件是否已经存在
    public boolean checkFileExists(String filepath){
        //新建文件对象
        File file = new File(filepath);
        return file.exists();
    }

    //以异步方式下载文件
    private class DownloadFileTask extends AsyncTask<String, Integer, Integer>{
        //后台下载
        @Override
        protected Integer doInBackground(String... sUrl) {
            // TODO Auto-generated method stub
            try{
                //获取URL地址
                String urlString = sUrl[0];
                //实例化url对象
                url = new URL(urlString);
                //打开连接
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                //获取内容
                InputStream istream = connection.getInputStream();
                //获取文件名称
                String filename = urlString.substring(urlString.lastIndexOf("/") + 1);
                //实例化新的文件目录
                File dir = new File(cachePath);
                //判断文件目录是否存在
                if(!dir.exists()){
                    //创建目录
                    dir.mkdir();
                }
                //实例化新的文件
                file = new File(cachePath + filename);
                //创建文件
                file.createNewFile();
                //读取信息到文件中
                OutputStream output = new FileOutputStream(file);
                byte[] buffer = new byte[1024 * 4];
                while(istream.read(buffer) != -1){
                    output.write(buffer);
                }
                //写入文件
                output.flush();
                output.close();
                istream.close();
            }catch(Exception ex){
                ex.printStackTrace();
                return -1;
            }
            return 1;
        }

        @Override
        protected void onPostExecute(Integer result) {
            // TODO Auto-generated method stub
            //如果没有异常
            if(result > 0){
                //保存到缓存维护键值对
                cacheMap.put(urlString,  file.getPath());
                Drawable d = Drawable.createFromPath(file.getPath());
                pictureView.setBackgroundDrawable(d);
            }
        }
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="URL: "/>

        <EditText
            android:id="@+id/urlText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:text="http://www.adnroid.com/images/logo.png" />
    </LinearLayout>

        <Button
            android:id="@+id/showPicture"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="ShowPicture"/>

        <ImageView 
            android:id="@+id/pictureView"
            android:layout_width="match_parent"
            android:layout_height="50dp"/>

       <!--  <ImageView 
            android:id="@+id/imageView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/ic_launcher"/> -->

</LinearLayout>
需要加入两个权限
<uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

这个案例比较简单,更加深入的讨论可以参看相关文献。很多时候,应用缓存机制还需要考虑一下几点:缓存的容量不是无限大的,需要给定一个可调整的值;缓存需要有相应的清理策略;缓存列表不能只放在内存里面,还需要利用数据库等进行长期的有效维护。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值