【Android】异步加载图片-------不错的思路
16lz
2021-12-22
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.URL;import java.util.HashMap;import java.util.Stack;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.widget.ImageView;/** * @author fed * 老外写的一个图片异步加载类,学习一下,应该可以改到任何适配器BaseAdapyer上去。 * * * 记得添加权限,访问internet,写外部存储器(sd卡等) * <uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> */public class ImageLoader {// the simplest in-memory cache implementation. This should be replaced with// something like SoftReference or BitmapOptions.inPurgeable(since 1.6)private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();PhotosQueue photosQueue = new PhotosQueue();// Task for the queueprivate class PhotoToLoad {public String url;public ImageView imageView;public PhotoToLoad(String u, ImageView i) {url = u;imageView = i;}}private File cacheDir;public ImageLoader(Context context) {// Make the background thead low priority. This way it will not affect// the UI performancephotoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);// Find the dir to save cached imagesif (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))cacheDir = new File(android.os.Environment.getExternalStorageDirectory(), "LazyList");elsecacheDir = context.getCacheDir();if (!cacheDir.exists())cacheDir.mkdirs();}final int stub_id = R.drawable.icon;public void DisplayImage(String url, Activity activity, ImageView imageView) {if (cache.containsKey(url))imageView.setImageBitmap(cache.get(url));else {queuePhoto(url, activity, imageView);imageView.setImageResource(stub_id);}}private void queuePhoto(String url, Activity activity, ImageView imageView) {// This ImageView may be used for other images before. So there may be// some old tasks in the queue. We need to discard them.photosQueue.Clean(imageView);PhotoToLoad p = new PhotoToLoad(url, imageView);synchronized (photosQueue.photosToLoad) {photosQueue.photosToLoad.push(p);photosQueue.photosToLoad.notifyAll();}// start thread if it's not started yetif (photoLoaderThread.getState() == Thread.State.NEW)photoLoaderThread.start();}private Bitmap getBitmap(String url) {// I identify images by hashcode. Not a perfect solution, good for the// demo.String filename = String.valueOf(url.hashCode());File f = new File(cacheDir, filename);// from SD cacheBitmap b = decodeFile(f);if (b != null)return b;// from webtry {Bitmap bitmap = null;InputStream is = new URL(url).openStream();OutputStream os = new FileOutputStream(f);Utils.CopyStream(is, os);os.close();bitmap = decodeFile(f);return bitmap;} catch (Exception ex) {ex.printStackTrace();return null;}}// decodes image and scales it to reduce memory consumptionprivate Bitmap decodeFile(File f) {try {// decode image sizeBitmapFactory.Options o = new BitmapFactory.Options();o.inJustDecodeBounds = true;BitmapFactory.decodeStream(new FileInputStream(f), null, o);// Find the correct scale value. It should be the power of 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++;}// decode with inSampleSizeBitmapFactory.Options o2 = new BitmapFactory.Options();o2.inSampleSize = scale;return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);} catch (FileNotFoundException e) {}return null;}public void stopThread() {photoLoaderThread.interrupt();}// stores list of photos to downloadclass PhotosQueue {private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();// removes all instances of this ImageViewpublic void Clean(ImageView image) {for (int j = 0; j < photosToLoad.size();) {if (photosToLoad.get(j).imageView == image)photosToLoad.remove(j);else++j;}}}class PhotosLoader extends Thread {@Overridepublic void run() {try {while (true) {// thread waits until there are any images to load in the// queueif (photosQueue.photosToLoad.size() == 0)synchronized (photosQueue.photosToLoad) {photosQueue.photosToLoad.wait();}if (photosQueue.photosToLoad.size() != 0) {PhotoToLoad photoToLoad;synchronized (photosQueue.photosToLoad) {photoToLoad = photosQueue.photosToLoad.pop();}Bitmap bmp = getBitmap(photoToLoad.url);cache.put(photoToLoad.url, bmp);if (((String) photoToLoad.imageView.getTag()).equals(photoToLoad.url)) {BitmapDisplayer bd = new BitmapDisplayer(bmp,photoToLoad.imageView);Activity a = (Activity) photoToLoad.imageView.getContext();a.runOnUiThread(bd);}}if (Thread.interrupted())break;}} catch (InterruptedException e) {// allow thread to exit}}}PhotosLoader photoLoaderThread = new PhotosLoader();// Used to display bitmap in the UI threadclass BitmapDisplayer implements Runnable {Bitmap bitmap;ImageView imageView;public BitmapDisplayer(Bitmap b, ImageView i) {bitmap = b;imageView = i;}public void run() {if (bitmap != null)imageView.setImageBitmap(bitmap);elseimageView.setImageResource(stub_id);}}public void clearCache() {// clear memory cachecache.clear();// clear SD cacheFile[] files = cacheDir.listFiles();for (File f : files)f.delete();}}
更多相关文章
- Android网格布局实现--recyclerview
- android 获取日期
- Android适配器之-----SimpleExpandableListAdapter
- android滑轮选择控件——whell
- Android(安卓)studio 简单适配器 simpleadapter
- 21、从头学Android之Android的数据存储--SD卡
- Android(安卓)自动完成文本框的实例
- Android之UI学习篇五:AutoCompleteTextView自动完成输入内容
- Android之UI学习篇五:AutoCompleteTextView自动完成输入内容