整体思路
1.当前Activity implements AbsListView.OnScrollListener
2.实现接囗的方法
3.listView注册滚动监听
4.Adapter中添加增加数据的函数
5.获得2页以后的数据后,adapter增加数据,并刷新notifyDataSetChanged();
实现步骤
/第一步:新建News类(也可从网络或数据库获取),初始化数据。/
// 创建News 类,单独文件
public class News {
String title;
String content;
}
// 初始化数据,该demo为静态,大项目数据来自数据库等其他地方。Activity 中的代码
private int index = 1;
private void initData(){
/**
* @Description: 这是一个方法,声明初始化数据方法
*/
for (int i = 0;i < 10;i++){
News n = new News();
n.title = "title--"+index;
n.content = "content--"+index;
index++;
// 添加到Vector<News> news 中。
news.add(n);
}
}
/第二步:自定义适配器填充数据,convertView减少对象的创建,ViewHolder减少组件的查找/
static class MyAdapter extends BaseAdapter{
/**
* @Description: 这是一个静态内部类,自定义适配器
*/
private Context context;
public MyAdapter(Context context){
this.context = context;
}
@Override
public int getCount() {
return news.size();
}
@Override
public Object getItem(int position) {
return news.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
// viewHolder 减少组件的查询,尽量减少到只查询一屏数量的次数
ViewHolder viewHolder;
// convertView 减少对象的创建,只创建一屏的空间再反复利用
if(convertView==null){
LayoutInflater layoutInflater = LayoutInflater.from(context);
convertView = layoutInflater.inflate(R.layout.list_item_12,null);
viewHolder = new ViewHolder();
viewHolder.textView_title = convertView.findViewById(R.id.textView_title);
viewHolder.textView_content = convertView.findViewById(R.id.textView_content);
// 将viewHolder 存在converView
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
// 获取数据,取静态成员属性 news (第一步中的)的一个数据存入局部变量 n 中,再映射到页面去。
News n = news.get(position);
viewHolder.textView_title.setText(n.title);
viewHolder.textView_content.setText(n.content);
return convertView;
}
static class ViewHolder{
/**
* @Description: 这是一个静态内部类,减少组件的查询。
*/
TextView textView_title;
TextView textView_content;
}
}
/第三步:创建模拟加载数据的线程,再次加载数据,利用handler 多线程交互/
class LoadDataThread extends Thread{
/**
* @Description: 这是一个子线程,用于动态显示加载数据。
* 子线程不能直接与主线程通信。
* 线程之间的通信的机制:Handler
*/
@Override
public void run(){
initData();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 不能让子线程通知主线程数据改变数据集,让主线程自己更新数据集。
// myAdapter.notifyDataSetInvalidated();
// 通过handler 给主线程发消息
handler.sendEmptyMessage(DATA_UPDATE);
}
}
// Handler来源: android.os.Handler;
// Handler:用于线程之间的通信
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
/**
* @Description: 用于处理消息
*/
switch (msg.what){
case DATA_UPDATE:
myAdapter.notifyDataSetInvalidated();
break;
}
}
};
/第四步:滚动监听事件,滚动状态改变和滚动之后的改变/
//用来存储显示在尾部的最后一条数据的索引值
private int visibleLastIndex;
// 首先当前的Activity 实现AbsListView.OnScrollListener 类。因此就需要重写 onScrollStateChanged 和 onScroll 两个方法
@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
/**
* @Description: 状态改变发生变化触动该方法
* @Params: * @param absListView
* @param scrollState: 滚动的状态:SCROLL STATE IDLE(停止滑动) /SCROLL STATE FLING(手指离开的滑动状态) /SCROLL STATE TOUCH SCROLL(手指停留的滑动状态)
*/
if (myAdapter.getCount() == visibleLastIndex && scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE){
// 当活动停止且页面底部为最后一条数据
// 启动线程,加载新数据
new LoadDataThread().start();
}
}
@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
/**
* @Description: 滚动时触发该方法
* @Params: * @param absListView
* @param firstVisibleItem: 第一个可见元素的序号
* @param visibleItemCount:屏幕可显示的元素数量
* @param totalItemCount: 元素总数
*/
visibleLastIndex = firstVisibleItem + visibleItemCount-1; // 减去“正在加载中...”的那一条
}
展示一下 Activity 中的
private ListView listView;
// 数据,将其设置为static ,则内部类可直接使用
private static Vector<News> news = new Vector<>();
private MyAdapter myAdapter;
private static final int DATA_UPDATE = 0x1;//数据更新完成后的标记,1,十六进制
@Override
protected void onCreate(Bundle savedInstanceState) {
/**
* @Description: activity主要逻辑代码,例如setAdapter /set
*/
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_12);
listView = findViewById(R.id.listView);
// 注册滑动事件
listView.setOnScrollListener(this);
// 设置底部loading布局页面
View footerView = getLayoutInflater().inflate(R.layout.loading_12,null);
listView.addFooterView(footerView);
// 初始化数据
initData();
myAdapter = new MyAdapter(MainActivity12.this);
listView.setAdapter(myAdapter);
}