加载过多图片出现的OutOfMemoryOutOfMemory问题 ."/>
Android中解决加载过多图片出现的OutOfMemoryOutOfMemory问题 .
首先呢,解决办法有好几种,降低图片的分辨率也不失一种办法,当然这里肯定不是这么用,也有直接更改虚拟机的内存的办法,
1. private final static floatTARGET_HEAP_UTILIZATION = 0.75f;
2. 在程序onCreate时就可以调用
3. VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
这里是增强VM的内存回收效率。
5:自定义我们的应用需要多大的内存,这个好暴力哇,强行设置最小内存大小,代码如下:
6. private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
7. //设置最小heap内存为6MB大小
8. VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);
这是直接更改内存大小,游戏可以参考,我这也不是这么做的。
我这直接给出一个类,大家呢直接调用构造器
第一步ImageLoader il=new ImageLoader(getApplicationContext(), id);这里第一个参数是用来得到缓存目录的,第二个参数是加载图片前的默认图片。
第二步调用il.DisplayImage(url, imageView);第一个参数是图片的url,第二个参数是imagview。复制拷贝,直接能用。
- package com.example.doudizhu;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.lang.ref.SoftReference;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Stack;
- import java.util.WeakHashMap;
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.widget.ImageView;
- public class ImageLoader {
- MemoryCache memoryCache = new MemoryCache();
- FileCache fileCache;
- /**这是一个弱引用,map的弱引用,关键是同步的,线程安全的*/
- private Map<ImageView, String> imageViews = Collections
- .synchronizedMap(new WeakHashMap<ImageView, String>());
- public ImageLoader(Context context,int id) {
- // Make the background thead low priority. This way it will not affect
- // the UI performance
- photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);
- stub_id=id;
- fileCache = new FileCache(context);
- }
- /**图片初始化的时显示的图片的id*/
- final int stub_id ;
- /**
- * 将最开始时的ImageView和url关联起来。因为最开始是空的所以显示的是初始化的图片
- * @param url
- * @param activity
- * @param imageView
- */
- public void DisplayImage(String url, ImageView imageView) {
- imageViews.put(imageView, url);
- Bitmap bitmap = memoryCache.get(url);
- if (bitmap != null)
- imageView.setImageBitmap(bitmap);
- else {
- queuePhoto(url, imageView);
- imageView.setImageResource(stub_id);
- }
- }
- /**
- * 初始化图片,设置初始的图片
- * @param url
- * @param activity
- * @param imageView
- */
- private void queuePhoto(String url, ImageView imageView) {
- // This ImageView may be used for other images before. So there may be
- // some old tasks in the queue. We need to discard them.
- photosQueue.Clean(imageView);
- PhotoToLoad p = new PhotoToLoad(url, imageView);
- synchronized (photosQueue.photosToLoad) {
- photosQueue.photosToLoad.push(p);
- photosQueue.photosToLoad.notifyAll();
- }
- // start thread if it's not started yet
- if (photoLoaderThread.getState() == Thread.State.NEW)
- photoLoaderThread.start();
- }
- private Bitmap getBitmap(String url) {
- File f = fileCache.getFile(url);
- // from SD cache
- Bitmap b = decodeFile(f);
- if (b != null)
- return b;
- // from web
- try {
- File myFile = new File(url);
- return decodeFile(myFile);
- } catch (Exception ex) {
- ex.printStackTrace();
- return null;
- }
- }
- // decodes image and scales it to reduce memory consumption
- private Bitmap decodeFile(File f) {
- try {
- // decode image size
- BitmapFactory.Options o = new BitmapFactory.Options();
- o.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(new FileInputStream(f), null, o);
- // Find the correct scale value. It should be the power of 2.
- final int REQUIRED_SIZE = 70;
- int width_tmp = o.outWidth, height_tmp = o.outHeight;
- int scale = 1;
- while (true) {
- if (width_tmp / 2 < REQUIRED_SIZE
- || height_tmp / 2 < REQUIRED_SIZE)
- break;
- width_tmp /= 2;
- height_tmp /= 2;
- scale *= 2;
- }
- // decode with inSampleSize
- BitmapFactory.Options o2 = new BitmapFactory.Options();
- o2.inSampleSize = scale;
- return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
- } catch (FileNotFoundException e) {
- }
- return null;
- }
- // Task for the queue
- private class PhotoToLoad {
- public String url;
- public ImageView imageView;
- public PhotoToLoad(String u, ImageView i) {
- url = u;
- imageView = i;
- }
- }
- PhotosQueue photosQueue = new PhotosQueue();
- public void stopThread() {
- photoLoaderThread.interrupt();
- }
- // stores list of photos to download
- class PhotosQueue {
- private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();
- // removes all instances of this ImageView
- /***
- * 移除掉堆栈当中的这个image
- * @param image
- */
- public void Clean(ImageView image) {
- for (int j = 0; j < photosToLoad.size();) {
- if (photosToLoad.get(j).imageView == image)
- photosToLoad.remove(j);
- else
- ++j;
- }
- }
- }
- class PhotosLoader extends Thread {
- public void run() {
- try {
- while (true) {
- // thread waits until there are any images to load in the
- // queue
- if (photosQueue.photosToLoad.size() == 0)
- synchronized (photosQueue.photosToLoad) {
- photosQueue.photosToLoad.wait();
- }
- if (photosQueue.photosToLoad.size() != 0) {
- PhotoToLoad photoToLoad;
- synchronized (photosQueue.photosToLoad) {
- photoToLoad = photosQueue.photosToLoad.pop();
- }
- Bitmap bmp = getBitmap(photoToLoad.url);
- memoryCache.put(photoToLoad.url, bmp);
- String tag = imageViews.get(photoToLoad.imageView);
- if (tag != null && tag.equals(photoToLoad.url)) {
- BitmapDisplayer bd = new BitmapDisplayer(bmp,
- photoToLoad.imageView);
- Activity a = (Activity) photoToLoad.imageView
- .getContext();
- a.runOnUiThread(bd);
- }
- }
- if (Thread.interrupted())
- break;
- }
- } catch (InterruptedException e) {
- // allow thread to exit
- }
- }
- }
- PhotosLoader photoLoaderThread = new PhotosLoader();
- // Used to display bitmap in the UI thread
- class BitmapDisplayer implements Runnable {
- Bitmap bitmap;
- ImageView imageView;
- public BitmapDisplayer(Bitmap b, ImageView i) {
- bitmap = b;
- imageView = i;
- }
- public void run() {
- if (bitmap != null)
- imageView.setImageBitmap(bitmap);
- else
- imageView.setImageResource(stub_id);
- }
- }
- public void clearCache() {
- memoryCache.clear();
- fileCache.clear();
- }
- class FileCache {
- private File cacheDir;
- public FileCache(Context context){
- //Find the dir to save cached images
- if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
- cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"LazyList");
- else
- cacheDir=context.getCacheDir();
- if(!cacheDir.exists())
- cacheDir.mkdirs();
- }
- public File getFile(String url){
- //I identify images by hashcode. Not a perfect solution, good for the demo.
- String filename=String.valueOf(url.hashCode());
- File f = new File(cacheDir, filename);
- return f;
- }
- public void clear(){
- File[] files=cacheDir.listFiles();
- for(File f:files)
- f.delete();
- }
- }
- class MemoryCache {
- private HashMap<String, SoftReference<Bitmap>> cache=new HashMap<String, SoftReference<Bitmap>>();
- public Bitmap get(String id){
- if(!cache.containsKey(id))
- return null;
- SoftReference<Bitmap> ref=cache.get(id);
- return ref.get();
- }
- public void put(String id, Bitmap bitmap){
- cache.put(id, new SoftReference<Bitmap>(bitmap));
- }
- public void clear() {
- cache.clear();
- }
- }
- }
更多推荐
Android中解决加载过多图片出现的OutOfMemoryOutOfMemory问题 .
发布评论