Android实现图片异步加载并缓存到本地
程序员文章站
2024-02-21 13:28:40
在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片。
软引用是一个现在非常流行的方法,用户体验...
在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片。
软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取。
下面就分享一下异步加载网络图片的方法吧。
filecache.java
import java.io.file; import android.content.context; public class filecache { private file cachedir; public filecache(context context) { // 找一个用来缓存图片的路径 if (android.os.environment.getexternalstoragestate().equals( android.os.environment.media_mounted)) cachedir = new file(android.os.environment.getexternalstoragedirectory(), "文件夹名称"); else cachedir = context.getcachedir(); if (!cachedir.exists()) cachedir.mkdirs(); } public file getfile(string url) { 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; for (file f : files) f.delete(); } }
httputil.java
import java.io.bytearrayoutputstream; import java.io.file; import java.io.filenotfoundexception; import java.io.fileoutputstream; import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.io.unsupportedencodingexception; import java.net.httpurlconnection; import java.net.malformedurlexception; import java.net.protocolexception; import java.net.url; import java.net.urlencoder; import java.util.map; /** * http 请求工具类 * * @author scorpio.liu * */ public class httputil { /** * 获取响应字符串 * * @param path * 路径 * @param parameters * 参数 * @return 响应字符串 */ public static string getresponsestr(string path, map<string, string> parameters) { stringbuffer buffer = new stringbuffer(); url url; try { if (parameters != null && !parameters.isempty()) { for (map.entry<string, string> entry : parameters.entryset()) { // 完成转码操作 buffer.append(entry.getkey()).append("=") .append(urlencoder.encode(entry.getvalue(), "utf-8")).append("&"); } buffer.deletecharat(buffer.length() - 1); } url = new url(path); httpurlconnection urlconnection = (httpurlconnection) url.openconnection(); urlconnection.setconnecttimeout(3000); urlconnection.setrequestmethod("post"); urlconnection.setdoinput(true);// 表示从服务器获取数据 urlconnection.setdooutput(true);// 表示向服务器写数据 // 获得上传信息的字节大小以及长度 byte[] mydata = buffer.tostring().getbytes(); // 表示设置请求体的类型是文本类型 urlconnection.setrequestproperty("content-type", "application/x-www-form-urlencoded"); urlconnection.setrequestproperty("content-length", string.valueof(mydata.length)); // 获得输出流,向服务器输出数据 outputstream outputstream = urlconnection.getoutputstream(); outputstream.write(mydata, 0, mydata.length); outputstream.close(); int responsecode = urlconnection.getresponsecode(); if (responsecode == 200) { return changeinputstream(urlconnection.getinputstream()); } } catch (unsupportedencodingexception e) { e.printstacktrace(); } catch (malformedurlexception e) { e.printstacktrace(); } catch (protocolexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } return null; } private static string changeinputstream(inputstream inputstream) { bytearrayoutputstream outputstream = new bytearrayoutputstream(); byte[] data = new byte[1024]; int len = 0; string result = ""; if (inputstream != null) { try { while ((len = inputstream.read(data)) != -1) { outputstream.write(data, 0, len); } result = new string(outputstream.tobytearray(), "utf-8"); } catch (ioexception e) { e.printstacktrace(); } } return result; } public static inputstream getinputstream(string path) { url url; try { url = new url(path); httpurlconnection urlconnection = (httpurlconnection) url.openconnection(); urlconnection.setconnecttimeout(3000); urlconnection.setrequestmethod("get"); urlconnection.setdoinput(true);// 表示从服务器获取数据 urlconnection.connect(); if (urlconnection.getresponsecode() == 200) return urlconnection.getinputstream(); } catch (malformedurlexception e) { // todo auto-generated catch block e.printstacktrace(); } catch (ioexception e) { // todo auto-generated catch block e.printstacktrace(); } catch (exception e) { // todo auto-generated catch block e.printstacktrace(); } return null; } public static byte[] readstream(inputstream instream) throws exception { bytearrayoutputstream outsteam = new bytearrayoutputstream(); byte[] buffer = new byte[1024]; int len = -1; while ((len = instream.read(buffer)) != -1) { outsteam.write(buffer, 0, len); } outsteam.close(); instream.close(); return outsteam.tobytearray(); } public static void copystream(string url, file f) { fileoutputstream fileoutputstream = null; inputstream inputstream = null; try { inputstream = getinputstream(url); byte[] data = new byte[1024]; int len = 0; fileoutputstream = new fileoutputstream(f); while ((len = inputstream.read(data)) != -1) { fileoutputstream.write(data, 0, len); } } catch (filenotfoundexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } finally { if (inputstream != null) { try { inputstream.close(); } catch (ioexception e) { e.printstacktrace(); } } if (fileoutputstream != null) { try { fileoutputstream.close(); } catch (ioexception e) { e.printstacktrace(); } } } } }
memorycache.java
import java.lang.ref.softreference; import java.util.collections; import java.util.hashmap; import java.util.map; import android.graphics.bitmap; public class memorycache { private map<string, softreference<bitmap>> cache = collections .synchronizedmap(new hashmap<string, softreference<bitmap>>());// 软引用 public bitmap get(string id) { if (!cache.containskey(id)) return null; softreference<bitmap> ref = cache.get(id); return ref.get(); } public void put(string id, bitmap bitmap) { cache.put(id, new softreference<bitmap>(bitmap)); } public void clear() { cache.clear(); } }
imageloader.java
import java.io.file; import java.io.fileinputstream; import java.io.filenotfoundexception; import java.io.unsupportedencodingexception; import java.net.urlencoder; import java.util.collections; import java.util.map; import java.util.weakhashmap; import java.util.concurrent.executorservice; import java.util.concurrent.executors; import android.app.activity; import android.content.context; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.graphics.drawable.bitmapdrawable; import android.widget.imageview; public class imageloader { private memorycache memorycache = new memorycache(); private filecache filecache; private map<imageview, string> imageviews = collections .synchronizedmap(new weakhashmap<imageview, string>()); private executorservice executorservice; private boolean issrc; /** * @param context * 上下文对象 * @param flag * true为source资源,false为background资源 */ public imageloader(context context, boolean flag) { filecache = new filecache(context); executorservice = executors.newfixedthreadpool(5); issrc = flag; } final int stub_id = r.drawable.ic_launcher; public void displayimage(string url, imageview imageview) { string u1 = url.substring(0, url.lastindexof("/") + 1); string u2 = url.substring(url.lastindexof("/") + 1); try { u2 = urlencoder.encode(u2, "utf-8"); } catch (unsupportedencodingexception e) { e.printstacktrace(); } url = u1 + u2; imageviews.put(imageview, url); bitmap bitmap = memorycache.get(url); if (bitmap != null) { if (issrc) imageview.setimagebitmap(bitmap); else imageview.setbackgrounddrawable(new bitmapdrawable(bitmap)); } else { queuephoto(url, imageview); if (issrc) imageview.setimageresource(stub_id); else imageview.setbackgroundresource(stub_id); } } private void queuephoto(string url, imageview imageview) { phototoload p = new phototoload(url, imageview); executorservice.submit(new photosloader(p)); } private bitmap getbitmap(string url) { try { file f = filecache.getfile(url); // 从sd卡 bitmap b = ondecodefile(f); if (b != null) return b; // 从网络 bitmap bitmap = null; system.out.println("imageloader-->download"); httputil.copystream(url, f); bitmap = ondecodefile(f); return bitmap; } catch (exception ex) { ex.printstacktrace(); return null; } } public bitmap ondecodefile(file f) { try { return bitmapfactory.decodestream(new fileinputstream(f)); } catch (filenotfoundexception e) { // todo auto-generated catch block e.printstacktrace(); } return null; } /** * 解码图像用来减少内存消耗 * * @param f * @return */ public bitmap decodefile(file f) { try { // 解码图像大小 bitmapfactory.options o = new bitmapfactory.options(); o.injustdecodebounds = true; bitmapfactory.decodestream(new fileinputstream(f), null, o); // 找到正确的刻度值,它应该是2的幂。 final int required_size = 70; int width_tmp = o.outwidth, height_tmp = o.outheight; int scale = 1; while (true) { if (width_tmp / 2 < required_size || height_tmp / 2 < required_size) break; width_tmp /= 2; height_tmp /= 2; scale *= 2; } bitmapfactory.options o2 = new bitmapfactory.options(); o2.insamplesize = scale; return bitmapfactory.decodestream(new fileinputstream(f), null, o2); } catch (filenotfoundexception e) { } return null; } /** * 任务队列 * * @author scorpio.liu * */ private class phototoload { public string url; public imageview imageview; public phototoload(string u, imageview i) { url = u; imageview = i; } } class photosloader implements runnable { phototoload phototoload; photosloader(phototoload phototoload) { this.phototoload = phototoload; } @override public void run() { if (imageviewreused(phototoload)) return; bitmap bmp = getbitmap(phototoload.url); memorycache.put(phototoload.url, bmp); if (imageviewreused(phototoload)) return; bitmapdisplayer bd = new bitmapdisplayer(bmp, phototoload); activity a = (activity) phototoload.imageview.getcontext(); a.runonuithread(bd); } } boolean imageviewreused(phototoload phototoload) { string tag = imageviews.get(phototoload.imageview); if (tag == null || !tag.equals(phototoload.url)) return true; return false; } /** * 显示位图在ui线程 * * @author scorpio.liu * */ class bitmapdisplayer implements runnable { bitmap bitmap; phototoload phototoload; public bitmapdisplayer(bitmap b, phototoload p) { bitmap = b; phototoload = p; } public void run() { if (imageviewreused(phototoload)) return; if (bitmap != null) { if (issrc) phototoload.imageview.setimagebitmap(bitmap); else phototoload.imageview.setbackgrounddrawable(new bitmapdrawable(bitmap)); } else { if (issrc) phototoload.imageview.setimageresource(stub_id); else phototoload.imageview.setbackgroundresource(stub_id); } } } public void clearcache() { memorycache.clear(); filecache.clear(); } }
使用的时候用imageloader这个类就ok了,很方便~
希望本文所述对大家学习android软件编程有所帮助。