对一个gridview异步加载大量图片的实例的个人理解

首先贴上原代码地址:链接

然后是在自己代码中的运用

public class GridAdapter extends BaseAdapter {
	private MediaThumbnail mtb;
	private final static String TAG="GridAdapter";
	private LayoutInflater mInflater;
	private ArrayList<BaseData> gridOnePage = new ArrayList<BaseData>();
	private Resources resourceGrid;
	private static int thumbnailVideoOrMusic=-100;
	public GridAdapter(Context context,ArrayList<BaseData>gridOnePage) {
		this.mInflater = LayoutInflater.from(context);
		this.gridOnePage=gridOnePage;
	}

	public int getCount() {
		//return mData.size();
		if(gridOnePage==null)
			  return 0;
		return gridOnePage.size();
	}

	public Object getItem(int arg0) {
		return null;
	}

	public long getItemId(int arg0) {
		return 0;
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder = null;
		if (convertView == null) {
			holder = new ViewHolder();
			convertView = mInflater.inflate(R.layout.gridview_item, null);
			holder.img = (ImageView) convertView.findViewById(R.id.img);
			holder.title = (TextView) convertView.findViewById(R.id.title);
			//holder.info = (TextView) convertView.findViewById(R.id.info);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}
        if(gridOnePage.get(position).getType() == Constants.FILE_TYPE_VIDEO){
			Drawable drawable =null;
			drawable = FileBrowserActivity.fileTypeDrawable.get(3);
				  holder.img.setImageDrawable(drawable);
		}
		
		else{
			Drawable drawable =null;
			if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_FILE){
				  
				  drawable = FileBrowserActivity.fileTypeDrawable.get(0);
				  holder.img.setImageDrawable(drawable);
			}
			else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_PICTURE){
				  
				  drawable = FileBrowserActivity.fileTypeDrawable.get(1);
				  holder.img.setImageDrawable(drawable);
			}
			else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_SONG){
				  
				  drawable = FileBrowserActivity.fileTypeDrawable.get(2);
				  holder.img.setImageDrawable(drawable);
			}
			else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_DIR){
				  
				  drawable = FileBrowserActivity.fileTypeDrawable.get(4);
				  holder.img.setImageDrawable(drawable);
			}
			else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_RETURN){
				  
				  drawable = FileBrowserActivity.fileTypeDrawable.get(5);
				  holder.img.setImageDrawable(drawable);
			}
		}
		    
		
		holder.title.setText((String) gridOnePage.get(position).getName());
        if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_VIDEO){
			  
             String url =gridOnePage.get(position).getPath();
				if (cancelPotentialLoad(url, holder.img)) {
			          try{
			 				AsyncLoadImageTask task = new AsyncLoadImageTask(holder.img,0);
	         				LoadedDrawable loadedDrawable = new LoadedDrawable(task);
	         				holder.img.setImageDrawable(loadedDrawable);
	         				task.execute(position);
			 		     }catch(Exception e){
				
								}
	         
				}
	         
	        
		}
		else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_SONG){
	            String url =gridOnePage.get(position).getPath();
				if (cancelPotentialLoad(url, holder.img)) {
			
	         			try{
			 				AsyncLoadImageTask task = new AsyncLoadImageTask(holder.img,1);
	         				LoadedDrawable loadedDrawable = new LoadedDrawable(task);
	         				holder.img.setImageDrawable(loadedDrawable);
	         				task.execute(position);
			 		     }catch(Exception e){
				
								}
					}
				
			}	

				
		return convertView;
	}
	public final class ViewHolder {
		public ImageView img;
		public TextView title;
		//public TextView info;
	}
	private Bitmap getBitmapFromUrl(String url,int fileType){
		
		
		Bitmap bitmap = null;
		mtb= new MediaThumbnail();
	    File file = new File(url);
		if(0==fileType)
			    bitmap = mtb.createVideoThumbnail(file.getAbsolutePath());
		else if(1==fileType)
			    bitmap = mtb.createAlbumThumbnail(file.getAbsolutePath());
	    bitmap=ThumbnailUtils.extractThumbnail(bitmap, 151, 159);
	    //Drawable drawable=new BitmapDrawable(bitmap);
		return bitmap;
	}

	//加载图片的异步任务	
	private class AsyncLoadImageTask extends AsyncTask<Integer, Void, Bitmap>{
		private String url = null;
		private final WeakReference<ImageView> imageViewReference;
		private int fileType;
		
		public AsyncLoadImageTask(ImageView imageview,int fileType) {
			super();
			// TODO Auto-generated constructor stub
			imageViewReference = new WeakReference<ImageView>(imageview);
			this.fileType=fileType;
		}

		@Override
		protected Bitmap doInBackground(Integer... params) {//task.execute(position);来的参数
			// TODO Auto-generated method stub
			Bitmap bitmap = null;
			//this.url = mList.get(params[0]);			
			if(params[0]>=gridOnePage.size()){
                     this.cancel(true);
			}
			else{
                this.url = gridOnePage.get(params[0]).getPath();
			    bitmap = getBitmapFromUrl(url,this.fileType);
			}
			
			//MainActivity.gridviewBitmapCaches.put(mList.get(params[0]), bitmap);			
			return bitmap;
		}
        /*
           在构造函数中建立的一个task->imageview的引用
		*/
		@Override
		protected void onPostExecute(Bitmap resultBitmap) {
			// TODO Auto-generated method stub
			if(isCancelled()){
				resultBitmap = null;
			}
			if(imageViewReference != null){
				ImageView imageview = imageViewReference.get();
				AsyncLoadImageTask loadImageTask = getAsyncLoadImageTask(imageview);
			    // Change bitmap only if this process is still associated with it
			    if (this == loadImageTask) {
			    	imageview.setImageBitmap(resultBitmap);
			    	imageview.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
			    }
			}
			super.onPostExecute(resultBitmap);
		}							
	}
	
	
	private boolean cancelPotentialLoad(String url,ImageView imageview){
		AsyncLoadImageTask loadImageTask = getAsyncLoadImageTask(imageview);

	    if (loadImageTask != null) {
	        String bitmapUrl = loadImageTask.url;
	        if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
	        	loadImageTask.cancel(true);	        	
	        } else {
	            // 相同的url已经在加载中.
	            return false;
	        }
	    }
	    return true;

	}
	
	//当 loadImageTask.cancel(true)被执行的时候,则AsyncLoadImageTask 就会被取消,
	//当AsyncLoadImageTask 任务执行到onPostExecute的时候,如果这个任务加载到了图片,
	//它也会把这个bitmap设为null了。 
	//getAsyncLoadImageTask代码如下:
	private AsyncLoadImageTask getAsyncLoadImageTask(ImageView imageview){
		if (imageview != null) {
			
	        Drawable drawable = imageview.getDrawable();
	        if (drawable instanceof LoadedDrawable) {
	        	
	        	LoadedDrawable loadedDrawable = (LoadedDrawable)drawable;
	            return loadedDrawable.getLoadImageTask();
	        }
	    }
	    return null;
	}

	//该类功能为:记录imageview加载任务并且为imageview设置默认的drawable
	public static class LoadedDrawable extends ColorDrawable{
		private final WeakReference<AsyncLoadImageTask> loadImageTaskReference;

	    public LoadedDrawable(AsyncLoadImageTask loadImageTask) {
	        super(Color.TRANSPARENT);
	        loadImageTaskReference =
	            new WeakReference<AsyncLoadImageTask>(loadImageTask);
	    }

	    public AsyncLoadImageTask getLoadImageTask() {
	        return loadImageTaskReference.get();
	    }

	}

