日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android使用软引用构建缓存

發布時間:2025/7/25 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android使用软引用构建缓存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://www.devdiv.com/Android-%E4%BD%BF%E7%94%A8%E8%BD%AF%E5%BC%95%E7%94%A8%E6%9E%84%E5%BB%BA%E7%BC%93%E5%AD%98-thread-130476-1-1.html

============================================================================================

一、為什么要使用軟引用

? ?? ? 在上面關于軟引用的介紹中,已經提到了軟引用的特性。使用SoftReference引用的對象會有很長的生命周期,只有當系統的內存不足的時候,才會去釋放這些軟引用對象。所以可以使用軟引用來緩存一些比較昂貴的資源,比如獲取的網絡圖片數據。

? ?? ???當應用從網絡中獲取網絡圖片數據時,用戶完全有可能做一些重復性的操作去查看相同的圖片信息。對于這樣的問題,通常會有兩種解決方法: 一種是把過去查看過的圖片信息保存在內存中,每一個存儲了圖片信息的 Java 對象的生命周期都貫穿整個應用程序生命周期,另一種是當用戶開始查看其他圖片信息的時候,把存儲了當前的圖片信息的 Java 對象結束引用,使得垃圾收集線程可以回收其所占用的內存空間,當用戶再次需要瀏覽該圖片信息的時候,重新獲取圖片信息。

? ?? ???很顯然,第一種實現方法將造成大量的內存浪費,而第二種實現的缺陷在于即使垃圾收集線程還沒有進行垃圾收集,包含圖片信息的對象仍然完好地保存在內存中,應用程序也要重新構建一個對象。

? ?? ???像訪問磁盤文件、訪問網絡資源、查詢數據庫等操作都是影響應用程序執行性能的重要因素,如果能重新獲取那些尚未被回收的 Java 對象的引用,必將減少不必要的訪問,大大提高程序的運行速度。

? ?? ???這樣看來,使用軟引用是非常有必要的一件事情。

二、如何使用軟引用

? ?? ???SoftReference 的特點是它的一個實例保存著一個 Java 對象的軟引用,該軟引用的存在不妨礙垃圾收集器線程對該 Java 對象的回收。也就是說,一旦SoftReference 保存著一個 Java 對象的軟引用之后,在垃圾收集器線程對這個 Java 對象回收之前, SoftReference 類所提供的 get() 方法都會返回 這個Java 對象的強引用。另外,一旦垃圾線程回收該 Java 對象之后, get() 方法將返回 null 。

? ?? ???軟引用的使用方法如下面的Java代碼所示 :

1 MyObject aRef = new MyObject();//創建一個對象 2 SoftReference aSoftRef = new SoftReference( aRef );//創建對象的軟引用


? ?
? ?? ???上面的代碼執行后,對于MyObject 對象,有兩個引用路徑,一個是來自 aSoftRef對象的軟引用,一個來自變量 aRef 的強引用,所以 MyObject對象是強可及對象。緊跟著,可以使用下面的java的代碼結束 aReference 對 MyObject 實例的強引用 :

1 aRef = null ;//斷開對象的強引用


? ?? ???此后, MyObject 對象成為了軟可及對象。如果垃圾收集線程進行內存垃圾收集,并不會因為有一個 SoftReference 對該對象的引用而始終保留該對象。 Java 虛擬機的垃圾收集線程對軟可及對象和其他一般 Java 對象進行了區別對待 ,軟可及對象的清理是由垃圾收集線程根據其特定算法按照內存需求決定的。也就是說,垃圾收集線程會在虛擬機拋出 OutOfMemoryError 之前回收軟可及對象,而且虛擬機會盡可能優先回收長時間閑置不用的軟可及對象,對那些剛剛構建的或剛剛使用過的“新”軟可及對象會被虛擬機盡可能保留。如果想獲取軟引用中包含的對象,可以使用下面的Java代碼:

1 MyObject anotherRef =(MyObject) aSoftRef .get();//通過軟引用獲取對象

?


? ??
? ?? ???在回收這些對象之前,可以通過上面的代碼重新獲得對該實例的強引用。而回收之后,當調用軟引用的get() 方法時,返回的是 null 。

三、如何使用 ReferenceQueue

