在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Android/ 緩存Bitmap
檢測(cè)常用的手勢(shì)
優(yōu)化layout的層級(jí)
用戶輸入
管理應(yīng)用的內(nèi)存
聯(lián)系人信息
開發(fā)輔助程序
Android多媒體
添加語音功能
顯示位置地址
提供向下與橫向?qū)Ш?/span>
支持游戲控制器
訪問可穿戴數(shù)據(jù)層
處理多點(diǎn)觸控手勢(shì)
全屏沉浸式應(yīng)用
為多線程創(chuàng)建管理器
數(shù)據(jù)保存
Intent的發(fā)送
更新Notification
優(yōu)化下載以高效地訪問網(wǎng)絡(luò)
打印
打包可穿戴應(yīng)用
接收從其他App傳送來的數(shù)據(jù)
發(fā)送與接收消息
建立靈活動(dòng)態(tài)的UI
處理鍵盤輸入
Building a Work Policy Controller
建立測(cè)試環(huán)境
創(chuàng)建表盤
分享文件
顯示Notification進(jìn)度
實(shí)現(xiàn)自適應(yīng)UI流(Flows)
使用設(shè)備管理策略增強(qiáng)安全性
使用能感知版本的組件
執(zhí)行網(wǎng)絡(luò)操作
建立文件分享
添加移動(dòng)
更新你的Security Provider來對(duì)抗SSL漏洞利用
支持鍵盤導(dǎo)航
創(chuàng)建和監(jiān)視地理圍欄
發(fā)送并同步數(shù)據(jù)
使用BigView樣式
無線連接設(shè)備
提供向上導(dǎo)航與歷史導(dǎo)航
最小化定期更新造成的影響
實(shí)現(xiàn)向下的導(dǎo)航
支持不同的屏幕大小
Android 可穿戴應(yīng)用
添加動(dòng)畫
顯示聯(lián)系人頭像
使用OpenGL ES顯示圖像
處理輸入法可見性
分享文件
保持設(shè)備喚醒
淡化系統(tǒng)Bar
使用NFC分享文件
保存到Preference
Android聯(lián)系人信息與位置信息
創(chuàng)建標(biāo)準(zhǔn)的網(wǎng)絡(luò)請(qǐng)求
使用Drawables
管理Bitmap的內(nèi)存使用
管理Activity的生命周期
按需加載視圖
傳輸資源
為可穿戴設(shè)備創(chuàng)建自定義UI
在一個(gè)線程中執(zhí)行一段特定的代碼
性能優(yōu)化
隱藏導(dǎo)航欄
創(chuàng)建目錄瀏覽器
為多種大小的屏幕進(jìn)行規(guī)劃
View間漸變
使用觸摸手勢(shì)
高效加載大圖
使用CursorLoader在后臺(tái)加載數(shù)據(jù)
創(chuàng)建抽屜式導(dǎo)航(navigation drawer)
管理音頻焦點(diǎn)
創(chuàng)建后臺(tái)服務(wù)
創(chuàng)建功能測(cè)試
創(chuàng)建使用Material Design的應(yīng)用
停止與重啟Activity
添加一個(gè)簡(jiǎn)便的分享功能
啟動(dòng)Activity時(shí)保留導(dǎo)航
TV應(yīng)用清單
創(chuàng)建向后兼容的UI
?# 優(yōu)化自定義View
創(chuàng)建單元測(cè)試
在UI上顯示Bitmap
建立OpenGL ES的環(huán)境
構(gòu)建表盤服務(wù)
JNI Tips
建立搜索界面
實(shí)現(xiàn)自定義View的繪制
使用HTTPS與SSL
按需操控BroadcastReceiver
分享簡(jiǎn)單的數(shù)據(jù)
繪制形狀
Android位置信息
創(chuàng)建并運(yùn)行可穿戴應(yīng)用
執(zhí)行 Sync Adpater
獲取最后可知位置
創(chuàng)建 Android 項(xiàng)目
實(shí)現(xiàn)高效的導(dǎo)航
退出全屏的Activity
創(chuàng)建Card
兼容音頻輸出設(shè)備
同步數(shù)據(jù)單元
傳輸數(shù)據(jù)時(shí)避免消耗大量電量
保存到文件
緩存Bitmap
提供配置 Activity
調(diào)度重復(fù)的鬧鐘
實(shí)現(xiàn)輔助功能
重復(fù)的下載是冗余的
隱藏狀態(tài)欄
實(shí)現(xiàn)自定義的網(wǎng)絡(luò)請(qǐng)求
規(guī)劃界面和他們之間的關(guān)系
使用Sync Adapter傳輸數(shù)據(jù)
TV應(yīng)用內(nèi)搜索
響應(yīng)觸摸事件
使用Google Cloud Messaging(已廢棄)
控制相機(jī)
Android網(wǎng)絡(luò)連接與云服務(wù)
請(qǐng)求分享一個(gè)文件
處理TV硬件
響應(yīng)UI可見性的變化
使用網(wǎng)絡(luò)服務(wù)發(fā)現(xiàn)
指定輸入法類型
優(yōu)化電池壽命
創(chuàng)建TV應(yīng)用
獲取聯(lián)系人列表
拖拽與縮放
啟動(dòng)與停止線程池中的線程
創(chuàng)建 Sync Adpater
使用 WiFi P2P 服務(wù)發(fā)現(xiàn)
開始使用Material Design
代理至新的APIs
使用include標(biāo)簽重用layouts
使得View可交互
高效顯示Bitmap
創(chuàng)建企業(yè)級(jí)應(yīng)用
Fragments之間的交互
創(chuàng)建與執(zhí)行測(cè)試用例
綜合:設(shè)計(jì)我們的樣例 App
繪制表盤
建立簡(jiǎn)單的用戶界面
自定義動(dòng)畫
開發(fā)輔助服務(wù)
避免出現(xiàn)程序無響應(yīng)ANR(Keeping Your App Responsive)
使用ViewPager實(shí)現(xiàn)屏幕滑動(dòng)
設(shè)計(jì)高效的導(dǎo)航
Android分享操作(Building Apps with Content Sharing)
提供向后的導(dǎo)航
保持向下兼容
創(chuàng)建TV播放應(yīng)用
縮放View
使用 WiFi 建立 P2P 連接
Android后臺(tái)任務(wù)
連接到網(wǎng)絡(luò)
為 Notification 添加頁面
使TV應(yīng)用是可被搜索的
添加Action Bar
使用Material的主題
啟動(dòng)另一個(gè)Activity
顯示正在播放卡片
適配不同的系統(tǒng)版本
輕松錄制視頻
創(chuàng)建可穿戴的應(yīng)用
創(chuàng)建自定義的布局
重新創(chuàng)建Activity
使用CursorLoader執(zhí)行查詢?nèi)蝿?wù)
使用舊的APIs實(shí)現(xiàn)新API的效果
使用備份API
安全要點(diǎn)
Android入門基礎(chǔ):從這里開始
保存并搜索數(shù)據(jù)
根據(jù)網(wǎng)絡(luò)連接類型來調(diào)整下載模式
使用Tabs創(chuàng)建Swipe視圖
SMP(Symmetric Multi-Processor) Primer for Android
解析 XML 數(shù)據(jù)
使用 Volley 傳輸網(wǎng)絡(luò)數(shù)據(jù)
建立ActionBar
Android交互設(shè)計(jì)
使用Intent修改聯(lián)系人信息
增加搜索功能
輕松拍攝照片
定義形狀
測(cè)試你的Activity
在 Notifcation 中接收語音輸入
與其他應(yīng)用的交互
管理系統(tǒng)UI
追蹤手勢(shì)移動(dòng)
Android界面設(shè)計(jì)
執(zhí)行 Android 程序
顯示確認(rèn)界面
創(chuàng)建Lists與Cards
打印HTML文檔
創(chuàng)建TV應(yīng)用
為多屏幕設(shè)計(jì)
定義Shadows與Clipping視圖
使用Fragment建立動(dòng)態(tài)UI
接收Activity返回的結(jié)果
布局變更動(dòng)畫
定位常見的問題
自定義ActionBar的風(fēng)格
定義Layouts
發(fā)送簡(jiǎn)單的網(wǎng)絡(luò)請(qǐng)求
啟動(dòng)與銷毀Activity
與UI線程通信
非UI線程處理Bitmap
創(chuàng)建TV布局
提升Layout的性能
報(bào)告任務(wù)執(zhí)行狀態(tài)
判斷并監(jiān)測(cè)網(wǎng)絡(luò)連接狀態(tài)
兼容不同的設(shè)備
處理按鍵動(dòng)作
優(yōu)化性能和電池使用時(shí)間
給其他App發(fā)送簡(jiǎn)單的數(shù)據(jù)
Implementing App Restrictions
向后臺(tái)服務(wù)發(fā)送任務(wù)請(qǐng)求
展示Card翻轉(zhuǎn)動(dòng)畫
管理ViewGroup中的觸摸事件
兼容不同的屏幕密度
通過藍(lán)牙進(jìn)行調(diào)試
為可穿戴設(shè)備創(chuàng)建Notification
控制音量與音頻播放
獲取聯(lián)系人詳情
在表盤上顯示信息
提供向上的導(dǎo)航
滾動(dòng)手勢(shì)動(dòng)畫
幫助用戶在TV上找到內(nèi)容
創(chuàng)建TV導(dǎo)航
為索引指定App內(nèi)容
ActionBar的覆蓋疊加
Android Wear 上的位置檢測(cè)
保護(hù)安全與隱私的最佳策略
Ensuring Compatibility with Managed Profiles
解決云同步的保存沖突
獲取位置更新
創(chuàng)建List
測(cè)試程序
管理網(wǎng)絡(luò)的使用情況
為App內(nèi)容開啟深度鏈接
推薦TV內(nèi)容
建立一個(gè)Notification
管理音頻播放
設(shè)計(jì)表盤
拍照
處理控制器輸入動(dòng)作
判斷并監(jiān)測(cè)設(shè)備的底座狀態(tài)與類型
處理查詢的結(jié)果
保存到數(shù)據(jù)庫(kù)
支持多個(gè)游戲控制器
創(chuàng)建 Stub Content Provider
使得ListView滑動(dòng)順暢
處理數(shù)據(jù)層的事件
創(chuàng)建TV應(yīng)用的第一步
使得你的App內(nèi)容可被Google搜索
將 Notification 放成一疊
創(chuàng)建 Stub 授權(quán)器
暫停與恢復(fù)Activity
管理設(shè)備的喚醒狀態(tài)
Android圖像與動(dòng)畫
打印照片
云同步
創(chuàng)建TV直播應(yīng)用
為Notification賦加可穿戴特性
提供一個(gè)Card視圖
建立請(qǐng)求隊(duì)列(RequestQueue)
適配不同的語言
創(chuàng)建詳情頁
測(cè)試UI組件
接收其他設(shè)備的文件
創(chuàng)建自定義View
建立第一個(gè)App
創(chuàng)建2D Picker
監(jiān)測(cè)電池的電量與充電狀態(tài)
打印自定義文檔
抽象出新的APIs
通知提示用戶
獲取文件信息
運(yùn)用投影與相機(jī)視角
在IntentService中執(zhí)行后臺(tái)任務(wù)
多線程操作
創(chuàng)建一個(gè)Fragment
添加Action按鈕
在不同的 Android 系統(tǒng)版本支持控制器
維護(hù)兼容性
發(fā)送文件給其他設(shè)備
創(chuàng)建TV游戲應(yīng)用
創(chuàng)建自定義的View類
代碼性能優(yōu)化建議
Intent過濾
適配不同的屏幕