下面是我的理解:

在某任务已经执行
在task类中含有对imageview的弱引用,也就是说当判断一个taskA有没有过时,那么
利用弱引用求出该taskA对应的imageview,然后再用imageview求出其对应的当前的taskB,
如果tashA,taskB不对等的话,则会取消taskA,因为taskB才是该Imageview最新的task。
getAsyncLoadImageTask就是通过该Imageview的Drawable属于LoadedDrawable类的实例,也就是对象,是的话
则获取其对应的弱引用:task。
上面这一句话不是很理解:但我认为是holder.img.setImageDrawable(loadedDrawable);之后的结果。
cancelPotentialLoad:
在准备执行某个Imageview的任务的时候,如果该Imageview的url已经在加载,那么就不必再加载了。
在什么时候会出现这样的情况呢?在一个不断上下滑动,或者不断上下翻页的情况出现。比如1212121212(页数)





onpostexcute的if(imageViewReference != null):
就是在执行完毕的时候,对于某个Imageview,选择哪一个task的结果来显示。
在什么时候会出现这样的情况呢?在一个ImageView的可能会先显示上一个task的结果,然后再显示当前task的结果。
显然这不是我们想要的结果,直接显示当前task的结果是我们期望的结果。
有同学说cancelPotentialLoad里面if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
        loadImageTask.cancel(true);        
       }
不是已经杜绝了这种情况么?我现在只能理解在复杂的多线程中进一步检查一遍


另外因为上面的代码对于我来说还差点实用性,也有点难理解,不好维护,主要是最后一个函数

所以我自己写了一个

