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