对一个gridview异步加载大量图片的实例的个人理解
2015-01-07 17:51
357 查看
首先贴上原代码地址:链接
然后是在自己代码中的运用
下面是我的理解:
在某任务已经执行
在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);
}
不是已经杜绝了这种情况么?我现在只能理解在复杂的多线程中进一步检查一遍
另外因为上面的代码对于我来说还差点实用性,也有点难理解,不好维护,主要是最后一个函数
所以我自己写了一个
小结:其实对于弱引用,我在这里没必要用,因为我做的是gridview分页,所以不会轻易出现out of memory的问题(一页显示12个),另外对于asynctask中的弱引用我保留了但是丢弃了LoadedDrawable类,因为这只是一个记录的作用。所以我用了数组来模拟,简单粗暴,暂时没发现什么问题。
asynctask中的弱引用保留时因为要找到正在运行的task对应的Imageview,所以上面代码实现了两边互相映射
我也建立了互相映射。
PS:如有侵权,联系我删掉。
然后是在自己代码中的运用
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:如有侵权,联系我删掉。
相关文章推荐
- Android完美解决GridView异步加载图片和加载大量图片时出现Out Of Memory问题
- 利用LruCache为GridView异步加载大量网络图片完整示例
- Android完美解决GridView异步加载图片和加载大量图片时出现Out Of Memory问题
- 利用LruCache为GridView异步加载大量网络图片完整示例
- Android完美解决GridView异步加载图片和加载大量图片时出现Out Of Memory问题
- 利用LruCache为GridView异步加载大量网络图片完整示例
- Android GridView异步加载图片和加载大量图片时出现Out Of Memory问题
- Android完美解决GridView异步加载图片和加载大量图片时出现OOM
- Android-GridView 实例(异步加载,LruCache缓存,图片请求,图片压缩)
- GridView使用AsyncTask模拟异步加载大量图片
- Android解决GridView异步加载大量图片时出现Out Of Memory问题00M
- LruCache为GridView异步加载大量网络图片
- ListView与GridView异步加载图片
- Android GridView 异步加载图片
- 演化理解 Android 异步加载图片
- 演化理解 Android 异步加载图片
- android之GridView异步加载图片时显示加载进度ProgressBar
- 演化理解 Android 异步加载图片
- 演化理解 Android 异步加载图片
- 演化理解 Android 异步加载图片