一般的关于Adapter中getView的写法不外乎以下形式:

@Overridepublic

ViewgetView(int position, View convertView, ViewGroup parent)

{

ViewHolder holder;

if (convertView == null)

{

convertView = mLayout.inflate(R.layout....);

holder =new ViewHolder();

holder.textView = (TextView) convertView.findViewById(R.id.textview);

... ...

convertView.setTag(holder);

}

else {

holder = (ViewHolder) convertView.getTag();

}

holder.textView.setText(mText + position);

return convertView;

}

在Android源码中关于getView方法的实现就是采用的以上形式,如ArrayAdapter等。因为这种写法的好处也是显而易见的,如果该position的convertview曾经被加载过,在数据集合未被改动的前提下,系统会自动将该position的convertview缓存起来,避免重复加载耗费资源。

我自己的代码:

@Override
public View getView(int position, View view, ViewGroup parent) {final ViewHolder mViewHolder;if(null == view){mViewHolder = new ViewHolder();view = LayoutInflater.from(mContext).inflate(R.layout.fragment_new_order_list_item, null);mViewHolder.txtPaystatus = (TextView) view.findViewById(R.id.order_pay_status);mViewHolder.txtOrdertime = (TextView) view.findViewById(R.id.order_time);mViewHolder.txtCustomerName = (TextView) view.findViewById(R.id.customer_name);mViewHolder.txtCustomerAddress = (TextView) view.findViewById(R.id.customer_address);mViewHolder.txtOrderSendTime = (TextView) view.findViewById(R.id.customer_post_time);mViewHolder.txtOrderGoodsDes = (TextView) view.findViewById(R.id.customer_list_goods_des);mViewHolder.txtCustomerPhone = (TextView) view.findViewById(R.id.customer_phone);mViewHolder.btnOrderOk = (Button) view.findViewById(R.id.order_ok);mViewHolder.btnOrderCancel = (Button) view.findViewById(R.id.order_cancel);mViewHolder.listgoods = (ListView) view.findViewById(R.id.customer_list_goods);if(listOrder.get(position).getPaystatus() == 0){mViewHolder.txtPaystatus.setText("未付款");}else
        {mViewHolder.txtPaystatus.setText("已付款");}mViewHolder.txtOrdertime.setText(listOrder.get(position).getOrdertime());mViewHolder.txtCustomerName.setText(listOrder.get(position).getAcceptname());mViewHolder.txtCustomerAddress.setText(listOrder.get(position).getAcceptlocation());mViewHolder.txtOrderSendTime.setText(listOrder.get(position).getGoodsarrivetime());mViewHolder.txtOrderGoodsDes.setText(listOrder.get(position).getOrderSeller().getRemark());mViewHolder.txtCustomerPhone.setText(listOrder.get(position).getAcceptphonenum());OrderGoodsListItemAdapter mOrderGoodsListItemAdapter = new OrderGoodsListItemAdapter(mContext,listOrder.get(position).getOrderSeller().getLstOrderGoods());mViewHolder.listgoods.setAdapter(mOrderGoodsListItemAdapter);setListViewHeightOnChildren(mViewHolder.listgoods);final int index = position;mViewHolder.btnOrderOk.setOnClickListener(new View.OnClickListener(){@Override
            public void onClick(View v) {String sellerorderid = String.valueOf(listOrder.get(index).getOrderSeller().getSellerorderid());String token = App.getInstance().sellerInfo.getToken();orderService.modifyOrder(sellerorderid, "1", token).subscribe(new Action1<String>() {@Override
                            public void call(String s) {Toast.makeText(mContext, s, Toast.LENGTH_SHORT).show();newOrderFragment.listOrder.clear();newOrderFragment.pageindex = 1;newOrderFragment.requestData();App.isNeedFreshData = true;App.isNeedFresShophData = true;}}, new Action1<Throwable>() {@Override
                            public void call(Throwable throwable) {Toast.makeText(mContext, throwable.getMessage(), Toast.LENGTH_SHORT).show();}});}});mViewHolder.btnOrderCancel.setOnClickListener(new View.OnClickListener(){@Override
            public void onClick(View v) {String sellerorderid = String.valueOf(listOrder.get(index).getOrderSeller().getSellerorderid());String token = App.getInstance().sellerInfo.getToken();orderService.modifyOrder(sellerorderid, "2", token).subscribe(new Action1<String>() {@Override
                            public void call(String s) {Toast.makeText(mContext, s, Toast.LENGTH_SHORT).show();newOrderFragment.listOrder.clear();newOrderFragment.pageindex = 1;newOrderFragment.requestData();App.isNeedFreshData = true;App.isNeedFresShophData = true;}}, new Action1<Throwable>() {@Override
                            public void call(Throwable throwable) {Toast.makeText(mContext, throwable.getMessage(), Toast.LENGTH_SHORT).show();}});}});view.setTag(mViewHolder);}else
    {mViewHolder = (ViewHolder) view.getTag();}return view;
}