? ?? ???作為一個 Java 對象, SoftReference 對象除了具有保存軟引用的特殊性之外,也具有 Java 對象的一般性。所以,當軟可及對象被回收之后,雖然這個 SoftReference 對象的 get() 方法返回 null, 但這個 SoftReference 對象已經不再具有存在的價值,需要一個適當的清除機制,避免大量 SoftReference 對象帶來的內存泄漏。在 java.lang.ref 包里還提供了 ReferenceQueue 。如果在創建 SoftReference 對象的時候,使用了帶有一個 ReferenceQueue 對象作為參數的構造方法,如下面的Java代碼 :

1 ReferenceQueue queue = new ReferenceQueue();//創建引用隊列 2 SoftReference ref = new SoftReference( aMyObject, queue );// 把引用加入到引用隊列

?

??


? ?? ???當這個 SoftReference 所軟引用的 aMyOhject 被垃圾收集器回收的同時,ref 所強引用的 SoftReference 對象被列入 ReferenceQueue 。也就是說, ReferenceQueue 中保存的對象是 Reference 對象,而且是已經失去了它所軟引用的對象的 Reference 對象。另外從 ReferenceQueue 這個名字也可以看出,它是一個隊列,當調用它的 poll() 方法的時候,如果這個隊列中不是空隊列,那么將返回隊列前面的那個 Reference 對象。

? ?? ???在任何時候,都可以調用 ReferenceQueue 的 poll() 方法來檢查是否有它所關心的非強可及對象被回收。如果隊列為空,將返回一個 null, 否則該方法返回隊列中最前面一個 Reference 對象。利用這個方法,可以檢查哪個 SoftReference 所軟引用的對象已經被回收。可以把這些失去所軟引用的對象的 SoftReference 對象清除掉,如下面的Java代碼所示。:

