在Android的应用中实现网络图片异步加载的方法

网友投稿 230 2023-07-30


在Android的应用中实现网络图片异步加载的方法

前言

其实很幸运,入职一周之后就能跟着两个师兄做android开发,师兄都是大神,身为小白的我只能多多学习,多多努力。最近一段时间都忙的没机会总结,今天刚完成了android客户端图片异步加载的类,这里记录一下(ps:其实我这里都是参考网上开源实现)

原理

在ListView或者GridView中加载图片的原理基本都是一样的:

先从内存缓存中获取,取到则返回,取不到进行下一步

    从文件缓存中获取,取到则返回并更新到内存缓存,取不到则进行进行下一步

    从网络上下载图片,并更新内存缓存和文件缓存

流程图如下:

同时,要注意线程的数量。一般在listview中加载图片,大家都是开启新的线程去加载,但是当快速滑动时,很容易造成OOM,因此需要控制线程数量。我们可以通过线程池控制线程的数量,具体线程池的大小还需要根据处理器的情况和业务情况自行判断

建立线程池的方法如下:

ExecutorService executorService = Executors.newFixedThreadPool(5); // 5是可变的

文件缓存类

import java.io.File;

import android.content.Context;

public class FileCache {

private static final String DIR_NAME = "your_dir";

private File cacheDir;

public FileCache(Context context) {

// Find the directory to save cached images

if (android.os.Environment.getExternalStorageState().equals(

android.os.Environment.MEDIA_MOUNTED)) {

cacheDir = new File(

android.os.Environment.getExternalStorageDirectory(),

DIR_NAME);

} else {

cacheDir = context.getCacheDir();

}

if (!cacheDir.exists()) {

cacheDir.mkdirs();

}

}

public File getFile(String url) {

// Identify images by url's hash code

String filename = String.valueOf(url.hashCode());

File f = new File(cacheDir, filename);

return f;

}

public void clear() {

File[] files = cacheDir.listFiles();

if (files == null) {

return;

} else {

for (File f : files) {

f.delete();

}

}

}

}

内存缓存类

这里使用了软引用,Map> cache,可以google一下软引用的机制,简单的说:实现了map,同时当内存紧张时可以被回收,不会造成内存泄露

import java.lang.ref.SoftReference;

import java.util.Collections;

import java.util.LinkedHashMap;

import java.util.Map;

import android.graphics.Bitmap;

public class MemoryCache {

private Map> cache = Collections

.synchronizedMap(new LinkedHashMap>(

10, 1.5f, true));

public Bitmap get(String id) {

if (!cache.containsKey(id)) {

return null;

}

SoftReference ref = cache.get(id);

return ref.get();

}

public void put(String id, Bitmap bitmap) {

cache.put(id, new SoftReference(bitmap));

}

public void clear() {

cache.clear();

}

}

图片加载类

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.Collections;

import java.util.Map;

import java.util.WeakHashMap;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.os.Handler;

import android.widget.ImageView;

