Android圖片三級(jí)緩存開發(fā)
因?yàn)槟壳肮こ虩o法使用第三方,只能搞一個(gè)三級(jí)緩存了三級(jí)緩存分為內(nèi)存緩存,本地緩存,網(wǎng)絡(luò)緩存;緩存的步驟依次是網(wǎng)絡(luò),內(nèi)存,本地,然后取的順序?yàn)閮?nèi)存,本地,網(wǎng)絡(luò)。在加載圖片時(shí)引用時(shí)盡量采用弱引用避免出現(xiàn)圖片過多產(chǎn)生OOM.。
1、內(nèi)存緩存,android為我們提供LruCache=其中維護(hù)著一個(gè)LinkedHashMap。LruCache可以用來存儲(chǔ)各種類型的數(shù)據(jù),我們?cè)O(shè)置它的大小,一般是系統(tǒng)最大存儲(chǔ)空間的1/8.
public class MemoryCacheUtil {
private LruCache<String, Bitmap> lruCache;
public MemoryCacheUtil(){
int maxSize = (int) (Runtime.getRuntime().maxMemory()/8);
// 一般獲取當(dāng)前應(yīng)用的最大內(nèi)存的1/8作為LruCache的容量
lruCache = new LruCache<String, Bitmap>(maxSize){
// 設(shè)置當(dāng)前添加的圖片的大小
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight();
}
};
}
// 從內(nèi)存緩存取圖片
public Bitmap getBitmap(String url){
return lruCache.get(url);
}
// 在內(nèi)存緩存存圖片
public void putBitmap(String url,Bitmap bitmap){
lruCache.put(url, bitmap);
}
}
2、本地緩存根據(jù)url,獲取本地文件,把url進(jìn)行md5加密,作為文件名,保證文件的正確性.
MD5加密工具類
public class MD5Encoder {
public static String encode(String string) throws Exception {
byte[] hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
StringBuilder hex = new StringBuilder(hash.length * 2);
for (byte b : hash) {
if ((b & 0xFF) < 0x10) {
hex.append("0");
}
hex.append(Integer.toHexString(b & 0xFF));
}
return hex.toString();
}
}
本地緩存
public class LocalCacheUtil {
private String CACHE_URl;
private MemoryCacheUtil memoryCacheUtil;
public LocalCacheUtil(MemoryCacheUtil memoryCacheUtil){
// 初始化本地存儲(chǔ)的路徑
CACHE_URl = Environment.getExternalStorageDirectory().getAbsoluteFile()+ "/test";
this.memoryCacheUtil = memoryCacheUtil;
}
// 從本地sdcard取圖片
public Bitmap getBitmap(String url){
// 根據(jù)url,獲取本地文件,把url進(jìn)行md5加密,作為文件名
try {
String fileName = MD5Encoder.encode(url);
File file = new File(CACHE_URl, fileName);
if(file.exists()){// 判斷當(dāng)前文件是否存在
// 把當(dāng)前文件轉(zhuǎn)換成Bitmap對(duì)象
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
// 需往內(nèi)存中存一份
memoryCacheUtil.putBitmap(url, bitmap);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 往本地存圖片的方法
public void saveBitmap(String url,Bitmap bitmap){
try {
String fileName = MD5Encoder.encode(url);
File file = new File(CACHE_URl, fileName);
// 判斷是否需要?jiǎng)?chuàng)建父目錄
File parentFile = file.getParentFile();
if(!parentFile.exists()){
parentFile.mkdirs();
}
// 把Bitmap對(duì)象保存到文件中 質(zhì)量越高壓縮速度越慢
OutputStream stream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, stream);//第一個(gè)參數(shù)可以設(shè)置圖片格式,第二個(gè)圖片壓縮質(zhì)量,第三個(gè)為圖片輸出流
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、網(wǎng)絡(luò)緩存使用異步加載AsyncTask,使用其有二種原因:
1.doInBackground運(yùn)行在子線程,做網(wǎng)絡(luò)請(qǐng)求耗時(shí)操作,避免主線程堵塞;
2.onPreExecute和onPostExecute便于更新UI提高用戶體驗(yàn)。
public class NetCacheUtil {
private MemoryCacheUtil memoryCacheUtil;
private LocalCacheUtil localCacheUtil;
private ListView lv_image_list;
public NetCacheUtil(MemoryCacheUtil memoryCacheUtil,LocalCacheUtil localCacheUtil){
this.memoryCacheUtil = memoryCacheUtil;
this.localCacheUtil = localCacheUtil;
}
public void display(ImageView imageView ,String url, ListView lv_image_list){
this.lv_image_list = lv_image_list;
new MyAsyncTask(imageView).execute(new Object[]{url,imageView});
}
class MyAsyncTask extends AsyncTask<Object, Void, Bitmap>{
private ImageView imageView;
private int position;
public MyAsyncTask(ImageView imageView2) {
position = (Integer) imageView2.getTag();
}
// 運(yùn)行在主線程,做準(zhǔn)備操作,在doInBackground之前,可以放置加載條提高用戶體驗(yàn)
@Override
protected void onPreExecute() {
super.onPreExecute();
}
// 運(yùn)行在子線程,做耗時(shí)操作
@Override
protected Bitmap doInBackground(Object... params) {
// 獲取url,下載圖片
String url = (String) params[0];
// 獲取ImageView
imageView = (ImageView) params[1];
try {
// 下載圖片
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.connect();// 連接網(wǎng)絡(luò)
// 獲取響應(yīng)碼
int resCode = conn.getResponseCode();
if(resCode==200){// 訪問成功
// 把服務(wù)器返回的輸入流轉(zhuǎn)換成Bitmap對(duì)象
Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream());
// 保存到本地和內(nèi)存
memoryCacheUtil.putBitmap(url, bitmap);
localCacheUtil.saveBitmap(url, bitmap);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 運(yùn)行在主線程,更新界面,在doInBackground之后
@Override
protected void onPostExecute(Bitmap result) {
// 判斷線程開始時(shí),那個(gè)位置是否還在Listview中
ImageView view = (ImageView) lv_image_list.findViewWithTag(position);
if(view!=null){
view.setImageBitmap(result);
}
super.onPostExecute(result);
}
}
}
4、封裝三級(jí)緩存形成ImageUtil,因內(nèi)存緩存中取速度較快,所以先從內(nèi)存緩存中取,取不到->本地緩存中取,取不到->網(wǎng)絡(luò)緩存中取。
public class ImageUtils {
private MemoryCacheUtil memoryCacheUtil;
private LocalCacheUtil localCacheUtil;
private NetCacheUtil netCacheUtil;
public ImageUtils(){
memoryCacheUtil = new MemoryCacheUtil();
localCacheUtil = new LocalCacheUtil(memoryCacheUtil);
netCacheUtil = new NetCacheUtil(memoryCacheUtil,localCacheUtil);
}
public void display(ImageView imageView, String url, ListView lv_photo_list) {
Bitmap bitmap = null;
/**
* 因內(nèi)存緩存中取速度較快
* 內(nèi)存緩存中取,取不到->本地緩存中取,取不到->網(wǎng)絡(luò)緩存中取
*/
bitmap = memoryCacheUtil.getBitmap(url);//從內(nèi)存緩存取圖片
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
return;
}
bitmap = localCacheUtil.getBitmap(url);//從本地緩存取圖片
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
return;
}
// 開啟線程訪問網(wǎng)絡(luò),下載圖片,并且展示
netCacheUtil.display(imageView, url,lv_photo_list);
}
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 淺談Android 中圖片的三級(jí)緩存策略
- Android圖片三級(jí)緩存的原理及其實(shí)現(xiàn)
- Android中Rxjava實(shí)現(xiàn)三級(jí)緩存的兩種方式
- 詳解Android 圖片的三級(jí)緩存及圖片壓縮
- Android中圖片的三級(jí)緩存機(jī)制
- Android圖片三級(jí)緩存策略(網(wǎng)絡(luò)、本地、內(nèi)存緩存)
- Android使用緩存機(jī)制實(shí)現(xiàn)文件下載及異步請(qǐng)求圖片加三級(jí)緩存
- Android實(shí)現(xiàn)圖片異步請(qǐng)求加三級(jí)緩存
- android中圖片的三級(jí)緩存cache策略(內(nèi)存/文件/網(wǎng)絡(luò))
- Android三級(jí)緩存原理講解
相關(guān)文章
ListView實(shí)現(xiàn)聊天列表之處理不同數(shù)據(jù)項(xiàng)
這篇文章主要為大家詳細(xì)介紹了ListView實(shí)現(xiàn)聊天列表之處理不同數(shù)據(jù)項(xiàng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
Android自定義有限制區(qū)域的圖例角度自識(shí)別涂鴉工具類完結(jié)篇
這篇文章主要為大家介紹了Android自定義有限制區(qū)域的圖例角度自識(shí)別涂鴉工具類完結(jié)篇,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Android 中 SwipeLayout一個(gè)展示條目底層菜單的側(cè)滑控件源碼解析
這篇文章主要介紹了Android 中 SwipeLayout一個(gè)展示條目底層菜單的側(cè)滑控件源碼解析,需要的朋友可以參考下2016-12-12
Android中利用C++處理Bitmap對(duì)象的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄狝ndroid中利用C++處理Bitmap對(duì)象的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03
Android中如何指定SnackBar在屏幕的位置及小問題解決
這篇文章主要給大家介紹了關(guān)于Android中如何指定SnackBar在屏幕的位置,以及一個(gè)小問題解決的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03
Android BottomNavigationView結(jié)合ViewPager實(shí)現(xiàn)底部導(dǎo)航欄步驟詳解
這篇文章主要介紹了Android BottomNavigationView結(jié)合ViewPager實(shí)現(xiàn)底部導(dǎo)航欄步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-02-02
Android實(shí)現(xiàn)三角形氣泡效果方式匯總
這篇文章主要介紹了Android實(shí)現(xiàn)三角形氣泡效果方式匯總,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Android TextView 去掉自適應(yīng)默認(rèn)的fontpadding的實(shí)現(xiàn)方法
這篇文章主要介紹了Android TextView 去掉自適應(yīng)默認(rèn)的fontpadding的實(shí)現(xiàn)方法的相關(guān)資料,希望通過本文大家能夠掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09