緩存Bitmap

編寫:kesenhoo - 原文:http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

將單個(gè)Bitmap加載到UI是簡(jiǎn)單直接的,但是如果我們需要一次性加載大量的圖片,事情則會(huì)變得復(fù)雜起來。在大多數(shù)情況下(例如在使用ListView,GridView或ViewPager時(shí)),屏幕上的圖片和因滑動(dòng)將要顯示的圖片的數(shù)量通常是沒有限制的。

通過循環(huán)利用子視圖可以緩解內(nèi)存的使用,垃圾回收器也會(huì)釋放那些不再需要使用的Bitmap。這些機(jī)制都非常好,但是為了保證一個(gè)流暢的用戶體驗(yàn),我們希望避免在每次屏幕滑動(dòng)回來時(shí),都要重復(fù)處理那些圖片。內(nèi)存與磁盤緩存通常可以起到輔助作用,允許控件可以快速地重新加載那些處理過的圖片。

這一課會(huì)介紹在加載多張Bitmap時(shí)使用內(nèi)存緩存與磁盤緩存來提高響應(yīng)速度與UI流暢度。

使用內(nèi)存緩存(Use a Memory Cache)

內(nèi)存緩存以花費(fèi)寶貴的程序內(nèi)存為前提來快速訪問位圖。LruCache類(在API Level 4的Support Library中也可以找到)特別適合用來緩存Bitmaps,它使用一個(gè)強(qiáng)引用(strong referenced)的LinkedHashMap保存最近引用的對(duì)象,并且在緩存超出設(shè)置大小的時(shí)候剔除(evict)最近最少使用到的對(duì)象。

