从网络到缓存:在Android中高效管理图片加载

文章目录

首先我们需要在配置AndroidManifest.xml里面添加

xml 复制代码
<uses-permission android:name="android.permission.INTERNET" />

在Android应用中实现图片缓存和下载

在现代移动应用开发中,用户体验至关重要,特别是在图像加载方面。为了提高应用的响应速度和减少网络流量,我们通常采用缓存机制来存储下载的图片。本文将介绍如何在Android中实现一个简单的图片缓存加载器,允许从网络下载图片并缓存到本地。

项目结构

我们将构建一个名为 ImageCacheLoader 的类,该类负责从URL加载图片,并首先检查本地缓存。如果缓存不存在,则从网络下载图片。

使用
java 复制代码
package com.example.dowhttppic;

import android.os.Bundle;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import android.os.Bundle;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private ImageView imageView;
    private ImageCacheLoader imageCacheLoader;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.imageView);

        // 初始化 ImageCacheLoader
        imageCacheLoader = new ImageCacheLoader(this);

        // 加载图片
        String imageUrl = "图片链接";
        imageCacheLoader.loadImage(imageUrl, imageView);
    }
}

代码解析

java 复制代码
package com.example.dowhttppic;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.widget.ImageView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class ImageCacheLoader {

    private Context context;
    private Handler handler = new Handler(); // 用于处理UI线程更新

    // 构造函数,接收上下文
    public ImageCacheLoader(Context context) {
        this.context = context;
    }

    // 公共方法:加载图片,首先从缓存读取,如果没有则通过网络下载
    public void loadImage(final String url, final ImageView imageView) {
        // 获取缓存目录
        File cacheDir = context.getCacheDir();
        String fileName = getFileNameFromUrl(url);
        final File imageFile = new File(cacheDir, fileName);

        // 如果本地有缓存,直接加载本地图片
        if (imageFile.exists()) {
            Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
            imageView.setImageBitmap(bitmap);
        } else {
            // 启动线程下载图片并缓存
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Bitmap bitmap = downloadImage(url);
                    if (bitmap != null) {
                        saveImageToCache(imageFile, bitmap);

                        // 更新UI,需在主线程中执行
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                imageView.setImageBitmap(bitmap);
                            }
                        });
                    } else {
                        // 超时或下载失败时显示默认图片
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                imageView.setImageResource(R.drawable.no_image_dow_http);
                            }
                        });
                    }
                }
            }).start();
        }
    }

    // 从网络下载图片,添加超时机制
    private Bitmap downloadImage(String urlString) {
        Bitmap bitmap = null;
        try {
            URL url = new URL(urlString);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(5000); // 设置连接超时为5秒
            connection.setReadTimeout(5000); // 设置读取超时为5秒
            connection.connect();
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                InputStream inputStream = connection.getInputStream();
                bitmap = BitmapFactory.decodeStream(inputStream);
                inputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    // 将下载的图片保存到本地缓存
    private void saveImageToCache(File imageFile, Bitmap bitmap) {
        try {
            OutputStream outputStream = new FileOutputStream(imageFile);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 根据URL提取文件名
    private String getFileNameFromUrl(String url) {
        return url.substring(url.lastIndexOf("/") + 1);
    }
}

关键功能解析

1. 图片加载方法

loadImage 方法是该类的核心,它负责加载指定URL的图片。首先,它尝试从本地缓存读取图片,如果缓存存在,则直接使用缓存的图片;如果不存在,则启动一个新线程下载图片。

java 复制代码
public void loadImage(final String url, final ImageView imageView) {
    File cacheDir = context.getCacheDir();
    String fileName = getFileNameFromUrl(url);
    final File imageFile = new File(cacheDir, fileName);

    if (imageFile.exists()) {
        Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
        imageView.setImageBitmap(bitmap);
    } else {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = downloadImage(url);
                if (bitmap != null) {
                    saveImageToCache(imageFile, bitmap);
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            imageView.setImageBitmap(bitmap);
                        }
                    });
                } else {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            imageView.setImageResource(R.drawable.no_image_dow_http);
                        }
                    });
                }
            }
        }).start();
    }
}
2. 下载图片

downloadImage 方法使用 HttpURLConnection 从给定URL下载图片。它设置了连接和读取的超时,以避免长时间等待。

java 复制代码
private Bitmap downloadImage(String urlString) {
    Bitmap bitmap = null;
    try {
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);
        connection.connect();
        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            InputStream inputStream = connection.getInputStream();
            bitmap = BitmapFactory.decodeStream(inputStream);
            inputStream.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return bitmap;
}
3. 保存图片到缓存

saveImageToCache 方法将下载的图片以PNG格式保存到应用的缓存目录中。

java 复制代码
private void saveImageToCache(File imageFile, Bitmap bitmap) {
    try {
        OutputStream outputStream = new FileOutputStream(imageFile);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
        outputStream.flush();
        outputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
4. 文件名提取

getFileNameFromUrl 方法从图片URL中提取文件名,以便在缓存中使用。

java 复制代码
private String getFileNameFromUrl(String url) {
    return url.substring(url.lastIndexOf("/") + 1);
}

总结

通过实现 ImageCacheLoader 类,我们成功地创建了一个简单的图片加载和缓存机制。这种方法不仅减少了网络流量,还提高了应用的响应速度和用户体验。在实际应用中,你可以根据需要进一步扩展该类,例如添加图片加载动画、处理更多的错误情况,或是实现更复杂的缓存策略。

相关推荐
阿巴斯甜1 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker2 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95273 小时前
Andorid Google 登录接入文档
android
黄林晴4 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab17 小时前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿19 小时前
Android MediaPlayer 笔记
android
Jony_20 小时前
Android 启动优化方案
android
阿巴斯甜20 小时前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇20 小时前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android