public class GridAdapter extends BaseAdapter {
	private MediaThumbnail mtb;
	private final static String TAG="GridAdapter";
	private LayoutInflater mInflater;
	private ArrayList<BaseData> gridOnePage = new ArrayList<BaseData>();
	private Resources resourceGrid;
	private static int thumbnailVideoOrMusic=-100;
	//ArrayList<AsyncLoadImageTask> imagePosition2Task = new ArrayList<AsyncLoadImageTask>();
	public static AsyncLoadImageTask imagePosition2Task[] = new AsyncLoadImageTask[24+1];
	public static int isFinish[] =new int[24+1];
	public static ImageView ivHasCancelTask[]=new ImageView[24+1];
	public GridAdapter(Context context,ArrayList<BaseData>gridOnePage) {
		this.mInflater = LayoutInflater.from(context);
		this.gridOnePage=gridOnePage;
	}
    public GridAdapter(){}
	public int getCount() {
		//return mData.size();
		if(gridOnePage==null)
			  return 0;
		return gridOnePage.size();
	}

	public Object getItem(int arg0) {
		return null;
	}

	public long getItemId(int arg0) {
		return 0;
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder = null;
		if (convertView == null) {
			holder = new ViewHolder();
			convertView = mInflater.inflate(R.layout.gridview_item, null);
			holder.img = (ImageView) convertView.findViewById(R.id.img);
			holder.title = (TextView) convertView.findViewById(R.id.title);
			//holder.info = (TextView) convertView.findViewById(R.id.info);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}
        if(gridOnePage.get(position).getType() == Constants.FILE_TYPE_VIDEO){
			Drawable drawable =null;
			drawable = FileBrowserActivity.fileTypeDrawable.get(3);
				  holder.img.setImageDrawable(drawable);
				  isFinish[position]=-1;
		}
		
		else{
			Drawable drawable =null;
			if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_FILE){
				  imagePosition2Task[position]=null;
				  drawable = FileBrowserActivity.fileTypeDrawable.get(0);
				  holder.img.setImageDrawable(drawable);
				  isFinish[position]=1;
			}
			else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_PICTURE){
				  imagePosition2Task[position]=null;
				  drawable = FileBrowserActivity.fileTypeDrawable.get(1);
				  holder.img.setImageDrawable(drawable);
				  isFinish[position]=1;
			}
			else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_SONG){
				  
				  drawable = FileBrowserActivity.fileTypeDrawable.get(2);
				  holder.img.setImageDrawable(drawable);
				  isFinish[position]=1;
			}
			else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_DIR){
				  imagePosition2Task[position]=null;
				  drawable = FileBrowserActivity.fileTypeDrawable.get(4);
				  holder.img.setImageDrawable(drawable);
				  isFinish[position]=1;
			}
			else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_RETURN){
				  imagePosition2Task[position]=null;
				  drawable = FileBrowserActivity.fileTypeDrawable.get(5);
				  holder.img.setImageDrawable(drawable);
				  isFinish[position]=1;
			}
		}
		    
		
		holder.title.setText((String) gridOnePage.get(position).getName());
        if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_VIDEO){
                String url =gridOnePage.get(position).getPath();
			if(cancelPotentialLoad(url, position)){
		    try{
				AsyncLoadImageTask task = new AsyncLoadImageTask(holder.img,0);
				imagePosition2Task[position]=task;
				ivHasCancelTask[position]=holder.img;
				task.execute(position);
				}
			     catch (Exception e) {   Log.e("error", e.toString());}
			}
				
		}
		else if(gridOnePage.get(position).getType()==Constants.FILE_TYPE_SONG){
		            String url =gridOnePage.get(position).getPath();
					if(cancelPotentialLoad(url, position)){
			        try{
						AsyncLoadImageTask task = new AsyncLoadImageTask(holder.img,1);
						imagePosition2Task[position]=task;
						task.execute(position);
						}catch(Exception e) {   Log.e("error", e.toString());  }
				
				    }
			}		
		return convertView;
	}


	public AsyncLoadImageTask createTaskObject(ImageView imageview,int fileType){
           AsyncLoadImageTask task = new AsyncLoadImageTask(imageview,fileType);
		   return task;
	}
	public final class ViewHolder {
		public ImageView img;
		public TextView title;
		//public TextView info;
	}
	private Drawable getBitmapFromUrl(String url,int filetype){
		
		
		
		Bitmap bitmap = null;
		mtb= new MediaThumbnail();
	    File file = new File(url);
		//Log.i(TAG, "-------getBitmapFromUrl------thumbnailVideoOrMusic:"+String.valueOf(thumbnailVideoOrMusic)+
			//"------fileUrl-------:"+file.getAbsolutePath());
		if(0==filetype){
              bitmap = mtb.createVideoThumbnail(file.getAbsolutePath());
		}
     	
		else if(1==filetype){
              bitmap = mtb.createAlbumThumbnail(file.getAbsolutePath());
		}
		
	    bitmap=ThumbnailUtils.extractThumbnail(bitmap, 380, 380);
		if(bitmap == null){
               //Log.i(TAG,"----ThumbnailUtils.extractThumbnail-bitmap--NULL");
			}
			else{
				//Log.i(TAG,"----ThumbnailUtils.extractThumbnail-bitmap-NOT-NULL");
				}
        if(bitmap == null) return null;
		Drawable drawable=new BitmapDrawable(bitmap);
		//return bitmap;
		return drawable;
	}
   
	public class AsyncLoadImageTask extends AsyncTask<Integer, Void, Drawable>{
		private String url = null;
		private final WeakReference<ImageView> imageViewReference;
		private ImageView iv;
		private int taskPos;
		private int fileType;//video is 0 and music is 1
		public AsyncLoadImageTask(ImageView imageview,int fileType) {
			super();
			// TODO Auto-generated constructor stub
			this.iv=imageview;
			this.fileType=fileType;
			imageViewReference = new WeakReference<ImageView>(imageview);
			
		}

		@Override
		protected Drawable doInBackground(Integer... params) {//task.execute(position);来的参数
			Log.i(TAG, "-------doInBackground");
			// TODO Auto-generated method stub
			Drawable drawable = null;
            if(params[0]>=gridOnePage.size()){
				     //Log.i(TAG,"--doInBackground--params[0]--gridOnePage.size()"+
					 	//String.valueOf(params[0])+"--"+String.valueOf(gridOnePage.size()));
                     this.cancel(true);
			}else{
			   //Log.i(TAG, "-------params[0]<gridOnePage.size()----");
			   this.taskPos =	params[0];
			   this.url = gridOnePage.get(params[0]).getPath();
			   drawable = getBitmapFromUrl(this.url,this.fileType);
		
				}
			
							
			return drawable;
		}
		@Override
		protected void onPostExecute(Drawable resultDrawable) {
            //Log.i(TAG,"------onPostExecute---this.taskPos---"+String.valueOf(this.taskPos));
			
			if(isCancelled())resultDrawable = null;
			if(imageViewReference != null){
               ImageView imageview = imageViewReference.get();
               AsyncLoadImageTask loadImageTask =imagePosition2Task[this.taskPos] ;
			   if(loadImageTask==null){
                 //Log.i(TAG,"---loadImageTask==null---");			   	                        
			   }else{
                 //Log.i(TAG,"---loadImageTask---not null----loadImageTask.url--"+loadImageTask.url);
			   }
               if (this == loadImageTask && resultDrawable!=null) {
               //Log.i(TAG,"------draw the image---this.taskPos---"+String.valueOf(this.taskPos));			   	      
                     iv.setImageDrawable(resultDrawable);
                     
               }
            }
			/*
			if(resultDrawable==null){
                Log.i(TAG, "#######000-------onPostExecute---positionDebug:"+String.valueOf(positionDebug));
			}
			else{
                Log.i(TAG, "#######111-------onPostExecute---positionDebug:"+String.valueOf(positionDebug));
                iv.setImageDrawable(resultDrawable);
			}*/
			isFinish[this.taskPos]=1;
			
		    
            
			super.onPostExecute(resultDrawable);
		}	
		
		 protected void onPreExecute () {
			   //Log.i(TAG, "-------onPreExecute");
         }  
	}
	private boolean cancelPotentialLoad(String url,int position){
		AsyncLoadImageTask loadImageTask = imagePosition2Task[position];

	    if (loadImageTask != null) {
	        String bitmapUrl = loadImageTask.url;
	        if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
	        	loadImageTask.cancel(true);	        	
	        } else {
	            // 相同的url已经在加载中.
	            return false;
	        }
	    }
	    return true;

	}

	
}


小结:其实对于弱引用,我在这里没必要用,因为我做的是gridview分页,所以不会轻易出现out of memory的问题(一页显示12个),另外对于asynctask中的弱引用我保留了但是丢弃了LoadedDrawable类,因为这只是一个记录的作用。所以我用了数组来模拟,简单粗暴,暂时没发现什么问题。

<span style="font-family:Comic Sans MS;">imagePosition2Task[position];</span>
在这个数组中,我用每个Imageview的pisition来记录每个Imageview,装的是其最新的task对象。

asynctask中的弱引用保留时因为要找到正在运行的task对应的Imageview,所以上面代码实现了两边互相映射

我也建立了互相映射。


PS:如有侵权,联系我删掉。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值