博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Scrollview嵌套下listView动态加载数据,解决onScrollChanged执行多次数据重复问题...
阅读量:5272 次
发布时间:2019-06-14

本文共 8463 字,大约阅读时间需要 28 分钟。

这一篇博客和上一篇讲的都是listView的动态加载,但有所不同的是,本篇的listView是嵌套在ScrollView下的,有时候在一个Activity中可能分为好几个模块,由于展示的需要(手机屏幕大小有限),我们需要在这些模块的外层嵌套ScrollView,这时候我们就不能根据listView的状态来监听是否需要加载数据啦,但是转念一想,我们可以监听scrollview,但scrollview滑动到最底部时,那listview肯定也滑动到底部啦。思路确定啦,但是在开发的过程中发现了一个bug,listView有时候会加载重复的数据,搞的莫名其妙,后来经过查资料得知在ScrollView滑动中,onScrollChanged总是在不停被调用,导致多次向服务器端请求同样的数据,这时候就需要我们自己做并发控制

ZdyListView

1 package com.example.listview; 2  3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.view.LayoutInflater; 6 import android.view.View; 7 import android.widget.ListView; 8 import android.widget.ProgressBar; 9 import android.widget.TextView;10 11 /**12  * Created by keranbin on 2015/10/25.13  */14 public class ZdyListView extends ListView {15     private Context context;16     private View footer;17     private ProgressBar progressBar; 18     private TextView tv;19 20     public ZdyListView(Context context) {21         super(context);22         init(context);23     }24     public ZdyListView(Context context, AttributeSet attrs) {25         super(context, attrs);26         init(context);27     }28     public ZdyListView(Context context, AttributeSet attrs, int defStyle) {29         super(context, attrs, defStyle);30         init(context);31     }32     private void init(Context context) {33         this.context=context;34         footer=LayoutInflater.from(context).inflate(R.layout.activity_footer, null);35         this.addFooterView(footer);36         progressBar=(ProgressBar) footer.findViewById(R.id.progressBar);37         tv=(TextView) footer.findViewById(R.id.tv);38         tv.setText("上拉加载更多");39     }40 41     //正在加载数据,将listview底部提示文字置为"正在加载中。。。。"42     public void onLoading(){43         progressBar.setVisibility(VISIBLE);44         tv.setText("正在加载中。。。。");45     }46 47     //加载完毕,将listView底部提示文字改为"上拉加载更多"48     public void LoadingComplete(){49         progressBar.setVisibility(GONE);50         tv.setText("上拉加载更多");51     }52 53     54     //重写onMeasure,解决scrollview与listview冲突55     @Override56     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {57         int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,58                 MeasureSpec.AT_MOST);59         super.onMeasure(widthMeasureSpec, expandSpec);60     }61 62 63 64 }

 

ZdyScrollView

1 package com.example.listview; 2  3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.view.View; 6 import android.widget.ScrollView; 7  8 public class ZdyScrollView extends ScrollView{ 9     private int flag=0;    //并发控制标志位10 11     private OnZdyScrollViewListener onZdyScrollViewListener;12 13     public ZdyScrollView(Context context) {14         super(context);15     }16 17     public ZdyScrollView(Context context, AttributeSet attrs) {18         super(context, attrs);19     }20 21     public ZdyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {22         super(context, attrs, defStyleAttr);23     }24 25     //listview加载完毕,将并发控制符置为026     public void loadingComponent(){27         flag=0;28     }29 30     @Override31     protected void onScrollChanged(int l, int t, int oldl, int oldt) {32         super.onScrollChanged(l, t, oldl, oldt);33         View view=this.getChildAt(0);34         //如果scrollview滑动到底部并且并发控制符为0,回调接口向服务器端请求数据35         if (this.getHeight() + this.getScrollY() == view.getHeight() && flag == 0) {36             flag = 1;//一进来就将并发控制符置为1,虽然onScrollChanged执行多次,但是由于并发控制符的值为1,不满足条件就不会执行到这37             onZdyScrollViewListener.ZdyScrollViewListener();38         }39     }40 41     public void setOnZdyScrollViewListener(OnZdyScrollViewListener onZdyScrollViewListener){42         this.onZdyScrollViewListener=onZdyScrollViewListener;43     }44 45     public interface OnZdyScrollViewListener{46         public void ZdyScrollViewListener();47     }48 49 }

 

MainActivity

1 package com.example.listview;  2   3 import java.util.ArrayList;  4   5 import com.example.listview.ZdyScrollView.OnZdyScrollViewListener;  6   7 import android.app.Activity;  8 import android.os.Bundle;  9 import android.os.Handler; 10 import android.os.Message; 11  12  13 public class MainActivity extends Activity { 14  15     private ZdyScrollView scrollView; 16     private ZdyListView listView; 17     private ListViewAdapter adapter; 18      19     //一次从服务器端请求十条数据 20     private int current=1;   21     private int number=9; 22      23     ArrayList
listDatas; 24 25 private Handler handler=new Handler(){ 26 public void handleMessage(Message msg) { 27 setListView((ArrayList
)msg.obj); 28 } 29 }; 30 31 32 @Override 33 protected void onCreate(Bundle savedInstanceState) { 34 super.onCreate(savedInstanceState); 35 setContentView(R.layout.activity_main); 36 initView(); 37 initListener(); 38 } 39 40 41 @Override 42 protected void onStart() { 43 super.onStart(); 44 //第一次请求数据 45 getDataThread(current,number); 46 } 47 48 49 50 private void initView() { 51 listView=(ZdyListView) this.findViewById(R.id.listView); 52 scrollView=(ZdyScrollView) this.findViewById(R.id.scrollView); 53 54 } 55 56 private void initListener() { 57 scrollView.setOnZdyScrollViewListener(new OnZdyScrollViewListener() { 58 @Override 59 public void ZdyScrollViewListener() { 60 //上拉加载更多数据 61 getDataThread(current,number); 62 } 63 }); 64 65 } 66 67 68 private void setListView(ArrayList
datas) { 69 if(listDatas==null){
//第一次加载数据,为listview设置适配器 70 listDatas=new ArrayList
(); 71 listDatas.addAll(datas); 72 adapter=new ListViewAdapter(MainActivity.this,listDatas); 73 listView.setAdapter(adapter); 74 current=adapter.getCount()+1; //记录当前listview中的最后一个数据的下标 75 listView.LoadingComplete(); //告诉listview已经加载完毕,重置提示文字 76 scrollView.loadingComponent();//告示scrollview已经加载完毕,重置并发控制符的值 77 }else{
//下拉加载更多数据,只需要告诉adapter刷新就行 78 listDatas.addAll(datas); 79 adapter.notifyDataSetChanged(); 80 current=adapter.getCount()+1; 81 listView.LoadingComplete(); 82 scrollView.loadingComponent(); 83 } 84 85 }; 86 87 private void getDataThread(final int current, final int number){ 88 final Message msg=new Message(); 89 listView.onLoading(); 90 new Thread(){ 91 public void run() { 92 try {
//模拟向服务器请求数据耗时 93 sleep(10000); 94 } catch (InterruptedException e) { 95 e.printStackTrace(); 96 } 97 ArrayList
datas=ListViewDatas.returnNum(current, current+number); 98 if(datas!=null&&datas.size()>0){ 99 msg.obj=datas;100 handler.sendMessage(msg);101 }102 };103 }.start();104 }105 106 }

模拟服务器端发回数据ListViewDatas

1 package com.example.listview; 2  3 import java.util.ArrayList; 4  5 public class ListViewDatas { 6     //模拟服务器端数据库中的数据,假设现在只有3条数据 7     public static int NUM=53; 8     public static ArrayList
returnNum(int startNum,int endNum){ 9 ArrayList
list=new ArrayList
();10 if(endNum<=NUM){
//客户端请求的数据在数据库数据范围之内11 for(int i=startNum;i<=endNum;i++){12 list.add(String.valueOf(i));13 }14 return list;15 }else if(endNum>=NUM&&startNum<=NUM){
//客户端请求的数据不全在数据库数据范围之内16 for(int i=startNum;i<=NUM;i++){17 list.add(String.valueOf(i));18 }19 return list; 20 }else if(startNum>NUM){
//客户端请求的数据超出数据库数据范围之内21 return null;22 }23 return null;24 }25 }

页面布局activity_main.xml

1 
5 6
10 11
15 16
17 18

listView的footView  activity_footer.xml

1 
2
6 7
15 16
22 23
28 29
30 31

 

转载于:https://www.cnblogs.com/bdsdkrb/p/5070891.html

你可能感兴趣的文章
Idea搭建Spring Boot框架,结合jpa实现增删改查
查看>>
请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1...
查看>>
关于全排列算法
查看>>
腾讯结盟HTC定制社交机 整合多种应用
查看>>
JS读写Cookie
查看>>
Android使用ContentObserver监听数据库变化
查看>>
SharePoint 2013: Knockout JS + Rest Service展示List数据
查看>>
页面缓存清除在浏览器加以下代码
查看>>
NSURLSession
查看>>
分享接私活心得(公司内部私活),晒晒私活成果[原创]
查看>>
Map集合中value()方法与keySet()、entrySet()区别
查看>>
不仅仅是写代码,而是完成作品
查看>>
C#开发Unity游戏教程之Scene视图与脚本的使用
查看>>
rsync入门
查看>>
认清性能问题
查看>>
jQuery源码分析--Event模块(2)
查看>>
BZOJ1121: [POI2008]激光发射器SZK
查看>>
BZOJ1093: [ZJOI2007]最大半连通子图
查看>>
BZOJ2656: [Zjoi2012]数列(sequence)
查看>>
BZOJ3438: 小M的作物
查看>>