什么是ListView分页加载数据功能呢?在现在的大数据时代,我们不可能把某些数据全部展示到界面,好比我们经常会看的QQ空间一样,当你看动态的时候,系统不可能会把所有好友的动态都展示在上面,你能看到的一般都是最新好友更新的动态,假如你要看非最新的好友动态,通常你都会手指向上滑动屏幕然后去查看,当界面下滑到一定数量的时候,就会看到一个“查看更多”,然后突然停顿一下,系统会通过网络去给你刷新其他动态信息,这样的功能我们一般叫做数据下拉刷新功能,也就是我们的分页加载功能,具体的实现是怎样的呢?下面我们开始详细讲解。
实现的原理:
1. 首先要先确定默认展示在ListView上的数据,比如默认在ListView上展示10条数据。
2. 将数据传递到自定义的适配器上,然后加载到ListView中。
3. 当用户将数据拉到最后一条的时候,就要开始刷新加载新数据了。
4. 通过监听ListView的滑动事件,判断是否达到最后一条,如果达到最后一条则开始刷新。
详细的实现步奏在代码中详细讲解。
整体结构如下:
activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
tools:context
=
"com.company.listviewdeepknow.MainActivity"
>
<
ListView
android:id
=
"@+id/mList"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
>
</
ListView
>
</
RelativeLayout
>
|
foot_boot.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
android:layout_width
=
"match_parent"
android:layout_height
=
"70dp"
android:gravity
=
"center"
android:orientation
=
"horizontal"
>
<
ProgressBar
android:id
=
"@+id/progressBar"
style
=
"?android:attr/progressBarStyleSmall"
android:layout_width
=
"45dp"
android:layout_height
=
"45dp"
/>
<
TextView
android:id
=
"@+id/mLoad"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"加载更多..."
android:textSize
=
"20sp"
/>
</
LinearLayout
>
|
list_item.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:orientation
=
"horizontal"
>
<
TextView
android:id
=
"@+id/mTv1"
android:layout_width
=
"100dp"
android:layout_height
=
"100dp"
android:textSize
=
"20sp"
/>
<
TextView
android:id
=
"@+id/mTv2"
android:layout_width
=
"100dp"
android:layout_height
=
"100dp"
android:layout_alignParentRight
=
"true"
android:textSize
=
"20sp"
/>
</
RelativeLayout
>
|
MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
public
class
MainActivity
extends
AppCompatActivity
implements
MyOnScrollListener.OnloadDataListener {
//ListView展示的数据项
private
List<Student> data;
//ListView控件
private
ListView mList;
//自定义适配器
MyAdapter adapter;
//底部加载更多布局
View footer;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//首先加载默认数据,这里设置为10条
getData();
//显示到ListView上
showListView(data);
//自定义的滚动监听事件
MyOnScrollListener onScrollListener =
new
MyOnScrollListener(footer, data);
//设置接口回调
onScrollListener.setOnLoadDataListener(
this
);
//设置ListView的滚动监听事件
mList.setOnScrollListener(onScrollListener);
}
/**
* 初始化ListView数据,默认设置为10条
*/
private
void
getData() {
data =
new
ArrayList<>();
Student stu =
null
;
for
(
int
i =
0
; i <
10
; i++) {
stu =
new
Student();
stu.setName(
"姓名"
+ i);
stu.setSex(i %
2
==
0
?
"男"
:
"女"
);
data.add(stu);
}
}
/**
* 将数据加载到ListView上
*
* @param data
*/
private
void
showListView(List<Student> data) {
//首先判断适配器是否为空,首次运行肯定是为空的
if
(adapter ==
null
) {
//查到ListView控件
mList = (ListView) findViewById(R.id.mList);
//将底部加载一个加载更多的布局
footer = LayoutInflater.from(
this
).inflate(R.layout.foot_boot,
null
);
//初始状态为隐藏
footer.setVisibility(View.GONE);
//加入到ListView的底部
mList.addFooterView(footer);
//创建adpter数据
adapter =
new
MyAdapter(data);
//设置adapter
mList.setAdapter(adapter);
}
else
{
//不为空,则刷新数据
this
.data = data;
//提醒ListView重新更新数据
adapter.notifyDataSetChanged();
}
}
@Override
public
void
onLoadData(List<Student> data) {
//加载数据完成后,展示数据到ListView
showListView(data);
}
}
|
MyOnScrollListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
public
class
MyOnScrollListener
implements
AbsListView.OnScrollListener {
//ListView总共显示多少条
private
int
totalItemCount;
//ListView最后的item项
private
int
lastItem;
//用于判断当前是否在加载
private
boolean
isLoading;
//底部加载更多布局
private
View footer;
//接口回调的实例
private
OnloadDataListener listener;
//数据
private
List<Student> data;
public
MyOnScrollListener(View footer, List<Student> data) {
this
.footer = footer;
this
.data = data;
}
//设置接口回调的实例
public
void
setOnLoadDataListener(OnloadDataListener listener) {
this
.listener = listener;
}
/**
* 滑动状态变化
*
* @param view
* @param scrollState 1 SCROLL_STATE_TOUCH_SCROLL是拖动 2 SCROLL_STATE_FLING是惯性滑动 0SCROLL_STATE_IDLE是停止 , 只有当在不同状态间切换的时候才会执行
*/
@Override
public
void
onScrollStateChanged(AbsListView view,
int
scrollState) {
//如果数据没有加载,并且滑动状态是停止的,而且到达了最后一个item项
if
(!isLoading && lastItem == totalItemCount && scrollState == SCROLL_STATE_IDLE) {
//显示加载更多
footer.setVisibility(View.VISIBLE);
Handler handler =
new
Handler();
//模拟一个延迟两秒的刷新功能
handler.postDelayed(
new
Runnable() {
@Override
public
void
run() {
if
(listener !=
null
) {
//开始加载更多数据
loadMoreData();
//回调设置ListView的数据
listener.onLoadData(data);
//加载完成后操作什么
loadComplete();
}
}
},
2000
);
}
}
/**
* 当加载数据完成后,设置加载标志为false表示没有加载数据了
* 并且设置底部加载更多为隐藏
*/
private
void
loadComplete() {
isLoading =
false
;
footer.setVisibility(View.GONE);
}
/**
* 开始加载更多新数据,这里每次只更新三条数据
*/
private
void
loadMoreData() {
isLoading =
true
;
Student stu =
null
;
for
(
int
i =
0
; i <
3
; i++) {
stu =
new
Student();
stu.setName(
"新名字"
+ i);
stu.setSex(
"新性别"
+ i);
data.add(stu);
}
}
/**
* 监听可见界面的情况
*
* @param view ListView
* @param firstVisibleItem 第一个可见的 item 的索引
* @param visibleItemCount 可以显示的 item的条数
* @param totalItemCount 总共有多少个 item
*/
@Override
public
void
onScroll(AbsListView view,
int
firstVisibleItem,
int
visibleItemCount,
int
totalItemCount) {
//当可见界面的第一个item + 当前界面多有可见的界面个数就可以得到最后一个item项了
lastItem = firstVisibleItem + visibleItemCount;
//总listView的item个数
this
.totalItemCount = totalItemCount;
}
//回调接口
public
interface
OnloadDataListener {
void
onLoadData(List<Student> data);
}
}
|
MyAdapter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
class
MyAdapter
extends
MyBaseAdapter<Student> {
public
MyAdapter(List<Student> data) {
super
(data);
}
@Override
public
void
setData(ViewHolder holder, Student t) {
holder.setText(R.id.mTv1, t.getName()).setText(R.id.mTv2, t.getSex());
}
}
|
MyBaseAdapter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public
abstract
class
MyBaseAdapter<T>
extends
BaseAdapter {
protected
List<T> data;
public
MyBaseAdapter(List<T> data){
this
.data = data;
}
@Override
public
int
getCount() {
return
data ==
null
?
0
: data.size();
}
@Override
public
Object getItem(
int
position) {
return
data.get(position);
}
@Override
public
long
getItemId(
int
position) {
return
position;
}
@Override
public
View getView(
int
position, View convertView, ViewGroup parent) {
ViewHolder holder = ViewHolder.getHolder(convertView,parent,position, R.layout.list_item);
setData(holder,data.get(position));
return
holder.getConvertView();
}
public
abstract
void
setData(ViewHolder holder,T t);
}
|
ViewHolder.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
public
class
ViewHolder {
private
int
position;
private
SparseArray<View> array;
private
View convertView;
private
Context context;
private
ViewHolder(ViewGroup parent,
int
position,
int
layout) {
this
.position = position;
this
.context = parent.getContext();
convertView = LayoutInflater.from(parent.getContext()).inflate(layout,
null
);
convertView.setTag(
this
);
array =
new
SparseArray<>();
}
public
static
ViewHolder getHolder(View convertView, ViewGroup parent,
int
position,
int
layout) {
if
(convertView ==
null
) {
return
new
ViewHolder(parent, position, layout);
}
else
{
ViewHolder holder = (ViewHolder) convertView.getTag();
holder.position = position;
return
holder;
}
}
public
<T
extends
View> T getView(
int
viewId) {
View view = array.get(viewId);
if
(view ==
null
) {
view = convertView.findViewById(viewId);
array.put(viewId, view);
}
return
(T) view;
}
public
View getConvertView() {
return
convertView;
}
public
ViewHolder setText(
int
viewId, String data) {
TextView tv = getView(viewId);
tv.setText(data);
return
this
;
}
|
Student.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
class
Student {
private
String name;
private
String sex;
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
String getSex() {
return
sex;
}
public
void
setSex(String sex) {
this
.sex = sex;
}
}
|