我需要幫助理解androids LruCache。我想用來加載圖像到我的gridview,使加載/滾動更好。有人可以使用LruCache發佈示例代碼。提前致謝。使用Android的示例lrucache
回答
下面是一類我使用LruCache製成,這是基於演示Doing More With Less: Being a Good Android Citizen given at Google I/O 2012。
退房電影,瞭解更多有關我在做什麼在TCImageLoader
類:
public class TCImageLoader implements ComponentCallbacks2 {
private TCLruCache cache;
public TCImageLoader(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(
Context.ACTIVITY_SERVICE);
int maxKb = am.getMemoryClass() * 1024;
int limitKb = maxKb/8; // 1/8th of total ram
cache = new TCLruCache(limitKb);
}
public void display(String url, ImageView imageview, int defaultresource) {
imageview.setImageResource(defaultresource);
Bitmap image = cache.get(url);
if (image != null) {
imageview.setImageBitmap(image);
}
else {
new SetImageTask(imageview).execute(url);
}
}
private class TCLruCache extends LruCache<String, Bitmap> {
public TCLruCache(int maxSize) {
super(maxSize);
}
@Override
protected int sizeOf(ImagePoolKey key, Bitmap value) {
int kbOfBitmap = value.getByteCount()/1024;
return kbOfBitmap;
}
}
private class SetImageTask extends AsyncTask<String, Void, Integer> {
private ImageView imageview;
private Bitmap bmp;
public SetImageTask(ImageView imageview) {
this.imageview = imageview;
}
@Override
protected Integer doInBackground(String... params) {
String url = params[0];
try {
bmp = getBitmapFromURL(url);
if (bmp != null) {
cache.put(url, bmp);
}
else {
return 0;
}
} catch (Exception e) {
e.printStackTrace();
return 0;
}
return 1;
}
@Override
protected void onPostExecute(Integer result) {
if (result == 1) {
imageview.setImageBitmap(bmp);
}
super.onPostExecute(result);
}
private Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection
= (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
if (level >= TRIM_MEMORY_MODERATE) {
cache.evictAll();
}
else if (level >= TRIM_MEMORY_BACKGROUND) {
cache.trimToSize(cache.size()/2);
}
}
}
看看Caching Bitmaps,其中演示了使用LruCache
。
從頁面代碼的相關部分如下: -
private LruCache mMemoryCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// Get memory class of this device, exceeding this amount will throw an
// OutOfMemory exception.
final int memClass = ((ActivityManager) context.getSystemService(
Context.ACTIVITY_SERVICE)).getMemoryClass();
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = 1024 * 1024 * memClass/8;
mMemoryCache = new LruCache(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in bytes rather than number of items.
return bitmap.getByteCount();
}
};
...
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}
嗯,我試圖把這個在我的活動,但有錯誤的種種給出的代碼所採取的第一個是LruCache是原始類型。參考通用類型LruCache
不需要擴展,'LruCache'是一個泛型類。閱讀Java泛型,瞭解這意味着什麼。本教程[Generic Types](http://docs.oracle.com/javase/tutorial/java/generics/types.html)應該讓你開始。 – Rajesh 2012-07-24 05:56:20
我明白了,謝謝。但是我仍然無法成功地使這個代碼工作 – MobDev 2012-07-24 07:32:25
我發現完美的我是一個工作非常簡單的方法...
這是Cache.java類。在這個類中,靜態的getInstance()
方法使我們能夠在整個應用程序中只創建一個緩存實例。 getLru()
方法用於檢索緩存的對象,它將在稍後顯示如何使用它。此緩存是通用的,這意味着您可以將任何對象類型保存到其中。
import android.support.v4.util.LruCache;
public class Cache {
private static Cache instance;
private LruCache<Object, Object> lru;
private Cache() {
lru = new LruCache<Object, Object>(1024);
}
public static Cache getInstance() {
if (instance == null) {
instance = new Cache();
}
return instance;
}
public LruCache<Object, Object> getLru() {
return lru;
}
}
這是你的活動,你的位圖保存到緩存代碼:
public void saveBitmapToCahche(){
//The imageView that you want to save it's bitmap image resourse
ImageView imageView = (ImageView) findViewById(R.id.imageViewID);
//To get the bitmap from the imageView
Bitmap bitmap = ((BitmapDrawable)imageview.getDrawable()).getBitmap();
//Saving bitmap to cache. it will later be retrieved using the bitmap_image key
Cache.getInstance().getLru().put("bitmap_image", bitmap);
}
的高速緩存大小這裏設置爲1024,可如果它太小被改變這是從緩存中檢索位圖的代碼,然後將imageView設置爲此位圖:
public void retrieveBitmapFromCache(){
//The imageView that you want to set to the retrieved bitmap
ImageView imageView = (ImageView) findViewById(R.id.imageViewID);
//To get bitmap from cache using the key. Must cast retrieved cache Object to Bitmap
Bitmap bitmap = (Bitmap)Cache.getInstance().getLru().get("bitmap_image");
//Setting imageView to retrieved bitmap from cache
imageView.setImageBitmap(bitmap));
}
這就是全部!正如你所看到的,這很容易和簡單。
- 例:
在我的應用程序,所有的意見都保存在類變量,使他們能夠在類的所有方法中可以看出。在我的第一個活動中,我在使用意圖開始新活動之前,將圖像位圖保存在onClickButton()
方法中的緩存中。我也是在我的緩存保存一個字符串值:
public void onClickButton(View v){
Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
String name = textEdit.getText().toString();
Cache.getInstance().getLru().put("bitmap_image", bitmap);
Cache.getInstance().getLru().put("name", name);
Intent i = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(i);
}
然後,我從第二活動導航到第三個活動也使用意圖。在上一個活動中,我將其他對象保存到我的緩存中,然後使用意向返回到第一個活動。一旦我回來了第一個活動,onCreate()
方法將開始。在該方法中,檢查我的緩存有任何位值或單獨的任何字符串值(根據我的應用業務):
public ImageView imageView;
public EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
//...Other code...
//The imageView that you want to save it's bitmap image resourse
imageView = (ImageView) findViewById(R.id.imageViewID);
//The editText that I want to save it's text into cache
editText = (EditText)findViewById(R.id.editTextID);
if(Cache.getInstance().getLru().get("name")!=null){
editText.setText(Cache.getInstance().getLru().get("name").toString());
}
if(Cache.getInstance().getLru().get("bitmap_image")!=null){
imageView.setImageBitmap((Bitmap)Cache.getInstance().getLru().get("bitmap_image"));
}
//...Other code...
}
https://techienotes.info/2015/08/28/caching-bitmaps-in-android-using-lrucache/
此鏈接有一個完整的項目爲樣本應用程序來加載圖像使用LruCache進入Gridview。
這個類是使用LruCache並從鏈接
public class ImageAdapter extends BaseAdapter{
private String TAG = getClass().getSimpleName();
Context mContext;
ArrayList<Uri> imageList;
private LruCache<String, Bitmap> mLruCache;
public ImageAdapter (Context context){
mContext = context;
//Find out maximum memory available to application
//1024 is used because LruCache constructor takes int in kilobytes
final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024);
// Use 1/4th of the available memory for this memory cache.
final int cacheSize = maxMemory/4;
Log.d(TAG, "max memory " + maxMemory + " cache size " + cacheSize);
// LruCache takes key-value pair in constructor
// key is the string to refer bitmap
// value is the stored bitmap
mLruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in kilobytes
return bitmap.getByteCount()/1024;
}
};
imageList = new ArrayList<Uri>();
//Change this directory to where the images are stored
String imagesFolderPath = Environment.getExternalStorageDirectory().getPath()+"/backups/";
File imageSrcDir = new File (imagesFolderPath);
// if directory not present, build it
if (!imageSrcDir.exists()){
imageSrcDir.mkdirs();
}
ArrayList<File> imagesInDir = getImagesFromDirectory(imageSrcDir);
for (File file: imagesInDir){
// imageList will hold Uri of all images
imageList.add(Uri.fromFile(file));
}
}
@Override
public int getCount() {
return imageList.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
/**
*
* @param position The position of the item within the
* adapter's data set of the item whose view we want.
* @param convertView it is the view to be reused
* @param parent The parent that this view will eventually be attached to
* @return a View corresponding to the data at the specified position.
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
Bitmap thumbnailImage = null;
if (convertView == null){
imageView = new ImageView(mContext);
imageView.setLayoutParams(
//150,150 is size of imageview to display image
new GridView.LayoutParams(150, 150));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
else {
imageView = (ImageView)convertView;
}
// Use the path as the key to LruCache
final String imageKey = imageList.get(position).toString();
//thumbnailImage is fetched from LRU cache
thumbnailImage = getBitmapFromMemCache(imageKey);
if (thumbnailImage == null){
// if asked thumbnail is not present it will be put into cache
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(imageKey);
}
imageView.setImageBitmap(thumbnailImage);
return imageView;
}
/**
* This function returns the files from a directory
* @param parentDirPath source directory in which images are located
* @return list of Files
*/
private ArrayList<File> getImagesFromDirectory (File parentDirPath){
ArrayList <File> listOfImages = new ArrayList<File>();
File [] fileArray = null;
if (parentDirPath.isDirectory()){//parentDirPath.exists() &&
// &&
// parentDirPath.canRead()){
fileArray = parentDirPath.listFiles();
}
if (fileArray == null){
return listOfImages; // return empty list
}
for (File file: fileArray){
if (file.isDirectory()){
listOfImages.addAll(getImagesFromDirectory(file));
}
else {
// Only JPEG and PNG formats are included
// for sake of simplicity
if (file.getName().endsWith("png") ||
file.getName().endsWith("jpg")){
listOfImages.add(file);
}
}
}
return listOfImages;
}
/**
* This function will return the scaled version of original image.
* Loading original images into thumbnail is wastage of computation
* and hence we will take put scaled version.
*/
private Bitmap getScaledImage (String imagePath){
Bitmap bitmap = null;
Uri imageUri = Uri.parse (imagePath);
try{
BitmapFactory.Options options = new BitmapFactory.Options();
/**
* inSampleSize flag if set to a value > 1,
* requests the decoder to sub-sample the original image,
* returning a smaller image to save memory.
* This is a much faster operation as decoder just reads
* every n-th pixel from given image, and thus
* providing a smaller scaled image.
* 'n' is the value set in inSampleSize
* which would be a power of 2 which is downside
* of this technique.
*/
options.inSampleSize = 4;
options.inScaled = true;
InputStream inputStream = mContext.getContentResolver().openInputStream(imageUri);
bitmap = BitmapFactory.decodeStream(inputStream, null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return bitmap;
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mLruCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key) {
return mLruCache.get(key);
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(String... params) {
final Bitmap bitmap = getScaledImage(params[0]);
addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);
return bitmap;
}
// onPostExecute() sets the bitmap fetched by doInBackground();
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = (ImageView)imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
}
- 1. Android:使用位圖的LruCache問題
- 2. Android LruCache和Animationdrawable
- 3. Android LRUCache檢索
- 4. 位圖不顯示使用lrucache和asynctask
- 5. 的Android LruCache在安卓1.6+
- 6. 使用H2的Android示例
- 7. Android LruCache(Android 3.1)線程安全
- 8. Android - 使用LruCache的圖像GridView庫 - 圖像不斷變化
- 9. 與LruCache
- 10. Android示例使用RtpStream
- 11. Android的使用Californium的CoAP示例
- 12. Android Lrucache參考/對象是否重複?
- 13. 如何清除Android設備LRUCache
- 14. 使用Android和SQLite的Oracle DMS示例?
- 15. Android的實時示例和使用AIDL?
- 16. 在應用程序中使用Android示例/示例
- 17. LruCache不工作
- 18. 用對象實現LruCache
- 19. 如何禁用ActiveAndroid LruCache
- 20. 如何檢查android的LruCache中可用的內存?
- 21. 類的實例作爲存儲位圖的LruCache中的鍵
- 22. LruCache受Android應用程序內存空間的限制嗎?
- 23. Android Twitter xAuth示例使用twitter4j
- 24. 使用Active MQ的示例JMS示例
- 25. Android支付API的示例示例
- 26. 如何計算Lrucache的sizeof?
- 27. 無法爲我的LruCache類
- 28. 自定義Gridview中的LRUCACHE
- 29. Python中的LRUcache行爲
- 30. 使用示例
它是基於pre-honeycomb LruCache還是更新的? http://developer.android.com/reference/android/support/v4/util/LruCache.html或http://developer.android.com/reference/android/util/LruCache.html – idish 2013-10-15 18:36:31
其猜測它基於支持版本,因爲使用的trimToSize僅適用於API> 17。 – 2014-10-27 08:52:26