第6天Bitmap三級快取
阿新 • • 發佈:2018-12-26
第6天Bitmap三級快取
Bitmap三級快取
一.為什麼Bitmap三級快取?
- 沒有快取的弊端 :費流量, 載入速度慢
- 加入快取的優點: 省流量,支援離線瀏覽
二.原理
思路:
- 從記憶體獲取圖片, 如果存在, 則顯示; 如果不存在, 則從SD卡中獲取圖片
- 從SD卡中獲取圖片, 如果檔案中存在, 顯示, 並且新增到記憶體中; 否則開啟網路下載圖片
- 從網路下載圖片, 如果下載成功, 則新增到快取中, 存入SD卡, 顯示圖片
三.程式碼
(1)新增讀寫SD卡的許可權和網路許可權
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET" ></uses-permission>
(2)操作記憶體工具類:提供從記憶體中讀寫的方法,記憶體不能持久儲存,可能過一會就會被回收掉
//Lrucache儲存工具類
public class LruUtils {
//TODO 1:例項化LruCache物件
private LruCache<String,Bitmap> lruCache;
private long max=Runtime.getRuntime().maxMemory();//獲得手機的最大記憶體
public LruUtils(){
lruCache= new LruCache<String,Bitmap>((int)max/8){//給記憶體大小,一般是最大記憶體的1/8
//重寫該方法返回每個物件的大小
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
}
//TODO 2:讀圖片
public Bitmap getBitmap(String key){
return lruCache.get(key);
}
//TODO 3:存圖片
public void setBitmap(String key,Bitmap bitmap){
lruCache.put(key,bitmap);
}
}
(3)操作SD卡工具類:提供從SD卡中讀寫的方法
//TODO 讀圖片和寫圖片
public class SDUtils {
//TODO 1:存圖片:bitmap.compress()
public static void setBitmap(String name,Bitmap bitmap){
//獲取路徑儲存圖片
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File file=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file1=new File(file,name);
//儲存圖片:bitmap物件---->SD卡
try {
//引數一 圖片的格式 引數二 圖片質量 0-100 引數三:輸出流
bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file1));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
//TODO 2:讀圖片:BitmapFactory.decodeFile()
public static Bitmap getBitmap(String name){
//獲取路徑儲存圖片
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File file=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file1=new File(file,name);
//讀取圖片:SD卡-----Bitmap
return BitmapFactory.decodeFile(file1.getAbsolutePath());
}
return null;
}
}
(3)網路下載工具類:提供下載圖片的方法
//網路獲取工具類
public class NetUtils {
//TODO 獲取網路圖片
public static Bitmap getBitmap(String url) throws ExecutionException, InterruptedException {
return new MyTask().execute(url).get();//get方法獲取執行完畢返回的結果Bitmap物件
}
static class MyTask extends AsyncTask<String,String,Bitmap>{
@Override
protected Bitmap doInBackground(String... strings) {
String imageUrl = strings[0];
HttpURLConnection conn = null;
try {
URL url = new URL(imageUrl);
conn = (HttpURLConnection) url.openConnection(); // 開啟連線
conn.setReadTimeout(5000); // 設定讀取超時時間
conn.setConnectTimeout(5000); // 設定連線超時時間
conn.setRequestMethod("GET"); // 設定請求方式
if (conn.getResponseCode() == 200) {
InputStream is = conn.getInputStream(); // 獲取流資料
Bitmap bitmap = BitmapFactory.decodeStream(is); // 將流資料轉成Bitmap物件
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.disconnect(); // 斷開連線
}
}
return null;
}
}
}
(4)使用三個工具類完成Bitmap的三級快取
/*
一。三級快取
1.執行記憶體:LruUtils(建立例項,存,讀)
2.檔案SD
3.網路請求
* */
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
private LruUtils lruUtils= new LruUtils();//TODO 注意:同一個記憶體物件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView=findViewById(R.id.image);
}
public void click(View view) throws ExecutionException, InterruptedException {
//TODO 1:先從執行記憶體中讀取
Bitmap bitmap=lruUtils.getBitmap("宋定行");
if(bitmap!=null){//有圖片
imageView.setImageBitmap(bitmap);
Toast.makeText(this, "圖片來自記憶體", Toast.LENGTH_SHORT).show();
}else{
//TODO 2:若記憶體沒有去SD卡
bitmap=SDUtils.getBitmap("宋定行.jpg");
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
Toast.makeText(this, "圖片從SD卡來de", Toast.LENGTH_SHORT).show();
//向記憶體中儲存一下
lruUtils.setBitmap("宋定行",bitmap);
}else{
//TODO 3:執行記憶體和SD卡都沒有圖片,接下來網路獲取
bitmap=NetUtils.getBitmap("http://upload.cbg.cn/2015/1126/1448506973451.jpg");
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
Toast.makeText(this, "圖片從網路獲取", Toast.LENGTH_SHORT).show();
//將圖片再放到SD卡和記憶體中
SDUtils.setBitmap("宋定行.jpg",bitmap);
lruUtils.setBitmap("宋定行",bitmap);
}else{
Toast.makeText(this, "窮玩意檢查下你的網咖", Toast.LENGTH_SHORT).show();
}
}
}
}
}