解决listview加载图片内存溢出的方案

listview 里的图片太多 会导致 listview 的OutOfMemoryException发生, 解决方案,只有例如 软引用 ,手动recycle 资源,缩小bitmap等等。(不过貌似都治标不治本,所以以前这个问题 一直困扰了我很久。。。)

即使使用了这些解决方案 也很可能碰到 以下的几个问题

1. 图片 比如 bitmap 或者 drawable 虽然可以用recycle 方法手动释放,但是 释放的时机。

2. 即使使用手动释放,但由于 图片被 imageview 或者其他控件引用 导致发生异常 比如 trying to use a recycled bitmap



我的解决方案是

testmemoryadapter.java

[java]  view plain copy
  1. package com.testmemoryadapter;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.content.Context;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.BitmapFactory;  
  8. import android.util.Log;  
  9. import android.view.LayoutInflater;  
  10. import android.view.View;  
  11. import android.view.ViewGroup;  
  12. import android.widget.BaseAdapter;  
  13. import android.widget.ImageView;  
  14.   
  15. public class TestAdapter extends BaseAdapter {  
  16.   
  17.     private ArrayList list;  
  18.     private LayoutInflater mInflater;  
  19.     private Context context;  
  20.     //这个用来保存 imageview 的引用  
  21.     private ArrayList viewList = new ArrayList();  
  22.     //这个用来 保存 bitmap  
  23.     private ArrayList bitmapList = new ArrayList();  
  24.   
  25.     @Override  
  26.     public int getCount() {  
  27.         // TODO Auto-generated method stub  
  28.         return list.size();  
  29.     }  
  30.   
  31.     @Override  
  32.     public Object getItem(int arg0) {  
  33.         // TODO Auto-generated method stub  
  34.         return null;  
  35.     }  
  36.   
  37.     @Override  
  38.     public long getItemId(int arg0) {  
  39.         // TODO Auto-generated method stub  
  40.         return 0;  
  41.     }  
  42.   
  43.     public TestAdapter(Context context, ArrayList list) {  
  44.         super();  
  45.         this.context = context;  
  46.         this.mInflater = LayoutInflater.from(context);  
  47.         this.list = list;  
  48.     }  
  49.   
  50.     @Override  
  51.     public View getView(int position, View convertView, ViewGroup arg2) {  
  52.         // TODO Auto-generated method stub  
  53.   
  54.         convertView = mInflater.inflate(R.layout.test_list_row, null);  
  55.   
  56.         ImageView iv = (ImageView) convertView.findViewById(R.id.imageView);  
  57.           
  58.           
  59.         //用try catch 块包围住  
  60.         try {  
  61.             setImage(iv);  
  62.         } catch (OutOfMemoryError e) {  
  63.             // 这里就是当内存泄露时 需要做的事情  
  64.             e.printStackTrace();  
  65.   
  66.             Log.d("memory""out");  
  67.               
  68.             //释放内存资源  
  69.             recycleMemory();  
  70.               
  71.             //将刚才 发生异常没有执行的 代码 再重新执行一次  
  72.             setImage(iv);  
  73.   
  74.         }  
  75.   
  76.         return convertView;  
  77.     }  
  78.   
  79.       
  80.     //这里是关键  
  81.     private void recycleMemory() {  
  82.         //一屏显示多少行 这里就设置为多少。不设也行 主要是用户体验好 不会将用户看到的图片设为默认图片  
  83.         int showCount = 10;  
  84.           
  85.         //  
  86.         for (int i = 0; i < viewList.size()-showCount; i++) {  
  87.             ImageView iv = (ImageView) viewList.get(i);  
  88.             /*** 
  89.              *  这里是关键! 将 imageview 设置一张默认的图片 , 
  90.              *  用于解决当释放bitmap的时候 还有其他 控件对他保持引用 
  91.              *  就不会发生trying to use a recycled bitmap异常了 
  92.              */  
  93.             iv.setImageResource(R.drawable.default_cover);  
  94.             //从list中去除  
  95.             viewList.remove(i);  
  96.         }  
  97.   
  98. //      viewList = new ArrayList();  
  99.   
  100.         for (int i = 0; i < bitmapList.size()-10; i++) {  
  101.   
  102.             Bitmap bitmap = (Bitmap) bitmapList.get(i);  
  103.             //这里就开始释放bitmap 所占的内存了  
  104.             if (!bitmap.isRecycled()) {  
  105.                 bitmap.recycle();  
  106.                 System.out.println("recycle ");  
  107.             }  
  108.             //从list中去除  
  109.             bitmapList.remove(i);  
  110.         }  
  111.   
  112. //      bitmapList = new ArrayList();  
  113.     }  
  114.       
  115.     private void setImage(ImageView iv){  
  116.         /*** 
  117.          * 从sdcard获取 图片  这张图片 只要不超过  android对于图片大小的限制即可  
  118.          * 我用了 一张比较大的图片 也通过测试 
  119.          */  
  120.         Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/test/1.jpg");  
  121.   
  122.         iv.setImageBitmap(bitmap);  
  123.           
  124.         //将这个控件 添加到 list里  
  125.         viewList.add(iv);  
  126.         //将要 释放的 bitmap也添加到list里  
  127.         bitmapList.add(bitmap);  
  128.     }  
  129.   
  130. }  

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <ImageView  
  8.         android:id="@+id/imageView"  
  9.         android:layout_width="80dip"  
  10.         android:layout_height="80dip" android:src="@drawable/default_cover"/>  
  11.   
  12. </LinearLayout>  

[java]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="@string/hello" />  
  11.   
  12.     <ListView  
  13.         android:id="@+id/testListView"  
  14.         android:layout_width="fill_parent"  
  15.         android:layout_height="fill_parent" >  
  16.     </ListView>  
  17.   
  18. </LinearLayout>  

[java]  view plain copy
  1. package com.testmemoryadapter;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.widget.ListView;  
  8.   
  9. public class MainActivity extends Activity {  
  10.     /** Called when the activity is first created. */  
  11.     @Override  
  12.     public void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.         setContentView(R.layout.main);  
  15.         ArrayList testList = new ArrayList();  
  16.           
  17.         for (int i = 0; i < 30; i++) {  
  18.             testList.add(0);  
  19.         }  
  20.           
  21.         TestAdapter ta = new TestAdapter(this,testList);  
  22.           
  23.         ListView lv = (ListView) findViewById(R.id.testListView);  
  24.           
  25.         lv.setAdapter(ta);  
  26.           
  27.     }  
  28. }  
。希望能给被这个问题困扰的朋友们提供些思路。


http://download.csdn.net/detail/w237or45/4124069

这里是源码下载的位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值