当前位置: 首页 > article >正文

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

文章目录

    • 在Android应用中实现图片缓存和下载
      • 项目结构
        • 使用
      • 代码解析
      • 关键功能解析
        • 1. 图片加载方法
        • 2. 下载图片
        • 3. 保存图片到缓存
        • 4. 文件名提取
    • 或者通过学习glide

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

<uses-permission android:name="android.permission.INTERNET" />

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

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

项目结构

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

使用
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);
    }
}

代码解析

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的图片。首先,它尝试从本地缓存读取图片,如果缓存存在,则直接使用缓存的图片;如果不存在,则启动一个新线程下载图片。

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下载图片。它设置了连接和读取的超时,以避免长时间等待。

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格式保存到应用的缓存目录中。

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中提取文件名,以便在缓存中使用。

private String getFileNameFromUrl(String url) {
    return url.substring(url.lastIndexOf("/") + 1);
}

或者通过学习glide


http://www.kler.cn/a/377367.html

相关文章:

  • jenkins入门10--自动化构建
  • DAY15 神经网络的参数和变量
  • 基于springboot的网上商城购物系统
  • 数据结构:包装类和泛型
  • SSM-SpringMVC-请求响应、REST、JSON
  • c++类和对象---上
  • 使用Git LFS管理大型文件
  • 适用于 c++ 的 wxWidgets框架源码编译SDK-windows篇
  • 【蔬菜识别】Python+深度学习+CNN卷积神经网络算法+TensorFlow+人工智能+模型训练
  • el-date-picker日期选择器动态设置日期
  • 基于python的语音识别与蓝牙通信的温控系统
  • 2024年大厂AI大模型面试题精选与答案解析
  • ffmpeg常用命令
  • RabbitMQ的主题模式
  • ensp中acl的使用
  • Vue页面带参数跳转
  • UE5 材质篇 0 创建一个材质
  • 如何在社媒平台上使用代理IP来保护帐号安全
  • solidity selfdestruct合约销毁
  • C语言专题
  • CSS元素类型(二)
  • 单个相机矫正畸变
  • 【图解版】力扣第121题:买卖股票的最佳时机
  • 使用贪心策略求解糖果罐调整次数
  • C# 单个函数实现各进制数间转换
  • 设计模式 - 简单工厂模式