Note: 在過去,一種比較流行的內(nèi)存緩存實(shí)現(xiàn)方法是使用軟引用(SoftReference)或弱引用(WeakReference)對(duì)Bitmap進(jìn)行緩存,然而我們并不推薦這樣的做法。從Android 2.3 (API Level 9)開始,垃圾回收機(jī)制變得更加頻繁,這使得釋放軟(弱)引用的頻率也隨之增高,導(dǎo)致使用引用的效率降低很多。而且在Android 3.0 (API Level 11)之前,備份的Bitmap會(huì)存放在Native Memory中,它不是以可預(yù)知的方式被釋放的,這樣可能導(dǎo)致程序超出它的內(nèi)存限制而崩潰。

為了給LruCache選擇一個(gè)合適的大小,需要考慮到下面一些因素:

  • 應(yīng)用剩下了多少可用的內(nèi)存?
  • 多少?gòu)垐D片會(huì)同時(shí)呈現(xiàn)到屏幕上?有多少圖片需要準(zhǔn)備好以便馬上顯示到屏幕?
  • 設(shè)備的屏幕大小與密度是多少?一個(gè)具有特別高密度屏幕(xhdpi)的設(shè)備,像Galaxy Nexus會(huì)比Nexus S(hdpi)需要一個(gè)更大的緩存空間來緩存同樣數(shù)量的圖片。
  • Bitmap的尺寸與配置是多少,會(huì)花費(fèi)多少內(nèi)存?
  • 圖片被訪問的頻率如何?是其中一些比另外的訪問更加頻繁嗎?如果是,那么我們可能希望在內(nèi)存中保存那些最常訪問的圖片,或者根據(jù)訪問頻率給Bitmap分組,為不同的Bitmap組設(shè)置多個(gè)LruCache對(duì)象。
  • 是否可以在緩存圖片的質(zhì)量與數(shù)量之間尋找平衡點(diǎn)?某些時(shí)候保存大量低質(zhì)量的Bitmap會(huì)非常有用,加載更高質(zhì)量圖片的任務(wù)可以交給另外一個(gè)后臺(tái)線程。