然后问题就来了,当时我就”自作小聪明“或者说“没有注意”,觉得当convertview==null时只是做了item布局的加载以及相关控件ID的绑定操作,为什么连内容的加载操作也放入其中呢,这样下次加载缓存是就省去内容set的操作了,然后就出现了滑动ListView后数据显示错位的问题。

剖析原因:

后来看源码发现,原来AbListView中获取getView()和滑动操作是异步进行的,其中滑动操作在一个FlingRunnable的支线程中运行,所以这就导致了在ListView在滑动时可能已经滑动到了第十行,但可能第二行的数据这时就被直接使用了,这就是导致数据加载错乱的根本原因。
附上源码中对FlingRunnable的注释:

/*** Responsible for fling behavior. Use {@link #start(int)} to* initiate a fling. Each frame of the fling is handled in {@link #run()}.* A FlingRunnable will keep re-posting itself until the fling is done.**/
private class FlingRunnable implements Runnable {/*** Tracks the decay of a fling scroll*/private final OverScroller mScroller;... ...
}

解决方法

所以唯一的解决方法就是只在convertview中缓存该ChildView的layout,但ChildView 中的数据必须每次都重新获取并加载。

修改后的代码:

@Override
public View getView(int position, View view, ViewGroup parent) {final ViewHolder mViewHolder;if(null == view){mViewHolder = new ViewHolder();view = LayoutInflater.from(mContext).inflate(R.layout.fragment_new_order_list_item, null);mViewHolder.txtPaystatus = (TextView) view.findViewById(R.id.order_pay_status);mViewHolder.txtOrdertime = (TextView) view.findViewById(R.id.order_time);mViewHolder.txtCustomerName = (TextView) view.findViewById(R.id.customer_name);mViewHolder.txtCustomerAddress = (TextView) view.findViewById(R.id.customer_address);mViewHolder.txtOrderSendTime = (TextView) view.findViewById(R.id.customer_post_time);mViewHolder.txtOrderGoodsDes = (TextView) view.findViewById(R.id.customer_list_goods_des);mViewHolder.txtCustomerPhone = (TextView) view.findViewById(R.id.customer_phone);mViewHolder.btnOrderOk = (Button) view.findViewById(R.id.order_ok);mViewHolder.btnOrderCancel = (Button) view.findViewById(R.id.order_cancel);mViewHolder.listgoods = (ListView) view.findViewById(R.id.customer_list_goods);view.setTag(mViewHolder);}else
    {mViewHolder = (ViewHolder) view.getTag();}if(listOrder.get(position).getPaystatus() == 0){mViewHolder.txtPaystatus.setText("未付款");}else
    {mViewHolder.txtPaystatus.setText("已付款");}mViewHolder.txtOrdertime.setText(listOrder.get(position).getOrdertime());mViewHolder.txtCustomerName.setText(listOrder.get(position).getAcceptname());mViewHolder.txtCustomerAddress.setText(listOrder.get(position).getAcceptlocation());mViewHolder.txtOrderSendTime.setText(listOrder.get(position).getGoodsarrivetime());mViewHolder.txtOrderGoodsDes.setText(listOrder.get(position).getOrderSeller().getRemark());mViewHolder.txtCustomerPhone.setText(listOrder.get(position).getAcceptphonenum());OrderGoodsListItemAdapter mOrderGoodsListItemAdapter = new OrderGoodsListItemAdapter(mContext,listOrder.get(position).getOrderSeller().getLstOrderGoods());mViewHolder.listgoods.setAdapter(mOrderGoodsListItemAdapter);setListViewHeightOnChildren(mViewHolder.listgoods);final int index = position;mViewHolder.btnOrderOk.setOnClickListener(new View.OnClickListener(){@Override
        public void onClick(View v) {String sellerorderid = String.valueOf(listOrder.get(index).getOrderSeller().getSellerorderid());String token = App.getInstance().sellerInfo.getToken();orderService.modifyOrder(sellerorderid, "1", token).subscribe(new Action1<String>() {@Override
                        public void call(String s) {Toast.makeText(mContext, s, Toast.LENGTH_SHORT).show();newOrderFragment.listOrder.clear();newOrderFragment.pageindex = 1;newOrderFragment.requestData();App.isNeedFreshData = true;App.isNeedFresShophData = true;}}, new Action1<Throwable>() {@Override
                        public void call(Throwable throwable) {Toast.makeText(mContext, throwable.getMessage(), Toast.LENGTH_SHORT).show();}});}});mViewHolder.btnOrderCancel.setOnClickListener(new View.OnClickListener(){@Override
        public void onClick(View v) {String sellerorderid = String.valueOf(listOrder.get(index).getOrderSeller().getSellerorderid());String token = App.getInstance().sellerInfo.getToken();orderService.modifyOrder(sellerorderid, "2", token).subscribe(new Action1<String>() {@Override
                        public void call(String s) {Toast.makeText(mContext, s, Toast.LENGTH_SHORT).show();newOrderFragment.listOrder.clear();newOrderFragment.pageindex = 1;newOrderFragment.requestData();App.isNeedFreshData = true;App.isNeedFresShophData = true;}}, new Action1<Throwable>() {@Override
                        public void call(Throwable throwable) {Toast.makeText(mContext, throwable.getMessage(), Toast.LENGTH_SHORT).show();}});}});return view;
}

