功能如下:
流程如下:
RemoteImageViewActivity:
publicclass RemoteImageViewActivity extends Activity {
/** Called when the activity is first created. */
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
RemoteImageView img = (RemoteImageView) findViewById(R.id.remote_img);
img.setDefaultImage(R.drawable.ic_launcher);
img.setImageUrl("http://img2.kwcdn.kuwo.cn:81/star/albumcover/120/7/8/83787_1323997225.jpg");
}
@Override
protectedvoid onPause() {
// TODO Auto-generated method stub
super.onPause();
}
}
ImageCache:
publicclass ImageCache extends WeakHashMap<String, Bitmap>{
/**
* 判斷該url是否存在
* @param url
* @return
*/
publicboolean isCached(String url){
return containsKey(url) && get(url) != null;
}
}
RemoteImageApplication:
publicclass RemoteImageApplication extends Application {
publicstaticfinal String TAG = "RemoteImageApplication";
privatestatic RemoteImageApplication application;
private ImageCache mImageCache;
public SharedPreferences prefs = null;
publicstatic RemoteImageApplication getInstance() {
return application;
}
@Override
publicvoid onCreate() {
// TODO Auto-generated method stub
super.onCreate();
application = this;
mImageCache = new ImageCache();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
}
public ImageCache getImageCache() {
return mImageCache;
}
}
RemoteSettings:
publicclass RemoteSettings {
publicstaticfinal String CACHE_SIZE = "cache_size"; //圖片緩存保留大小,如果超過該大小,即進行自動清除緩存.
}
RemoteImageView:
publicclass RemoteImageView extends ImageView {
private Context mContext;
privatestaticint mCacheSize = 150; // 設置的緩存大小。
privatestaticfinalint MAX_FAILURES = 3; // 下載的嘗試請求次數
privateint mFailure; // 下載失敗次數
private String mUrl; // 當前下載的url
private String mCurrentlyGrabbedUrl; // 當前下載成功的url
privatefinalstatic String JAMENDO_DIR = "Android/data/com.teleca.jamendo"; // 文件緩存存放的路徑.
privatefinalstaticlong MB = 1073741824;
public RemoteImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
}
public RemoteImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
public RemoteImageView(Context context) {
super(context);
mContext = context;
}
/**
* 設置默認圖片
*/
publicvoid setDefaultImage(Integer resid) {
setImageResource(resid);
}
/**
* 設置需要異步加載的圖片
*/
publicvoid setImageUrl(String url) {
// 下載失敗進行重試,如果重試次數超過規定的限制,則直接返回.
if (mUrl != null
&& mUrl.equals(url)
&& (mCurrentlyGrabbedUrl == null || (mCurrentlyGrabbedUrl != null && !mCurrentlyGrabbedUrl
.equals(url)))) {
mFailure++;
if (mFailure > MAX_FAILURES) {
Log.e(RemoteImageApplication.TAG, "下載該圖片地址失敗:" + url);
return;
}
} else {
mUrl = url;
mFailure = 0;
}
ImageCache imageCache = RemoteImageApplication.getInstance()
.getImageCache();
if (imageCache.isCached(url)) {
setImageBitmap(imageCache.get(url));
} else {
// 如果內存中沒有該緩存,則從文件中進行查找.
String fileName = convertUrlToFileName(url); // 進行文件名處理
String filepath = getDirectory(fileName); // 取得緩存文件夾目錄
String pathFileName = filepath + "/" + fileName; // 組拼文件
File pathFile = new File(pathFileName);
if (!pathFile.exists()) {
try {
pathFile.createNewFile();
} catch (IOException e) {
Log.d(RemoteImageApplication.TAG, "創建圖片文件失敗:"
+ pathFileName);
}
}
Bitmap tbmp = BitmapFactory.decodeFile(pathFileName);
if (tbmp == null) {
Log.d(RemoteImageApplication.TAG, "圖片文件不存在,開始進行下載");
try {
new DownloadTask().execute(url);
} catch (RejectedExecutionException e) {
Log.d(RemoteImageApplication.TAG, "下載失敗");
}
} else {
Log.i(RemoteImageApplication.TAG, "從文件中加載圖片");
RemoteImageApplication.getInstance().getImageCache()
.put(url, tbmp);
this.setImageBitmap(tbmp);
}
updateCacheSize(pathFileName); // 進行檢測文件大小,以便於清除緩存.
}
}
privatevoid updateCacheSize(String pathFileName) {
// TODO Auto-generated method stub
updateSizeCache(pathFileName);
}
/**
* 檢查文件目錄是否超過規定的緩存大小
*
* @param fileName
*/
privatevoid updateSizeCache(String pathFileName) {
// TODO Auto-generated method stub
mCacheSize = PreferenceManager.getDefaultSharedPreferences(mContext)
.getInt(RemoteSettings.CACHE_SIZE, 100); // 讀取設置的緩存大小,前臺可以動態設置此值
if (isSDCardEnable()) {
String extStorageDirectory = Environment
.getExternalStorageDirectory().toString(); // 取得SD根路徑
String dirPath = extStorageDirectory + "/" + JAMENDO_DIR
+ "/imagecache";
File dirFile = new File(dirPath);
File[] files = dirFile.listFiles();
long dirSize = 0;
for (File file : files) {
dirSize += file.length();
}
if (dirSize > mCacheSize * MB) {
clearCache();
}
}
}
/**
* 異步下載圖片
*
* @ClassName: DownloadTask
* @author 姜濤
* @version 1.0 2012-1-15 下午5:06:21
*/
class DownloadTask extends AsyncTask<String, Void, String> {
private String mTaskUrl;
private Bitmap mBmp = null;
@Override
publicvoid onPreExecute() {
// loadDefaultImage();
super.onPreExecute();
}
@Override
public String doInBackground(String... params) {
mTaskUrl = params[0];
InputStream stream = null;
URL imageUrl;
Bitmap bmp = null;
try {
imageUrl = new URL(mTaskUrl);
try {
stream = imageUrl.openStream();
bmp = BitmapFactory.decodeStream(stream);
try {
if (bmp != null) {
mBmp = bmp;
RemoteImageApplication.getInstance()
.getImageCache().put(mTaskUrl, bmp);
Log.d(RemoteImageApplication.TAG,
"圖片緩存到application中: " + mTaskUrl);
}
} catch (NullPointerException e) {
Log.w(RemoteImageApplication.TAG, "下載失敗,圖片爲空:"
+ mTaskUrl);
}
} catch (IOException e) {
Log.w(RemoteImageApplication.TAG, "無法加載該url:" + mTaskUrl);
} finally {
try {
if (stream != null) {
stream.close();
}
} catch (IOException e) {
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
return mTaskUrl;
}
@Override
publicvoid onPostExecute(String url) {
super.onPostExecute(url);
Bitmap bmp = RemoteImageApplication.getInstance().getImageCache()
.get(url);
if (bmp == null) {
Log.w(RemoteImageApplication.TAG, "嘗試重新下載:" + url);
RemoteImageView.this.setImageUrl(url);
} else {
RemoteImageView.this.setImageBitmap(bmp);
mCurrentlyGrabbedUrl = url;
saveBmpToSd(mBmp, url);
}
}
};
/**
* 把圖片保存到本地
*
* @param bm
* @param url
*/
privatevoid saveBmpToSd(Bitmap bm, String url) {
if (bm == null) {
return;
}
if (mCacheSize == 0) {
return;
}
String filename = convertUrlToFileName(url);
String dir = getDirectory(filename);
File file = new File(dir + "/" + filename);
try {
file.createNewFile();
OutputStream outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
Log.i(RemoteImageApplication.TAG, "圖片已保存到sd卡");
} catch (FileNotFoundException e) {
Log.w(RemoteImageApplication.TAG, "無法找到文件目錄");
} catch (IOException e) {
Log.w(RemoteImageApplication.TAG, "操作文件出錯");
}
}
/**
* 組拼文件名,後綴名用dat代替,避免別人使用圖片管理器搜索出這種對於她們無用的圖片.
*
* @param url
* @return
*/
private String convertUrlToFileName(String url) {
String filename = url;
filename = filename.replace("http://", "");
filename = filename.replace("/", ".");
filename = filename.replace(":", ".");
filename = filename.replace("jpg", "dat");
filename = filename.replace("png", "dat");
return filename;
}
/**
* 返回緩存圖片所存放的文件夾
*
* @param filename
* @return
*/
private String getDirectory(String filename) {
String extStorageDirectory = Environment.getExternalStorageDirectory()
.toString(); // 取得SD根路徑
String dirPath = extStorageDirectory + "/" + JAMENDO_DIR
+ "/imagecache";
File dirFile = new File(dirPath);
if (!dirFile.exists()) {
dirFile.mkdirs();
}
return dirPath;
}
/**
* 清除緩存
*/
privatevoid clearCache() {
if (isSDCardEnable()) {
String extStorageDirectory = Environment
.getExternalStorageDirectory().toString(); // 取得SD根路徑
String dirPath = extStorageDirectory + "/" + JAMENDO_DIR
+ "/imagecache";
File dir = new File(dirPath);
File[] files = dir.listFiles(); // 取得該目錄下的所有文件
if (files == null || files.length == 0) {
return;
}
for (File file : files) {
file.delete();
}
Log.d(RemoteImageApplication.TAG, "已清除緩存:" + dirPath);
}
}
/**
* 判斷SD卡是否可用
*/
publicstaticboolean isSDCardEnable() {
return Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
}
}
本文轉自:http://lewisliu.iteye.com/blog/1346820