通常沒有指定的大小或者公式能夠適用于所有的情形,我們需要分析實(shí)際的使用情況后,提出一個(gè)合適的解決方案。緩存太小會(huì)導(dǎo)致額外的花銷卻沒有明顯的好處,緩存太大同樣會(huì)導(dǎo)致java.lang.OutOfMemory的異常,并且使得你的程序只留下小部分的內(nèi)存用來工作(緩存占用太多內(nèi)存,導(dǎo)致其他操作會(huì)因?yàn)閮?nèi)存不夠而拋出異常)。

下面是一個(gè)為Bitmap建立LruCache的示例:

private LruCache<String, Bitmap> mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Get max available VM memory, exceeding this amount will throw an
    // OutOfMemory exception. Stored in kilobytes as LruCache takes an
    // int in its constructor.
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = maxMemory / 8;

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in kilobytes rather than
            // number of items.
            return bitmap.getByteCount() / 1024;
        }
    };
    ...
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }
}

public Bitmap getBitmapFromMemCache(String key) {
    return mMemoryCache.get(key);
}

Note:在上面的例子中, 有1/8的內(nèi)存空間被用作緩存。 這意味著在常見的設(shè)備上(hdpi),最少大概有4MB的緩存空間(32/8)。如果一個(gè)填滿圖片的GridView控件放置在800x480像素的手機(jī)屏幕上,大概會(huì)花費(fèi)1.5MB的緩存空間(800x480x4 bytes),因此緩存的容量大概可以緩存2.5頁的圖片內(nèi)容。

