ListView使用getView问题

ListView适配器

View getView(int position, View convertView, ViewGroup parent);


一般布局时获取每一项View出现,调用多次,并且会使用同一个convertView来measure高度。
如下: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);
                        holder.icon.setTag("唯一标记");//在异步中把这个唯一标记也随任务一起发送,然后发给主线程中检测是否holder.icon.setTag是否等于任务中一起发的
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;}}





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;
    }







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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值