異步圖片加載控件

發一個異步圖片加載控件。網上也有大把的異步網絡加載圖片的控件,但是有一個問題,異步加載會造成列表中的圖片混亂,因爲列表的每一項的View都可能被重用,異步加載的時候多個異步線程引用到了同一個View造成圖片加載混亂。該控件解決這個問題:

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 [email protected]
 * @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<String, Integer, Bitmap> {
/**
* 是否取消
*/
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;
}
}

發佈了19 篇原創文章 · 獲贊 28 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章