1 SoftReference ref = null ; 2 while ((ref = (EmployeeRef) q .poll()) != null ) { 3 // 清除 ref 4 }
??


四、實例分析

? ?? ???理解了 Java中的引用機制之后就可以在Android中構造緩存器(cache)了,在Android中應用比較多的控件是ListView,通常會使用ListView顯示網絡數據列表,同時會包含圖片縮略圖,當數據量很大的時候,為了讓用戶能更流暢地流量信息,可以使用異步加載和緩存機制處理網絡圖片。
通過以上對于Java軟引用類型的了解,可以知道使用軟引用來構建緩存是比較合適的。雖然軟引用能夠延長數據對象的生命周期,但是對于移動設備來說,內存資源相對來說比較緊缺,僅使用軟引用未必能達到最佳的緩存效果。通常會使用一些組合方式來進行數據緩存,最常用的是強引用、軟引用加本地緩存的方式。

? ?? ???Android提供了一個AsyncTask類,它封裝了基本的異步操作模型,只需要實現幾個最基本的方法就可以很容易的實現異步加載圖片,主要的方法是doInBackground方法和onPostExecute方法。AsyncTask類會啟動一個新的線程執行doInBackground方法,所以我們所有的網絡操作都應該在這個方法中實現,當doInBackground方法執行完成后,AsyncTask類會使用內置的Handler發送消息在主線程中執行onPostExecute方法,所以關于對UI的操作都應該放在onPostExecute方法中實現。

? ?? ???對于緩存的處理,主要思路是:在開始時,創建兩個緩存區域:強引用緩存區域和軟引用緩存區域。在強引用緩存區中保存有限的圖片對象,根據LRU策略把一些最不常用的圖片對象移到軟引用緩存區,當緩存區域中都沒有圖片對象時從網絡加載圖片。完成后把圖片數據保存到SDCard中,并根據LRU策略進行管理SDCard中保存的圖片文件。

? ?? ???下圖為ListView異步加載遠程圖片的流程圖:

?

下面通過一個ListView的使用實例來說明如何在Android應用程序中使用異步加載圖片,并且在內存和本地緩存它們。

? ?? ???第一步,首先建立一個Android工程,名稱為AsyncListImage,由于應用需要訪問網絡所以需要修改AndroidManifest.xml文件,添加網絡連接的權限,代碼如下:

1 <uses-permission android:name="android.permission.INTERNET"/>

??? ???第二步,修改main.xml文件添加listview控件,并設置listview的一些基本屬性信息,如下面的xml代碼:

01 <?xml version="1.0" encoding="utf-8"?> 02 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 03android:orientation="vertical" 04 android:layout_width="fill_parent" 05android:layout_height="fill_parent"> 06<ListView android:id="@+id/list" 07android:layout_width="fill_parent" 08android:layout_height="fill_parent" 09android:background="#ffffffff" 10android:cacheColorHint="#00000000"/> 11 </LinearLayout>

? 第三步,修改AsyncListImage Activity類并覆蓋oncreate方法,初始化listview,并創建listview控件使用的Adapter。在AsyncListImage中定義了兩種緩存區域A和B,A代表強引用緩存區域,B代表軟引用緩存區域,由于使用強引用緩存區域保存數據只能保存一定的數量,而不能一直往里面存放,需要設置數據的過期時間、LRU等算法。這里有一個方法是把常用的數據放到緩存A中,不常用的放到另外一個緩存B中。當要獲取數據時先從A中去獲取,如果A中不存在那么再去B中獲取。B中的數據主要是A中經過LRU生成的數據,這里的內存回收主要針對B內存,從而保持A中的數據可以有效的被命中。

? ?? ???下面是完整的Java代碼:

1 package com.devdiv.android.asynimagelist; 2 3 import java.io.File; 4 import java.lang.ref.SoftReference; 5 import java.util.HashMap; 6 import java.util.LinkedHashMap; 7 import java.util.concurrent.ConcurrentHashMap; 8 9 import android.app.Activity; 10 import android.graphics.Bitmap; 11 import android.os.Bundle; 12 import android.util.Log; 13 import android.view.View; 14 import android.view.ViewGroup; 15 import android.widget.BaseAdapter; 16 import android.widget.ImageView; 17 import android.widget.ListView; 18 import android.widget.ImageView.ScaleType; 19 20 @SuppressWarnings("serial") 21 public class AsyncListImage extends Activity implements RemoteImageCallback { 22 private ListView list; 23 private static final String TAG = AsyncListImage.class.getSimpleName(); 24 private static final int HARD_CACHE_CAPACITY = 10; 25 26 private final HashMap<String, Bitmap> mHardBitmapCache = new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) { 27 28 @Override 29 protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) { 30 if (size() > HARD_CACHE_CAPACITY) { 31 //當map的size大于10時,把最近不常用的key放到mSoftBitmapCache中,從而保證mHardBitmapCache的效率 32 mSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue())); 33 return true; 34 } else 35 return false; 36 } 37 }; 38 39 /** 40 *當mHardBitmapCache的key大于10的時候,會根據LRU算法把最近沒有被使用的key放入到這個緩存中。 41 * Bitmap使用了SoftReference,當內存空間不足時,此cache中的bitmap會被垃圾回收掉 42 */ 43 private final static ConcurrentHashMap<String, SoftReference<Bitmap>> mSoftBitmapCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>( 44 HARD_CACHE_CAPACITY / 2); 45 46 @Override 47 public void onCreate(Bundle savedInstanceState) { 48 super.onCreate(savedInstanceState); 49 setContentView(R.layout.main); 50 list = (ListView) findViewById(R.id.list); 51 52 initCacheDir(); 53 54 MyListAdapter adapter = new MyListAdapter(); 55 list.setAdapter(adapter); 56 } 57 58 private void initCacheDir() { 59 String cacheDir = "/data/data/com.devdiv.android.asynimagelist/files/caches"; 60 File f = new File(cacheDir); 61 if (!f.exists()) { 62 f.mkdirs(); 63 } 64 } 65 66 private class MyListAdapter extends BaseAdapter { 67 private String[] urls = new String[] { 68 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Add%20Icon.jpg", 69 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Adobe%20Illustator%20Icon.jpg", 70 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Attach%20Icon.jpg", 71 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Applications%20Cascade%20Icon.jpg", 72 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Administrator%20Icon.jpg", 73 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Clients%20Icon.jpg", 74 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Coinstack%20Icon.jpg", 75 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Download%20Icon.jpg", 76 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Help%20Icon.jpg", 77 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Home%20Icon.jpg", 78 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Pen%20Icon.jpg", 79 "http://www.icosky.com/icon/thumbnails/System/Sleek%20XP%20Basic/Statistics%20Icon.jpg" 80 }; 81 82 @Override 83 public int getCount() { 84 return urls.length; 85 } 86 87 @Override 88 public String getItem(int position) { 89 return urls[position]; 90 } 91 92 @Override 93 public long getItemId(int position) { 94 return position; 95 } 96 97 @Override 98 public View getView(int position, View convertView, ViewGroup parent) { 99 if (convertView == null) { 100 convertView = new ImageView(AsyncListImage.this); 101 } 102 ImageView iv = (ImageView)convertView; 103 iv.setScaleType(ScaleType.FIT_START); 104 Bitmap bitmap = getBitmapFromCache(getItem(position)); 105 if (bitmap == null) { 106 iv.setImageResource(R.drawable.default_image); 107 iv.setTag(getItem(position)); 108 new ImageDownloaderTask(AsyncListImage.this).execute(new String[]{getItem(position)}); 109 } else { 110 iv.setImageBitmap(bitmap); 111 } 112 iv = null; 113 return convertView; 114 } 115 116 } 117 118 /** 119 * 從緩存中獲取圖片 120 */ 121 private Bitmap getBitmapFromCache(String url) { 122 // 先從mHardBitmapCache緩存中獲取 123 synchronized (mHardBitmapCache) { 124 final Bitmap bitmap = mHardBitmapCache.get(url); 125 if (bitmap != null) { 126 //如果找到的話,把元素移到linkedhashmap的最前面,從而保證在LRU算法中是最后被刪除 127 mHardBitmapCache.remove(url); 128 Log.d(TAG, "move bitmap to the head of linkedhashmap:" + url); 129 mHardBitmapCache.put(url,bitmap); 130 return bitmap; 131 } 132 } 133 //如果mHardBitmapCache中找不到,到mSoftBitmapCache中找 134 SoftReference<Bitmap> bitmapReference = mSoftBitmapCache.get(url); 135 if (bitmapReference != null) { 136 final Bitmap bitmap = bitmapReference.get(); 137 if (bitmap != null) { 138 Log.d(TAG, "get bitmap from mSoftBitmapCache with key:" + url); 139 return bitmap; 140 } else { 141 mSoftBitmapCache.remove(url); 142 Log.d(TAG, "remove bitmap with key:" + url); 143 } 144 } 145 return null; 146 } 147 148 @Override 149 public void onComplete(String url, Bitmap bitmap) { 150 Log.d(TAG, "onComplete after got bitmap from remote with key:" + url); 151 ImageView iv = (ImageView)list.findViewWithTag(url); 152 if (iv != null) { 153 iv.setImageBitmap(bitmap); 154 mHardBitmapCache.put(url, bitmap); 155 } 156 } 157 158 }


? ?? ???第四步,定義AsyncTask 類的子類ImageDownloaderTask類并覆蓋doInBackground 方法和onPostExecute方法。在doInBackground方法中進行網絡操作和文件操作,在onPostExecute方法中執行回調函數,把獲取的bitmap數據發送到UI線程與ListView中的imageView進行關聯,Java代碼如下。

1 package com.devdiv.android.asynimagelist; 2 3 import java.io.BufferedOutputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.Closeable; 6 import java.io.File; 7 import java.io.FileNotFoundException; 8 import java.io.FileOutputStream; 9 import java.io.IOException; 10 import java.io.InputStream; 11 import java.io.OutputStream; 12 import java.lang.ref.WeakReference; 13 import java.util.Arrays; 14 import java.util.Comparator; 15 16 import org.apache.http.HttpEntity; 17 import org.apache.http.HttpResponse; 18 import org.apache.http.HttpStatus; 19 import org.apache.http.client.methods.HttpGet; 20 import org.apache.http.impl.client.DefaultHttpClient; 21 22 import android.graphics.Bitmap; 23 import android.graphics.BitmapFactory; 24 import android.os.AsyncTask; 25 import android.os.Environment; 26 import android.os.StatFs; 27 import android.util.Log; 28 29 public class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap> { 30 private static String TAG = ImageDownloaderTask.class.getSimpleName(); 31 private static final int IO_BUFFER_SIZE = 4 * 1024; 32 private static final int MB = 1024 * 1024; 33 private static final int CACHE_SIZE = 1024 * 1024; 34 private static final int mTimeDiff = 5 * 24 * 60 * 60 * 1000; 35 private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 30; 36 private static final String WHOLESALE_CONV = "/data/data/com.devdiv.android.asynimagelist/files/caches"; 37 private String url; 38 private final WeakReference<AsyncListImage> activityReference; 39 40 public ImageDownloaderTask(AsyncListImage activity) { 41 activityReference = new WeakReference<AsyncListImage>(activity); 42 } 43 44 @Override 45 protected Bitmap doInBackground(String... params) { 46 url = params[0]; 47 String filename = convertUrlToFileName(url); 48 String dir = getDirectory(filename); 49 File file = new File(dir + "/" + filename); 50 if (file.exists()) { 51 removeExpiredCache(dir, filename); 52 updateFileTime(dir, filename); 53 Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); 54 if (bitmap != null) 55 return bitmap; 56 } 57 58 final DefaultHttpClient client = new DefaultHttpClient(); 59 60 final HttpGet getRequest = new HttpGet(url); 61 try { 62 HttpResponse response = client.execute(getRequest); 63 final int statusCode = response.getStatusLine().getStatusCode(); 64 if (statusCode != HttpStatus.SC_OK) { 65 Log.w(TAG, "從" + url + "中下載圖片時出錯!,錯誤碼:" + statusCode); 66 return null; 67 } 68 final HttpEntity entity = response.getEntity(); 69 if (entity != null) { 70 InputStream inputStream = null; 71 OutputStream outputStream = null; 72 try { 73 inputStream = entity.getContent(); 74 final ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); 75 outputStream = new BufferedOutputStream(dataStream, 76 IO_BUFFER_SIZE); 77 copy(inputStream, outputStream); 78 outputStream.flush(); 79 final byte[] data = dataStream.toByteArray(); 80 final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 81 0, data.length); 82 83 saveBmpToSd(bitmap, url); 84 85 return bitmap; 86 } finally { 87 closeStream(inputStream); 88 closeStream(outputStream); 89 entity.consumeContent(); 90 } 91 } 92 } catch (IOException e) { 93 getRequest.abort(); 94 Log.w(TAG, "I/O error while retrieving bitmap from " + url, e); 95 } catch (IllegalStateException e) { 96 getRequest.abort(); 97 Log.w(TAG, "Incorrect URL:" + url); 98 } catch (Exception e) { 99 getRequest.abort(); 100 Log.w(TAG, "Error while retrieving bitmap from " + url, e); 101 } 102 return null; 103 } 104 105 @Override 106 protected void onPostExecute(Bitmap result) { 107 super.onPostExecute(result); 108 AsyncListImage act = activityReference.get(); 109 if (act != null && result != null) { 110 act.onComplete(url, result); 111 } 112 } 113 114 115 /** 116 * Copy the content of the input stream into the output stream, using a temporary 117 * byte array buffer whose size is defined by {@link #IO_BUFFER_SIZE}. 118 * 119 * @param in The input stream to copy from. 120 * @param out The output stream to copy to. 121 * 122 * @throws java.io.IOException If any error occurs during the copy. 123 */ 124 public static void copy(InputStream in, OutputStream out) throws IOException { 125 byte[] b = new byte[IO_BUFFER_SIZE]; 126 int read; 127 while ((read = in.read(b)) != -1) { 128 out.write(b, 0, read); 129 } 130 } 131 132 /** 133 * Closes the specified stream. 134 * 135 * @param stream The stream to close. 136 */ 137 public static void closeStream(Closeable stream) { 138 if (stream != null) { 139 try { 140 stream.close(); 141 } catch (IOException e) { 142 android.util.Log.e(TAG, "Could not close stream", e); 143 } 144 } 145 } 146 147 private void saveBmpToSd(Bitmap bm, String url) { 148 if (bm == null) { 149 Log.w(TAG, " trying to savenull bitmap"); 150 return; 151 } 152 // 判斷sdcard上的空間 153 if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) { 154 Log.w(TAG, "Low free space onsd, do not cache"); 155 removeCache(WHOLESALE_CONV); 156 return; 157 } 158 String filename = convertUrlToFileName(url); 159 String dir = getDirectory(filename); 160 File file = new File(dir + "/" + filename); 161 try { 162 file.createNewFile(); 163 OutputStream outStream = new FileOutputStream(file); 164 bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream); 165 outStream.flush(); 166 outStream.close(); 167 Log.i(TAG, "Image saved tosd"); 168 } catch (FileNotFoundException e) { 169 Log.w(TAG, "FileNotFoundException"); 170 } catch (IOException e) { 171 Log.w(TAG, "IOException"); 172 } 173 } 174 175 private String convertUrlToFileName(String url) { 176 int lastIndex = url.lastIndexOf('/'); 177 return url.substring(lastIndex + 1); 178 } 179 180 private String getDirectory(String filename) { 181 return WHOLESALE_CONV; 182 } 183 184 /** 185 * 計算sdcard上的剩余空間 186 * 187 * @return 188 */ 189 private int freeSpaceOnSd() { 190 StatFs stat = new StatFs(Environment.getExternalStorageDirectory() 191 .getPath()); 192 double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat 193 .getBlockSize()) 194 / MB; 195 return (int) sdFreeMB; 196 } 197 198 /** 199 * 修改文件的最后修改時間 200 * 201 * @param dir 202 * @param fileName 203 */ 204 private void updateFileTime(String dir, String fileName) { 205 File file = new File(dir, fileName); 206 long newModifiedTime = System.currentTimeMillis(); 207 file.setLastModified(newModifiedTime); 208 } 209 210 /** 211 *計算存儲目錄下的文件大小, 212 * 當文件總大小大于規定的CACHE_SIZE或者sdcard剩余空間小于FREE_SD_SPACE_NEEDED_TO_CACHE的規定 213 * 那么刪除40%最近沒有被使用的文件 214 * 215 * @param dirPath 216 * @param filename 217 */ 218 private void removeCache(String dirPath) { 219 File dir = new File(dirPath); 220 File[] files = dir.listFiles(); 221 if (files == null) { 222 return; 223 } 224 int dirSize = 0; 225 for (int i = 0; i < files.length; i++) { 226 if (files.getName().contains(WHOLESALE_CONV)) { 227 dirSize += files.length(); 228 } 229 } 230 if (dirSize > CACHE_SIZE * MB 231 || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) { 232 int removeFactor = (int) ((0.4 * files.length) + 1); 233 234 Arrays.sort(files, new FileLastModifSort()); 235 236 Log.i(TAG, "Clear some expiredcache files "); 237 238 for (int i = 0; i < removeFactor; i++) { 239 240 if (files.getName().contains(WHOLESALE_CONV)) { 241 242 files.delete(); 243 244 } 245 246 } 247 248 } 249 250 } 251 252 /** 253 * TODO 根據文件的最后修改時間進行排序 * 254 */ 255 class FileLastModifSort implements Comparator<File> { 256 public int compare(File arg0, File arg1) { 257 if (arg0.lastModified() > arg1.lastModified()) { 258 return 1; 259 } else if (arg0.lastModified() == arg1.lastModified()) { 260 return 0; 261 } else { 262 return -1; 263 } 264 } 265 } 266 267 /** 268 * 刪除過期文件 269 * 270 * @param dirPath 271 * @param filename 272 */ 273 private void removeExpiredCache(String dirPath, String filename) { 274 275 File file = new File(dirPath, filename); 276 277 if (System.currentTimeMillis() - file.lastModified() > mTimeDiff) { 278 279 Log.i(TAG, "Clear some expiredcache files "); 280 281 file.delete(); 282 283 } 284 285 } 286 }

?第五步、運行工程之后,運行效果如下圖示。

? ?? ???運行工程,最開始時,ListView使用默認的圖片填充imageview。

? ?然后使用異步方式獲取網絡圖片,當獲取到網絡圖片后,使用最新的網絡圖片替換默認圖片。

?

?當用戶拖動ListView,顯示效果如下圖所示:

?

?再次運行工程后,加載圖片的速度會非常塊,因為程序在手機內存中存儲了相應的圖片資源,直接加載這些資源就好了,不需要再訪問網絡。

? ?? ???下圖是在DDMS的File Explorer中的顯示:

?

轉載于:https://www.cnblogs.com/elefish/archive/2013/02/15/2912809.html

總結

以上是生活随笔為你收集整理的android使用软引用构建缓存的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。