Android異步加載圖片并緩存到內存和SD卡上

jopen 11年前發布 | 74K 次閱讀 Android Android開發 移動開發

* 異步加載圖片

  • 使用方法:
  • private AsyncImageLoader asyImg = new AsyncImageLoader();
  • asyImg.LoadImage(productItems.get(position).getPic(), (ImageView)view.findViewById(R.id.pic)); */

public class AsyncImageLoader { // 為了加快速度,在內存中開啟緩存(主要應用于重復圖片較多時,或者同一個圖片要多次被訪問,比如在ListView時來回滾動) public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>(); private ExecutorService executorService = Executors.newFixedThreadPool(5); // 固定五個線程來執行任務 private final Handler handler = new Handler(); // SD卡上圖片儲存地址 private final String path = Environment.getExternalStorageDirectory() .getPath() + "/maiduo";

/**
 * 
 * @param imageUrl
 *            圖像url地址
 * @param callback
 *            回調接口
 * @return 返回內存中緩存的圖像,第一次加載返回null
 */
public Drawable loadDrawable(final String imageUrl,
        final ImageCallback callback) {
    // 如果緩存過就從緩存中取出數據
    if (imageCache.containsKey(imageUrl)) {
        SoftReference<Drawable> softReference = imageCache.get(imageUrl);
        if (softReference.get() != null) {
            return softReference.get();
        }
    } else if (useTheImage(imageUrl) != null) {
        return useTheImage(imageUrl);
    }
    // 緩存中沒有圖像,則從網絡上取出數據,并將取出的數據緩存到內存中
    executorService.submit(new Runnable() {
        public void run() {
            try {
                final Drawable drawable = Drawable.createFromStream(
                        new URL(imageUrl).openStream(), "image.png");
                imageCache.put(imageUrl, new SoftReference<Drawable>(
                        drawable));
                handler.post(new Runnable() {
                    public void run() {
                        callback.imageLoaded(drawable);
                    }
                });
                saveFile(drawable, imageUrl);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    });
    return null;
}

// 從網絡上取數據方法
public Drawable loadImageFromUrl(String imageUrl) {
    try {

        return Drawable.createFromStream(new URL(imageUrl).openStream(),
                "image.png");
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

// 對外界開放的回調接口
public interface ImageCallback {
    // 注意 此方法是用來設置目標對象的圖像資源
    public void imageLoaded(Drawable imageDrawable);
}

// 引入線程池,并引入內存緩存功能,并對外部調用封裝了接口,簡化調用過程
public void LoadImage(final String url, final ImageView iv) {
    if (iv.getImageMatrix() == null) {
        iv.setImageResource(R.drawable.loading);
    }
    // 如果緩存過就會從緩存中取出圖像,ImageCallback接口中方法也不會被執行
    Drawable cacheImage = loadDrawable(url,
            new AsyncImageLoader.ImageCallback() {
                // 請參見實現:如果第一次加載url時下面方法會執行
                public void imageLoaded(Drawable imageDrawable) {
                    iv.setImageDrawable(imageDrawable);
                }
            });
    if (cacheImage != null) {
        iv.setImageDrawable(cacheImage);
    }
}

/**
 * 保存圖片到SD卡上
 * 
 * @param bm
 * @param fileName
 * 
 */
public void saveFile(Drawable dw, String url) {
    try {
        BitmapDrawable bd = (BitmapDrawable) dw;
        Bitmap bm = bd.getBitmap();

        // 獲得文件名字
        final String fileNa = url.substring(url.lastIndexOf("/") + 1,
                url.length()).toLowerCase();
        File file = new File(path + "/image/" + fileNa);
        // 創建圖片緩存文件夾
        boolean sdCardExist = Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED); // 判斷sd卡是否存在
        if (sdCardExist) {
            File maiduo = new File(path);
            File ad = new File(path + "/image");
            // 如果文件夾不存在
            if (!maiduo.exists()) {
                // 按照指定的路徑創建文件夾
                maiduo.mkdir();
                // 如果文件夾不存在
            } else if (!ad.exists()) {
                // 按照指定的路徑創建文件夾
                ad.mkdir();
            }
            // 檢查圖片是否存在
            if (!file.exists()) {
                file.createNewFile();
            }
        }

        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream(file));
        bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
        bos.flush();
        bos.close();
    } catch (Exception e) {
        // TODO: handle exception
    }
}

/**
 * 使用SD卡上的圖片
 * 
 */
public Drawable useTheImage(String imageUrl) {

    Bitmap bmpDefaultPic = null;

    // 獲得文件路徑
    String imageSDCardPath = path
            + "/image/"
            + imageUrl.substring(imageUrl.lastIndexOf("/") + 1,
                    imageUrl.length()).toLowerCase();
    File file = new File(imageSDCardPath);
    // 檢查圖片是否存在
    if (!file.exists()) {
        return null;
    }
    bmpDefaultPic = BitmapFactory.decodeFile(imageSDCardPath, null);

    if (bmpDefaultPic != null || bmpDefaultPic.toString().length() > 3) {
        Drawable drawable = new BitmapDrawable(bmpDefaultPic);
        return drawable;
    } else
        return null;
}

}</pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!