: import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.net.URLConnection; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.util.AttributeSet; import android.widget.ImageView; /** * 非同步圖片控制項 * 使用:new AsyncImageView().asyncLoadBitmapFromUrl("http://xxxx","緩衝路徑"){ * * @author gaoomei@gmail.com * @site http://obatu.sinaapp.com * @version 1.0 * @2011-12-3 */ public class AsyncImageView extends ImageView { /** * 非同步task載入器 */ private AsyncLoadImage mAsyncLoad; /** * 下載回來的圖片緩衝存活時間,單位:秒(s),預設30分鐘 */ private long mCacheLiveTime = 1800; public AsyncImageView(Context context) { super(context); } public AsyncImageView(Context context, AttributeSet attrs) { super(context, attrs); } public AsyncImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * */ @Override public void setImageDrawable(Drawable drawable) { if (mAsyncLoad != null) { mAsyncLoad.cancel(true); mAsyncLoad = null; } super.setImageDrawable(drawable); } /** * 重寫下面幾個設定圖片資源的方法,目地是取消網路載入 */ @Override public void setImageResource(int resId) { cancelLoad(); super.setImageResource(resId); } @Override public void setImageURI(Uri uri) { cancelLoad(); super.setImageURI(uri); } @Override public void setImageBitmap(Bitmap bitmap) { cancelLoad(); super.setImageBitmap(bitmap); } /** * 取消進行中的非同步task */ public void cancelLoad() { if (mAsyncLoad != null) { mAsyncLoad.cancel(true); mAsyncLoad = null; } } /** * 設定圖片存活時間 * * @param second * 存活時間,單位【秒】,如果等於0或null,則不緩衝 */ public void setCacheLiveTime(long second) { if (second == 0) { this.mCacheLiveTime = 0; } else if (second >= 0) { this.mCacheLiveTime = second * 1000; } } /** * 從網路非同步載入 * * @param url * @param saveFileName */ public void asyncLoadBitmapFromUrl(String url, String saveFileName) { if (mAsyncLoad != null) { mAsyncLoad.cancel(true); } // AsyncTask不可重用,所以每次重新執行個體 mAsyncLoad = new AsyncLoadImage(); mAsyncLoad.execute(url, saveFileName); } /** * 非同步載入器 */ private class AsyncLoadImage extends AsyncTask { /** * 是否取消 */ private boolean isCancel = false; @Override protected Bitmap doInBackground(String... params) { if (isCancel) { return null; } String url = params[0]; String fileName = params[1]; try { return getBitmap(url, fileName); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onCancelled() { System.out.println("async load imgae cancel"); isCancel = true; } @Override protected void onPostExecute(Bitmap result) { if (!isCancel && result != null) { AsyncImageView.this.setImageBitmap(result); } } } /** * 下載圖片 * * @param urlString * url下載地址 * @param fileName * 快取檔案路徑 * @throws IOException */ private Bitmap getBitmap(String urlString, String fileName) throws IOException { if (fileName == null || fileName.trim().isEmpty()) { InputStream input = getBitmapInputStreamFromUrl(urlString); return BitmapFactory.decodeStream(input); } File file = new File(fileName); if (!file.isFile() || (mCacheLiveTime > 0 && (System.currentTimeMillis() - file.lastModified() > mCacheLiveTime))) { InputStream input = getBitmapInputStreamFromUrl(urlString); file = saveImage(input, fileName); // 如果檔案結構建立失敗,則直接從輸入資料流解碼圖片 if (file == null || !file.exists() || !file.canWrite() || !file.canRead()) { return BitmapFactory.decodeStream(input); } } return BitmapFactory.decodeFile(file.getAbsolutePath()); } /** * 下載圖片,輸入InputStream * * @param urlString * @return * @throws IOException */ private InputStream getBitmapInputStreamFromUrl(String urlString) throws IOException { URL url = new URL(urlString); URLConnection connection = url.openConnection(); connection.setConnectTimeout(25000); connection.setReadTimeout(90000); return connection.getInputStream(); } /** * 從輸入資料流儲存圖片到檔案系統 * * @param fileName * @param input * @return */ private File saveImage(InputStream input, String fileName) { if (fileName.trim().isEmpty() || input == null) { return null; } File file = new File(fileName); OutputStream output = null; try { file.getParentFile().mkdirs(); if (file.exists() && file.isFile()) { file.delete(); } if (!file.createNewFile()) { return null; } output = new FileOutputStream(file); byte[] buffer = new byte[4 * 1024]; do { // 迴圈讀取 int numread = input.read(buffer); if (numread == -1) { break; } output.write(buffer, 0, numread); } while (true); output.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { output.close(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e2) { e2.printStackTrace(); } } return file; } } |