其实ListView数据加载及数据缓存是比较复杂的,所以以后有机会还是要好好研读源码,这样才能有助于提升自己开发Android的性能和对Android工作的原理的理解。

关于 android listview 加载数据错位(错乱)问题相关推荐

  1. ListView加载图片错位的问题,解决很简单

    能看到这片文章,相信你遇到了ListView获取RecycView加载数据,产生了错乱的情况, 最近项目遇到,需要动态根据服务器返回的图片链接,动态生成图片,并显示的问题, 结果就出现了图片错兰的问题 ...

  2. android progressbar 加载数据,ProgressBar的使用实例

    以下内容有三方式设置进度条 设置一个简单的进度条 布局 android:id="@+id/progressBar" style="?android:attr/progre ...

  3. Android中ListView分页加载数据

    熟悉Android的朋友们都知道,不管是微博客户端还是新闻客户端,都离不开列表组件,可以说列表组件是Android数据展现方面最重要的组件,我们今天就要讲一讲列表组件ListView加载数据的相关内容 ...

  4. [转]ListView滚动到底部自动加载数据

    转自:http://blog.csdn.net/shineflowers/article/details/41744241 在Android中有很多时候会选择用ListView加载数据,有的是分批加载 ...

  5. android异步加载视频缩略图,Android 视频缩略图的缓存机制和异步加载

    关注微信号:javalearns   随时随地学Java 或扫一扫 随时随地学Java 在这次的工作开发项目中,涉及到一个视频缩略图的视频列表:这个在大家看来,制作视频缩略图就是两行代码就搞定的事.确 ...

  6. android 之ListView分页效果以及从网络上加载数据一系列的综合运用

    数据分页策略: <1>:用多少查多少 <2>:全部查询出来,再进行分页处理 数据分页的有关算法: (1):起始索引值 = (当前页-1)*每页显示的记录数 (2):结束索引值 ...

  7. Android Listview滑动时不加载数据,停下来时加载数据,让App更优

    转载:http://blog.csdn.net/yy1300326388/article/details/45153813 数据源配置(Adapter) package com.zhengsongla ...

  8. android listview动态加载数据,ListView动态加载数据

    当listview需要加载的数据过多时,若一次性载入则速度会相当缓慢,影响用户体验,这时候就需要动态加载数据,即每次载入固定长度的数据,android market的listview就是采用这种方式, ...

  9. Android开发之ContentProvider结合LoaderManager加载数据(图文源代码分享)

    ContentProvider作为Android的四大存储方式之一,有着广泛的应用性,它暴露了数据地址,可以让其他应用访问数据,可以用于存储图片.通讯录等信息,这篇博文将详细介绍ContentProv ...

最新文章

  1. aix java home_在AIX环境下安装IBM JDK 1.6的教程
  2. MIT:睡眠不足会让你连路都走不好,但补觉还有救
  3. EXPLAIN 命令详解
  4. mysql主从 1050错误
  5. Multi thread: std::promise
  6. Jquery实现子菜单散开动画
  7. python random random_【python】random与numpy.random
  8. 管理感悟:维护每日工作列表
  9. 基于Python的旅游管理系统-小程序
  10. 学习记录 | ZigBee协议栈实践——串口收发数据
  11. BAT投资AI已超硅谷巨头,北京成风投增长第一城
  12. oppoa5降级教程_OPPO A5官方出厂rom系统刷机包下载_卡刷升级包降级回退包
  13. 对Autorun.inf类U盘病毒的攻防经验总结
  14. vue.js动态计时器_基于Vue.js的Pomodoro技术计时器
  15. python+flask+html/css+mysql+BAE 打造CSDN简历自动生成系统(附网站完全源码)
  16. 日语考级N1~N5各等级证书含金量如何,代表什么水平?有没有必要考?
  17. 系统稳定性(基于matlab求传递函数特征根)
  18. 广东省第四届“强网杯”网络安全大赛(“泄露的秘密WP”)
  19. 2022届秋招,从被拒到上岸 | 谈谈YK菌在2021年的经历与收获
  20. 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 HDU - 2191

热门文章

  1. 修改文件后git只用两步push文件
  2. catboost进行分类并开启GPU模式
  3. Clion this file does not belong to any project target问题解决方案
  4. C++自定义函数实现灰度图转化
  5. 深度学习:用于multinoulli输出分布的softmax单元
  6. df命令---Linux学习笔记
  7. 方法的反射---反射学习笔记(二)
  8. 15分钟构建超低成本数据大屏:DataV + DLA
  9. markDown 语法(个人练习篇)
  10. Unix基本操作指令备忘