ImageLoader是android開發中常用到的圖片快取技術。本文通過閱讀《Android原始碼設計模式解析與實戰》後,瞭解到一個程式的健壯性,可擴充性是十分重要的。原始碼設計均來自於《Android原始碼設計模式解析與實戰》: 1.首先定義ImageCache介面,實現圖片的快取和提取兩種方法。
public interface ImageCache {
void put(String url,Bitmap bitmap);
Bitmap get(String url);
}
複製程式碼
2.分別實現記憶體快取(MemoryCache),sd卡快取(DiskCache)和雙快取(DoubleCache)策略,其均實現ImageCache介面。
public class MemoryCache implements ImageCache {
LruCache<String, Bitmap> mMemoryCache;
public MemoryCache(){
initMemoryCache();
}
private void initMemoryCache() {
//計算可使用的最大記憶體
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
//取四分之一的可用記憶體作為快取
final int CacheSize = maxMemory / 4;
mMemoryCache = new LruCache<String, Bitmap>(CacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
//圖片的寬高之積/1024(儲存的應該是圖片的大小)
return value.getRowBytes() * value.getHeight() / 1024;
}
};
}
@Override
public void put(String url, Bitmap bitmap) {
mMemoryCache.put(url,bitmap);
}
@Override
public Bitmap get(String url) {
return mMemoryCache.get(url);
}
}
複製程式碼
public class DiskCache implements ImageCache{
static String cacheDir = "sdcard/cache/";
@Override
public void put(String url, Bitmap bitmap) {
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(cacheDir + url);
bitmap.compress(Bitmap.CompressFormat.PNG,100,fileOutputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if(fileOutputStream != null){
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Override
public Bitmap get(String url) {
return BitmapFactory.decodeFile(cacheDir + url);
}
}
複製程式碼
public class DoubleCache implements ImageCache{
ImageCache mMemmoryCache = new MemoryCache();
ImageCache mDiskCache = new DiskCache();
@Override
public void put(String url, Bitmap bitmap) {
mMemmoryCache.put(url,bitmap);
mDiskCache.put(url,bitmap);
}
@Override
public Bitmap get(String url) {
Bitmap bitmap = mMemmoryCache.get(url);
if(bitmap == null){
bitmap = mDiskCache.get(url);
}
return bitmap;
}
}
複製程式碼
3.建立ImageLoader類
public class ImageLoader {
//記憶體快取
ImageCache mImageCache = new MemoryCache();
//執行緒池,執行緒數量為CPU的數量
ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public void setImageCache(ImageCache cache){
mImageCache = cache;
}
public void displayImage(final String url, final ImageView imageView) {
//判斷該url的圖片是否在快取中存在,存在則直接顯示在imageview上
Bitmap bitmap = mImageCache.get(url);
if(bitmap != null){
imageView.setImageBitmap(bitmap);
return;
}
//圖片沒快取,線上程池中下載
submitLoadRequest(url,imageView);
}
private void submitLoadRequest(final String url, final ImageView imageView) {
imageView.setTag(url);
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap = downloadImage(url);
if (bitmap == null) {
return;
}
if (imageView.getTag().equals(url)) {
imageView.setImageBitmap(bitmap);
}
mImageCache.put(url, bitmap);
}
});
}
private Bitmap downloadImage(String imageurl) {
Bitmap bitmap = null;
try {
URL url = new URL(imageurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
conn.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
複製程式碼
在ImageLoader類中新增setImageCache()方法,使用者可以通過此方法決定快取的方式為以上3種的哪一種。
4.在Activity上進行宣告,使用。
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
private ImageLoader imageLoader;
private String url = "http://bmob-cdn-11151.b0.upaiyun.com/2017/06/04/3cdfbcc8400de13c8027b5513d469637.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
imageView = (ImageView)findViewById(R.id.imageView);
imageLoader = new ImageLoader();
//使用記憶體快取
imageLoader.setImageCache(new MemoryCache());
//使用sd卡快取
imageLoader.setImageCache(new DiskCache());
//使用doubleCache快取
imageLoader.setImageCache(new DoubleCache());
//使用自定義的方法快取
imageLoader.setImageCache(new ImageCache() {
@Override
public void put(String url, Bitmap bitmap) {
}
@Override
public Bitmap get(String url) {
return null;
}
});
imageLoader.displayImage(url,imageView);
}
}
複製程式碼
本方法高度內聚,低耦合,在使用過程中,分別使用3中不同的快取策略,使複雜的程式碼進行分離,在出現問題時,便於方便的修改,不會影響到其他的程式碼功能,實現抽象介面的方法還允許開發者使用自定義的快取策略,可擴充性高。
理解這種程式設計時十分必要的,在以後的開發中要時刻考慮自己程式的健壯性,可擴充性,高內聚低耦合。