當(dāng)加載Bitmap顯示到ImageView 之前,會(huì)先從LruCache 中檢查是否存在這個(gè)Bitmap。如果確實(shí)存在,它會(huì)立即被用來顯示到ImageView上,如果沒有找到,會(huì)觸發(fā)一個(gè)后臺(tái)線程去處理顯示該Bitmap任務(wù)。

public void loadBitmap(int resId, ImageView imageView) {
    final String imageKey = String.valueOf(resId);

    final Bitmap bitmap = getBitmapFromMemCache(imageKey);
    if (bitmap != null) {
        mImageView.setImageBitmap(bitmap);
    } else {
        mImageView.setImageResource(R.drawable.image_placeholder);
        BitmapWorkerTask task = new BitmapWorkerTask(mImageView);
        task.execute(resId);
    }
}

上面的程序中 BitmapWorkerTask 需要把解析好的Bitmap添加到內(nèi)存緩存中:

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
    ...
    // Decode image in background.
    @Override
    protected Bitmap doInBackground(Integer... params) {
        final Bitmap bitmap = decodeSampledBitmapFromResource(
                getResources(), params[0], 100, 100));
        addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);
        return bitmap;
    }
    ...
}

使用磁盤緩存(Use a Disk Cache)

內(nèi)存緩存能夠提高訪問最近用過的Bitmap的速度,但是我們無法保證最近訪問過的Bitmap都能夠保存在緩存中。像類似GridView等需要大量數(shù)據(jù)填充的控件很容易就會(huì)用盡整個(gè)內(nèi)存緩存。另外,我們的應(yīng)用可能會(huì)被類似打電話等行為而暫停并退到后臺(tái),因?yàn)楹笈_(tái)應(yīng)用可能會(huì)被殺死,那么內(nèi)存緩存就會(huì)被銷毀,里面的Bitmap也就不存在了。一旦用戶恢復(fù)應(yīng)用的狀態(tài),那么應(yīng)用就需要重新處理那些圖片。

磁盤緩存可以用來保存那些已經(jīng)處理過的Bitmap,它還可以減少那些不再內(nèi)存緩存中的Bitmap的加載次數(shù)。當(dāng)然從磁盤讀取圖片會(huì)比從內(nèi)存要慢,而且由于磁盤讀取操作時(shí)間是不可預(yù)期的,讀取操作需要在后臺(tái)線程中處理。

Note:如果圖片會(huì)被更頻繁的訪問,使用ContentProvider或許會(huì)更加合適,比如在圖庫(kù)應(yīng)用中。

這一節(jié)的范例代碼中使用了一個(gè)從Android源碼中剝離出來的DiskLruCache。改進(jìn)過的范例代碼在已有內(nèi)存緩存的基礎(chǔ)上增加磁盤緩存的功能。

private DiskLruCache mDiskLruCache;
private final Object mDiskCacheLock = new Object();
private boolean mDiskCacheStarting = true;
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
private static final String DISK_CACHE_SUBDIR = "thumbnails";

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Initialize memory cache
    ...
    // Initialize disk cache on background thread
    File cacheDir = getDiskCacheDir(this, DISK_CACHE_SUBDIR);
    new InitDiskCacheTask().execute(cacheDir);
    ...
}

class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
    @Override
    protected Void doInBackground(File... params) {
        synchronized (mDiskCacheLock) {
            File cacheDir = params[0];
            mDiskLruCache = DiskLruCache.open(cacheDir, DISK_CACHE_SIZE);
            mDiskCacheStarting = false; // Finished initialization
            mDiskCacheLock.notifyAll(); // Wake any waiting threads
        }
        return null;
    }
}

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
    ...
    // Decode image in background.
    @Override
    protected Bitmap doInBackground(Integer... params) {
        final String imageKey = String.valueOf(params[0]);

        // Check disk cache in background thread
        Bitmap bitmap = getBitmapFromDiskCache(imageKey);

        if (bitmap == null) { // Not found in disk cache
            // Process as normal
            final Bitmap bitmap = decodeSampledBitmapFromResource(
                    getResources(), params[0], 100, 100));
        }

        // Add final bitmap to caches
        addBitmapToCache(imageKey, bitmap);

        return bitmap;
    }
    ...
}

public void addBitmapToCache(String key, Bitmap bitmap) {
    // Add to memory cache as before
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }

    // Also add to disk cache
    synchronized (mDiskCacheLock) {
        if (mDiskLruCache != null && mDiskLruCache.get(key) == null) {
            mDiskLruCache.put(key, bitmap);
        }
    }
}