public class ImageLoader {

/**

* Network time out

*/

private static final int TIME_OUT = 30000;

/**

* Default picture resource

*/

private static final int DEFAULT_BG = R.drawable.plate_list_head_bg;

/**

* Thread pool number

*/

private static final int THREAD_NUM = 5;

/**

* Memory image cache

*/

MemoryCache memoryCache = new MemoryCache();

/**

* File image cache

*/

FileCache fileCache;

/**

* Judge image view if it is reuse

*/

private Map imageViews = Collections

.synchronizedMap(new WeakHashMap());

/**

* Thread paEqZiySeFool

*/

ExecutorService executorService;

/**

* Handler to display images in UI thread

*/

Handler handler = new Handler();

public ImageLoader(Context context) {

fileCache = new FileCache(context);

executorService = Executors.newFixedThreadPool(THREAD_NUM);

}

public void disPlayImage(String url, ImageView imageView) {

imageViews.put(imageView, url);

Bitmap bitmap = memoryCache.get(url);

if (bitmap != null) {

// Display image from Memory cache

imageView.setImageBitmap(bitmap);

} else {

// Display image from File cache or Network

queuePhoto(url, imageView);

}

}

private void queuePhoto(String url, ImageView imageView) {

PhotoToLoad photoToLoad = new PhotoToLoad(url, imageView);

executorService.submit(new PhotosLoader(photoToLoad));

}

private Bitmap getBitmap(String url) {

File f = fileCache.getFile(url);

// From File cache

Bitmap bmp = decodeFile(f);

if (bmp != null) {

return bmp;

}

// From Network

try {

Bitmap bitmap = null;

URL imageUrl = new URL(url);

HttpURLConnection conn = (HttpURLConnection) imageUrl

.openConnection();

conn.setConnectTimeout(TIME_OUT);

conn.setReadTimeout(TIME_OUT);

conn.setInstanceFollowRedirects(true);

InputStream is = conn.getInputStream();

OutputStream os = new FileOutputStream(f);

copyStream(is, os);

os.close();

conn.disconnect();

bitmap = decodeFile(f);

return bitmap;

} catch (Throwable ex) {

if (ex instanceof OutOfMemoryError) {

clearCache();

}

return null;

}

}

private void copyStream(InputStream is, OutputStream os) {

int buffer_size = 1024;

try {

byte[] bytes = new byte[buffer_size];

while (true) {

int count = is.read(bytes, 0, buffer_size);

if (count == -1) {

break;

}

os.write(bytes, 0, count);

}

} catch (Exception e) {

}

}

private Bitmap decodeFile(File f) {

try {

// TODO:Compress image size

FileInputStream fileInputStream = new FileInputStream(f);

Bitmap bitmap = BitmapFactory.decodeStream(fileInputStream);

return bitmap;

} catch (FileNotFoundException e) {

return null;

}

}

private void clearCache() {

memoryCache.clear();

fileCache.clear();

}

/**

* Task for the queue

*

* @author zhengyi.wzy

*

*/

private class PhotoToLoad {

public String url;

public ImageView imageView;

public PhotoToLoad(String url, ImageView imageView) {

this.url = url;

this.imageView = imageView;

}

}

/**

* Asynchronous to load picture

*

* @author zhengyi.wzy

*

*/

http:// class PhotosLoader implements Runnable {

PhotoToLoad photoToLoad;

public PhotosLoader(PhotoToLoad photoToLoad) {

this.photoToLoad = photoToLoad;

}

private boolean imageViewReused(PhotoToLoad photoToLoad) {

String tag = imageViews.get(photoToLoad.imageView);

if (tag == null || !tag.equals(photoToLoad.url)) {

return true;

}

return false;

}

@Override

public void run() {

// Abort current thread if Image View reused

if (imageViewReused(photoToLoad)) {

return;

}

Bitmap bitmap = getBitmap(photoToLoad.url);

// Update Memory

memoryCache.put(photoToLoad.url, bitmap);

if (imageViewReused(photoToLoad)) {

return;

}

// Don't change UI in children thread

BitmapDisplayer bd = new BitmapDisplayer(bitmap, photoToLoad);

handler.post(bd);

}

class BitmapDisplayer implements Runnable {

Bitmap bitmap;

PhotoToLoad photoToLoad;

public BitmapDisplayer(Bitmap bitmap, PhotoToLoad photoToLoad) {

this.bitmap = bitmap;

this.photoToLoad = photoToLoad;

}

@Override

public void run() {

if (imageViewReused(photoToLoad)) {

return;

}

if (bitmap != null) {

photoToLoad.imageView.setImageBitmap(bitmap);

} else {

photoToLoad.imageView.setImageResource(DEFAULT_BG);

}

}

}

}

}

调用方法

ImageLoader imageLoader = new ImageLoader(context);

imageLoader.disPlayImage(imageUrl, imageView);


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:函数window.open实现关闭所有的子窗口
下一篇:分享java打印简单图形的实现代码
相关文章

 发表评论

暂时没有评论,来抢沙发吧~