GridView内存及时释放,不需要使用软引用

来源:互联网 发布:美国标志软件 编辑:程序博客网 时间:2024/05/20 22:40
突然写上瘾了,就把这个得意之作发上来吧,这个内存释放可是花费了我将近一周呢,显示搞懂gridview机制,然后是进行优化,反正是搞死我了。
先说软引用吧,不得不说软引用是个非常好的解决OOM的方法,只要系统内存不够就会释放掉软引用中不需要的bitmap,但是经我测试这个也并不是及时释放的,我一屏显示20张图片的话,有时内存中会存在60多张图片,这个是我不能容忍的,我最多让它存在30张,多了如果我在此时处理一个需要很大内存的动作,系统会提高heapsize,这是会出现OOM的。
我的解决办法:人为及时释放内存,保证内存中图片不超过30张。
原理:gridview有两个参数,getFirstVisiblePosition和getLastVisiblePosition,这两个参数意思是当前显示的第一张图片的position和最后一张图片的position,有了这两个我们就可以有选择的释放内存了,此范围外的都是可以释放的。
我的代码:

[代码]java代码:

/** * * Copyright 2012 HISENSE. All rights reserved. * DirListAdapter.java * */package com.hisense.hicloud.album.hiview;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Map.Entry;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.GridView;import android.widget.ImageView;import com.hisense.hicloud.album.HiCloudAlbum;import com.hisense.hicloud.album.HiCloudApplication;import com.hisense.hicloud.album.R;import com.hisense.hicloud.album.imagecache.AsyncImageLoader;import com.hisense.hicloud.album.imagecache.HiImageView;import com.hisense.hicloud.album.imagecache.LocationImageCache;import com.hisense.hicloud.album.imagecache.AsyncImageLoader.BitmapCallback;import com.hisense.hicloud.album.imagecache.LocationImageCache.OnLoadImageListener;import com.hisense.hicloud.album.scanfiles.ImageListBean;import com.hisense.hicloud.album.sys.SYSPath;/** * @author qiuxiaolong (qiuxiaolong1@hisense.com) * @date 2012-2-13 */public class LocalImageAdapter2 extends BaseAdapter {private Context context;private static ArrayList<String> imagePathList;private LayoutInflater inflater;private ViewHolder holder = null;private AsyncImageLoader imageLoader; private String LocalThumbPath;//本地图片缩略图地址private static String TAG = "LocalImageAdapter2";    /**存放bitmap与position*/    public static ArrayList<HashMap<String,Object>> bitmapArrayList = new ArrayList<HashMap<String,Object>>();    //获取LocalGridView对象private GridView gridview;/**记步,记录getView执行次数,六次一循环*/private static int local_i = 0;/**记录gridview中第一张和最后一张图片的position*/private static int gridviewFirst = 0;private static int gridviewLast = 0;public LocalImageAdapter2(){}public LocalImageAdapter2(Context context,ArrayList<String> callList,GridView gridview) {this.context = context;this.imagePathList = callList;for (String url : imagePathList) {Log.d("==========Image Url==========", url);}inflater = LayoutInflater.from(this.context);imageLoader = new AsyncImageLoader(true, context);this.gridview = gridview;//judge that whether the bitmapArrayList  is nullCloudImageAdapter cloudimageadapter = new CloudImageAdapter();if(cloudimageadapter.getbitmapArrayListSize() != 0){//clean the bitmapArrayListcloudimageadapter.cleanbitmapArrayList();}}public void removeAdpterList(ArrayList<String> removeList){    System.out.println("=============删除元数据:"+removeList.size());    System.out.println("=============前:"+imagePathList.size());    imagePathList.removeAll(removeList);    System.out.println("=============后:"+imagePathList.size());}public int getCount() {return imagePathList.size();}public Object getItem(int position) {return imagePathList.get(position);}public long getItemId(int position) {return position;}/**return bitmapArrayList size*/public int getbitmapArrayListSize(){return bitmapArrayList.size();}/**clean bitmapArrayList all*/public void cleanbitmapArrayList(){for(int k = 0;k < bitmapArrayList.size();k++){if(bitmapArrayList.get(k).get("bitmap") != null){//get bitmap from hashmapBitmap bitmap1 = (Bitmap) bitmapArrayList.get(k).get("bitmap");try{if(!bitmap1.isRecycled()){bitmap1.recycle();Log.i(TAG,"clean bitmapArrayList success,print position:" + (Integer)bitmapArrayList.get(k).get("ID"));//remove this elementbitmapArrayList.remove(k);k--;}}catch(Exception e){Log.e(TAG,"clean bitmapArrayList error");e.printStackTrace();}}}}/**clean bitmap that not in gridview*/public void cleanGridView(){//select bitmaps what can be recycledfor(int k = 0;k < bitmapArrayList.size();k++){//keep these bitmaps which between first and lastif((Integer)bitmapArrayList.get(k).get("ID")>=(gridviewFirst-3) && (Integer)bitmapArrayList.get(k).get("ID") <= (gridviewLast + 3)){//in the range,do nothingLog.i(TAG,"in the range continue,print the k:" + k + ";and print the position:" + (Integer)bitmapArrayList.get(k).get("ID"));continue;}//get the bitmap from hashmapBitmap bitmap1 = (Bitmap) bitmapArrayList.get(k).get("bitmap");if(bitmap1 != null){try{Log.i(TAG,"start to recycle,print the position:" + (Integer)bitmapArrayList.get(k).get("ID") + ";print first position:" + gridviewFirst + ";print last position:" + gridviewLast);if(!bitmap1.isRecycled()){Log.i(TAG,"can be recycled,the id of bitmap:" + bitmap1.toString());//do the actionbitmap1.recycle();Log.i(TAG,"success to recycle,print the position:" + (Integer)bitmapArrayList.get(k).get("ID"));//remove this elementbitmapArrayList.remove(k);k--;}}catch(RuntimeException e){Log.e(TAG,"the bitmap can't be recycled,print the position:" + (Integer)bitmapArrayList.get(k).get("ID"));e.printStackTrace();}}}//do gcSystem.gc();}public View getView( final int position, View convertView, final ViewGroup parent) {Log.e(TAG,"print the position:" + position + ";print bitmapArrayList size:" + bitmapArrayList.size());//get current first position and last position gridviewFirst = gridview.getFirstVisiblePosition();gridviewLast = gridview.getLastVisiblePosition();//do the clean action for every sixif(local_i == 6){local_i = 0;//do the clean action//cleanGridView();}if (convertView == null) {holder = new ViewHolder();if(HiCloudAlbum.album_orientation == HiCloudAlbum.ALBUM_ORIENTATION_LANDSCAPE)convertView = inflater.inflate(R.layout.image_local_gridview_item_land, null);elseconvertView = inflater.inflate(R.layout.image_local_gridview_item, null);holder.img = (HiImageView) convertView.findViewById(R.id.image_thumbnail);holder.mask = (ImageView) convertView.findViewById(R.id.masklayer);holder.uploaded = (ImageView)convertView.findViewById(R.id.uploadedlayer);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}holder.img.setTag(imagePathList.get(position));if (LocalGridView.getAlreadUploadList().contains(imagePathList.get(position))){holder.uploaded.setVisibility(View.VISIBLE);holder.mask.setVisibility(View.GONE);}else{if (LocalGridView.getSelectedItemsList().contains(imagePathList.get(position))){    holder.mask.setVisibility(View.VISIBLE);}else{    holder.mask.setVisibility(View.GONE);}holder.uploaded.setVisibility(View.GONE);}//计算本地缩略图存放地址LocalThumbPath = SYSPath.LocalThumCachePATH + "/" + imagePathList.get(position).substring(imagePathList.get(position).lastIndexOf("/")+1) + "_Thum.jpg";Bitmap bitmap = null;boolean flag = false;Log.d(TAG,"输出LocalThumbPath" + LocalThumbPath);//if the bitmap is in the bitmapArrayList,then get it from bitmapArrayList /*for(int i = 0;i<bitmapArrayList.size();i++){//Comparison the positionif(bitmapArrayList.get(i).get("ID").toString().equals(String.valueOf(position))){Log.i(TAG,"have the same position,print this position:" + position);//get bitmap from hashmapbitmap = (Bitmap)bitmapArrayList.get(i).get("bitmap");holder.img.setImageBitmap(null);    holder.img.setImageBitmap(bitmap);    //set to be true,then skip getting bitmap from localflag = true;break;}}*/if(flag == false){//mark addlocal_i++;Log.i(TAG,"print the local_i" + local_i);//get bitmap from local//bitmap = AsyncImageLoader.getCacheBitmap(LocalThumbPath,position);bitmap = AsyncImageLoader.getCacheBitmap(imagePathList.get(position));if (bitmap != null){Log.i(TAG,"success to get the bitmap at section one");holder.img.setImageBitmap(null);    holder.img.setImageBitmap(bitmap);    //bitmapArrayList add            bitmapArrayListAdd(position,bitmap,"one");}else{Log.i(TAG,"can't find bitmap from local,bitmap is null,now start to create thumb picture and get bitmap from it");//bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.fipper_loading);    holder.img.setImageBitmap(null);    imageLoader.loadLocalBitmap(imagePathList.get(position),LocalThumbPath,new BitmapCallback() {    //imageLoader.loadLocalBitmap(imagePathList.get(position),LocalThumbPath, position,new BitmapCallback() {    public void imageLoaded(Bitmap imageBitmap, String imageUrl)                {                    // TODO Auto-generated method stub                    HiImageView iv = (HiImageView) parent.findViewWithTag(imageUrl);                    if (iv != null && imageBitmap != null)                    {        Log.i(TAG,"success to get the bitmap at section two");                    iv.setImageBitmap(null);                        iv.setImageBitmap(imageBitmap);                      //bitmapArrayList add                    bitmapArrayListAdd(position,imageBitmap,"two");                    }                }            });}}return convertView;}    /**bitmapArrayList add*/    private void bitmapArrayListAdd(int position,Bitmap bitmap,String section){    Log.d(TAG,"at section "+section+" print the id of bitmap:" + bitmap.toString() + ";print the position" + position);    //create map to put informationHashMap<String,Object> map = new HashMap<String,Object>();map.put("ID", position);//map.put("bitmap", bitmap);//add bitmapArrayListbitmapArrayList.add(map);    Log.d(TAG,"success and over at section " + section);    }public class ViewHolder {public HiImageView img;public ImageView mask;public ImageView uploaded;}}
其中cleanbitmapArrayList方法是不需要整个gridview的时候调用的,它会释放所有的bitmap资源,cleanGridView方法除了自身调用外,比如处理大内存消耗动作而且还要保留此gridview时也可以调用,可清除额外内存,其中有点要说明,Integer)bitmapArrayList.get(k).get("ID")>=(gridviewFirst-3),之所以减三加三,是我自己做的一个缓存区,可以调大,但是如果不减任何数肯定会报错,如果有try to use a recyclee bitmap 那就是这里出问题了,数字一般最好为你一行显示的个数。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
这都是12年写的文章了,现在已经有更好的代替方法,直接使用LruCache和DiskLruCache做缓存就行,Android既然已经提供了这么好用的缓存我们就不用再多此一举啦。
0 0