public Bitmap getBitmapFromDiskCache(String key) {
    synchronized (mDiskCacheLock) {
        // Wait while disk cache is started from background thread
        while (mDiskCacheStarting) {
            try {
                mDiskCacheLock.wait();
            } catch (InterruptedException e) {}
        }
        if (mDiskLruCache != null) {
            return mDiskLruCache.get(key);
        }
    }
    return null;
}

// Creates a unique subdirectory of the designated app cache directory. Tries to use external
// but if not mounted, falls back on internal storage.
public static File getDiskCacheDir(Context context, String uniqueName) {
    // Check if media is mounted or storage is built-in, if so, try and use external cache dir
    // otherwise use internal cache dir
    final String cachePath =
            Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||
                    !isExternalStorageRemovable() ? getExternalCacheDir(context).getPath() :
                            context.getCacheDir().getPath();

    return new File(cachePath + File.separator + uniqueName);
}

Note:因?yàn)槌跏蓟疟P緩存涉及到I/O操作,所以它不應(yīng)該在主線程中進(jìn)行。但是這也意味著在初始化完成之前緩存可以被訪問。為了解決這個(gè)問題,在上面的實(shí)現(xiàn)中,有一個(gè)鎖對(duì)象(lock object)來確保在磁盤緩存完成初始化之前,應(yīng)用無法對(duì)它進(jìn)行讀取。

內(nèi)存緩存的檢查是可以在UI線程中進(jìn)行的,磁盤緩存的檢查需要在后臺(tái)線程中處理。磁盤操作永遠(yuǎn)都不應(yīng)該在UI線程中發(fā)生。當(dāng)圖片處理完成后,Bitmap需要添加到內(nèi)存緩存與磁盤緩存中,方便之后的使用。

處理配置改變(Handle Configuration Changes)

如果運(yùn)行時(shí)設(shè)備配置信息發(fā)生改變,例如屏幕方向的改變會(huì)導(dǎo)致Android中當(dāng)前顯示的Activity先被銷毀然后重啟。(關(guān)于這一方面的更多信息,請(qǐng)參考Handling Runtime Changes)。我們需要在配置改變時(shí)避免重新處理所有的圖片,這樣才能提供給用戶一個(gè)良好的平滑過度的體驗(yàn)。

幸運(yùn)的是,在前面介紹使用內(nèi)存緩存的部分,我們已經(jīng)知道了如何建立內(nèi)存緩存。這個(gè)緩存可以通過調(diào)用setRetainInstance(true)保留一個(gè)Fragment實(shí)例的方法把緩存?zhèn)鬟f給新的Activity。在這個(gè)Activity被重新創(chuàng)建之后,這個(gè)保留的Fragment會(huì)被重新附著上。這樣你就可以訪問緩存對(duì)象了,從緩存中獲取到圖片信息并快速的重新顯示到ImageView上。

下面是配置改變時(shí)使用Fragment來保留LruCache的代碼示例:

private LruCache<String, Bitmap> mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    RetainFragment retainFragment =
            RetainFragment.findOrCreateRetainFragment(getFragmentManager());
    mMemoryCache = retainFragment.mRetainedCache;
    if (mMemoryCache == null) {
        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
            ... // Initialize cache here as usual
        }
        retainFragment.mRetainedCache = mMemoryCache;
    }
    ...
}

class RetainFragment extends Fragment {
    private static final String TAG = "RetainFragment";
    public LruCache<String, Bitmap> mRetainedCache;

    public RetainFragment() {}

    public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
        RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG);
        if (fragment == null) {
            fragment = new RetainFragment();
            fm.beginTransaction().add(fragment, TAG).commit();
        }
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }
}

為了測(cè)試上面的效果,可以嘗試在保留Fragment與沒有這樣做的情況下旋轉(zhuǎn)屏幕。我們會(huì)發(fā)現(xiàn)當(dāng)保留緩存時(shí),從內(nèi)存緩存中重新繪制幾乎沒有延遲的現(xiàn)象。 內(nèi)存緩存中沒有的圖片可能存儲(chǔ)在磁盤緩存中。如果兩個(gè)緩存中都沒有,則圖像會(huì)像平時(shí)正常流程一樣被處理。