ListView适配器
View getView(int position, View convertView, ViewGroup parent);
如下:0-7,android.widget.RelativeLayout@45f94e28的重复调用。
这里就有一个问题:
如果异步显示图片出现,异步图片会覆盖android.widget.RelativeLayout@45f94e28里的图片(异步获取图片再显示肯定慢于直接显示图片)。
如,第一个和最后一个图片相同。
04-27 09:58:10.591: I/onLoad.cpp(487): loading . . . 04-27 09:58:10.591: I/onLoad.cpp(487): Registering fang/android/OS natives 04-27 09:58:10.601: I/onLoad.cpp(487): loaded. 04-27 09:58:10.601: I/os c(487): readdirx dir = /sdcard, filter = 0x0, accept = 0x0, fnmatch_flags = 6 04-27 09:58:10.601: I/os c(487): readdirx = ., type = 4 04-27 09:58:10.601: I/os c(487): readdirx = .., type = 4 04-27 09:58:10.601: I/os c(487): readdirx = LOST.DIR, type = 4 04-27 09:58:10.601: I/os c(487): readdirx = .android_secure, type = 4 04-27 09:58:10.601: I/os c(487): readdirx = Replace Studio.cfg, type = 8 04-27 09:58:10.601: I/os c(487): readdirx = New Folder, type = 4 04-27 09:58:10.601: I/os c(487): readdirx = New FolderscrollTo, type = 4 04-27 09:58:10.601: I/os c(487): readdirx = sf05.jpg, type = 8 04-27 09:58:10.601: I/os c(487): readdirx = 1.jpg, type = 8 04-27 09:58:10.601: I/os c(487): readdirx = DCIM, type = 4 04-27 09:58:10.611: I/os c(487): readdirx = Solid_Explorer_FULL_1.5.6_build68_GCA.apk, type = 8 04-27 09:58:10.611: I/os c(487): readdirx = com.estrongs.android.pop_v3.0.9.0.apk, type = 8 04-27 09:58:10.611: I/os c(487): readdirx = hh, type = 8 04-27 09:58:10.671: D/dalvikvm(487): GC_EXPLICIT freed 527 objects / 28048 bytes in 49ms 04-27 09:58:10.761: D/dalvikvm(487): GC_EXPLICIT freed 195 objects / 8592 bytes in 81ms 04-27 09:58:10.901: D/getView() new(487): 0 = .android_secure, android.widget.RelativeLayout@45f94e28 04-27 09:58:10.921: D/getView() old(487): 1 = DCIM, android.widget.RelativeLayout@45f94e28 04-27 09:58:10.921: D/getView() old(487): 2 = LOST.DIR, android.widget.RelativeLayout@45f94e28 04-27 09:58:10.941: D/getView() old(487): 3 = New Folder, android.widget.RelativeLayout@45f94e28 04-27 09:58:10.941: D/getView() old(487): 4 = New FolderscrollTo, android.widget.RelativeLayout@45f94e28 04-27 09:58:10.960: D/getView() old(487): 5 = 1.jpg, android.widget.RelativeLayout@45f94e28 04-27 09:58:11.021: D/getView() old(487): 6 = Replace Studio.cfg, android.widget.RelativeLayout@45f94e28 04-27 09:58:11.021: D/ImageLoaderThread(487): getDbId : pathEx = /sdcard/1.jpg, id = 0 04-27 09:58:11.091: D/ImageLoaderThread(487): after check the file category and mThumbnailFlag, category = 3, bitmap = android.graphics.Bitmap@45fb8328 04-27 09:58:11.091: D/getView() old(487): 7 = Solid_Explorer_FULL_1.5.6_build68_GCA.apk, android.widget.RelativeLayout@45f94e28 04-27 09:58:11.101: D/ImageLoaderThread(487): after check the file category and mThumbnailFlag, category = 0, bitmap = null 04-27 09:58:11.121: D/ANDROID_LAB(487): pkgParser:android.content.pm.PackageParser@45fba280 04-27 09:58:11.211: D/getView() old(487): 0 = .android_secure, android.widget.RelativeLayout@45f94e28 04-27 09:58:11.271: D/ANDROID_LAB(487): pkg:pl.solidexplorer uid=-1 04-27 09:58:11.311: D/getView() new(487): 1 = DCIM, android.widget.RelativeLayout@45fc3220 04-27 09:58:11.351: D/ANDROID_LAB(487): label=SE管理器 04-27 09:58:11.361: D/getView() new(487): 2 = LOST.DIR, android.widget.RelativeLayout@45fd3068 04-27 09:58:11.381: D/getView() new(487): 3 = New Folder, android.widget.RelativeLayout@45fd6eb8 04-27 09:58:11.411: D/getView() new(487): 4 = New FolderscrollTo, android.widget.RelativeLayout@45fda848 04-27 09:58:11.431: D/getView() new(487): 5 = 1.jpg, android.widget.RelativeLayout@45fde298 04-27 09:58:11.451: D/getView() new(487): 6 = Replace Studio.cfg, android.widget.RelativeLayout@45fe2108 04-27 09:58:11.451: D/ImageLoaderThread(487): after check the file category and mThumbnailFlag, category = 0, bitmap = null 04-27 09:58:11.481: D/getView() new(487): 7 = Solid_Explorer_FULL_1.5.6_build68_GCA.apk, android.widget.RelativeLayout@45fe6418 04-27 09:58:11.571: D/getView() new(487): 0 = .android_secure, android.widget.RelativeLayout@45febd90 04-27 09:58:11.581: D/getView() old(487): 1 = DCIM, android.widget.RelativeLayout@45febd90 04-27 09:58:11.601: D/getView() old(487): 2 = LOST.DIR, android.widget.RelativeLayout@45febd90 04-27 09:58:11.601: D/getView() old(487): 3 = New Folder, android.widget.RelativeLayout@45febd90 04-27 09:58:11.611: D/getView() old(487): 4 = New FolderscrollTo, android.widget.RelativeLayout@45febd90 04-27 09:58:11.621: D/getView() old(487): 5 = 1.jpg, android.widget.RelativeLayout@45febd90 04-27 09:58:11.631: D/getView() old(487): 6 = Replace Studio.cfg, android.widget.RelativeLayout@45febd90 04-27 09:58:11.631: D/ImageLoaderThread(487): after check the file category and mThumbnailFlag, category = 0, bitmap = null 04-27 09:58:11.651: D/getView() old(487): 7 = Solid_Explorer_FULL_1.5.6_build68_GCA.apk, android.widget.RelativeLayout@45febd90
初步(重用时可能失效,不好)
private View lastConvertView;
if (lastConvertView == convertView) {
//不准,如数据更新后
Log.d("lastConvertView", position + " at (" + mListView.getFirstVisiblePosition() + ", " + mListView.getLastVisiblePosition() );
//防止重用,新出现的itemView复用消失的itemView
//if(postion > mListView.getFirstVisiblePosition() && postion < mListView.getLastVisiblePosition())
return convertView;
}
}
lastConvertView = convertView;
//下面更新convertView
新出现的itemView重用消失的itemView时直接返回old itemView而没有更新数据,造成和错误。
解决(代码截图):
//用于判断重复调用 private View mLastConvertView; // public View getView(int position, View convertView, ViewGroup parent){ //代码片段 //更新图片时判断 //Drawable loadLazyImage(String path, boolean bLoadAsyn) = LoadCacheImage(); -> if(bLoadAsyn) LoadAsynImage(); -> LoadDefault(); Drawable dr = mImageLoader.loadLazyImage(filePathName, mLastConvertView == convertView); holder.icon.setBackgroundDrawable(dr); mLastConvertView = convertView; }
//ListView listView, //滚动监听,ListView的防止重用机制,让我们在getView中误判listView.setOnScrollListener(new OnScrollListener(){@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// TODO Auto-generated method stubmLastConvertView = null;}});
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if(lastConvertView != convertView) { mImageLoader.removeRequest(holder);
Drawable dr = mImageLoader.loadLazyImage(filePathName, holder, stat, position);holder.icon.setBackgroundDrawable(dr);lastConvertView = convertView;}return convertView;}// /AbsListView.OnScrollListener@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {lastConvertView = null;switch (scrollState) {case AbsListView.OnScrollListener.SCROLL_STATE_FLING:mImageLoader.pause();break;case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:mImageLoader.resume();break;case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:mImageLoader.pause();break;default:break;}}holder.icon.setTag("唯一标记");//在异步中把这个唯一标记也随任务一起发送,然后发给主线程中检测是否holder.icon.setTag是否等于任务中一起发的
SDK的代码ListView
/** * Measures the height of the given range of children (inclusive) and * returns the height with this ListView's padding and divider heights * included. If maxHeight is provided, the measuring will stop when the * current height reaches maxHeight. * * @param widthMeasureSpec The width measure spec to be given to a child's * {@link View#measure(int, int)}. * @param startPosition The position of the first child to be shown. * @param endPosition The (inclusive) position of the last child to be * shown. Specify {@link #NO_POSITION} if the last child should be * the last available child from the adapter. * @param maxHeight The maximum height that will be returned (if all the * children don't fit in this value, this value will be * returned). * @param disallowPartialChildPosition In general, whether the returned * height should only contain entire children. This is more * powerful--it is the first inclusive position at which partial * children will not be allowed. Example: it looks nice to have * at least 3 completely visible children, and in portrait this * will most likely fit; but in landscape there could be times * when even 2 children can not be completely shown, so a value * of 2 (remember, inclusive) would be good (assuming * startPosition is 0). * @return The height of this ListView with the given children. */ final int measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition, final int maxHeight, int disallowPartialChildPosition) { final ListAdapter adapter = mAdapter; if (adapter == null) { return mListPadding.top + mListPadding.bottom; } // Include the padding of the list int returnedHeight = mListPadding.top + mListPadding.bottom; final int dividerHeight = ((mDividerHeight > 0) && mDivider != null) ? mDividerHeight : 0; // The previous height value that was less than maxHeight and contained // no partial children int prevHeightWithoutPartialChild = 0; int i; View child; // mItemCount - 1 since endPosition parameter is inclusive endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition; final AbsListView.RecycleBin recycleBin = mRecycler; final boolean recyle = recycleOnMeasure(); final boolean[] isScrap = mIsScrap; for (i = startPosition; i <= endPosition; ++i) { child = obtainView(i, isScrap); measureScrapChild(child, i, widthMeasureSpec); if (i > 0) { // Count the divider for all but one child returnedHeight += dividerHeight; } // Recycle the view before we possibly return from the method if (recyle && recycleBin.shouldRecycleViewType( ((LayoutParams) child.getLayoutParams()).viewType)) { recycleBin.addScrapView(child, -1); } returnedHeight += child.getMeasuredHeight(); if (returnedHeight >= maxHeight) { // We went over, figure out which height to return. If returnedHeight > maxHeight, // then the i'th position did not fit completely. return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1) && (i > disallowPartialChildPosition) // We've past the min pos && (prevHeightWithoutPartialChild > 0) // We have a prev height && (returnedHeight != maxHeight) // i'th child did not fit completely ? prevHeightWithoutPartialChild : maxHeight; } if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) { prevHeightWithoutPartialChild = returnedHeight; } } // At this point, we went through the range of children, and they each // completely fit, so return the returnedHeight return returnedHeight; }