前几篇博客,我们从缓存的角度优化了ListView,如果你对此还不太熟悉的话可以到android-----带你一步一步优化ListView(一),android-----带你一步一步优化ListView(二),android-----带你一步一步优化ListView(三),查看,其实,对于ListView的优化来说,还有一种方式我们没有涉及,那就是分页加载了,你在微信加载朋友圈的时候会发现每次显示到最下面会出现加载更多的提示信息,这就是分页加载的使用啦,我们没有必要每次加载ListView的数据时把所有数据全部都查找到,因为ListView本身能够显示在一个界面的条目数是有限的,我们完全可以只去查找一屏幕的数据并且显示他,当用户滑动到最下面的时候再去加载下一屏幕的数据,这对于ListView上面有图片显示的应用来说优化效果特别明显,那么这篇博客,我们将会实现类似于朋友圈上拉加载更多的功能;
先来看看效果图:
好了,接下来我们从代码层面来讲解该怎么实现:
首先定义一个主界面布局listview.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. "match_parent"
4. "match_parent"
5. "vertical" >
6. <ListView
7. "@+id/listView"
8. "match_parent"
9. "match_parent">
10. </ListView>
11. </LinearLayout>
定义每个item的显示布局item.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. "match_parent"
4. "match_parent"
5. "vertical" >
6. <ImageView
7. "@+id/imageView"
8. "50dp"
9. "50dp"
10. />
11. <TextView
12. "@+id/textView"
13. "wrap_content"
14. "50dp"
15. "@id/imageView"
16. "20dp"
17. "70dp"
18. />
19. </RelativeLayout>
很简单,就是一个ImageView和一个TextView
接下来就是一个用于显示加载更多的布局了load_more.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. "@+id/loadmore"
4. "match_parent"
5. "match_parent"
6. "center"
7. "horizontal" >
8.
9. <ProgressBar
10. "@+id/progress"
11. "?android:attr/progressBarStyleSmall"
12. "wrap_content"
13. "wrap_content"
14. "30dp"
15. "30dp" />
16.
17. <TextView
18. "@+id/tv"
19. "wrap_content"
20. "wrap_content"
21. "20dp"
22. "正在加载..."
23. "#FF0000" />
24. </LinearLayout>
这个界面中会显示一个进度条和正在加载的TextView
之后便是为我们的ListView设置适配器ListViewAdapter了
1. public class ListViewAdapter extends BaseAdapter{
2.
3. public List<String> list;
4. public LayoutInflater inflater;
5.
6.
7. public ListViewAdapter() {
8. }
9.
10. public ListViewAdapter(Context context,List<String> list) {
11. this.list = list;
12. this.inflater = LayoutInflater.from(context);
13. }
14.
15. @Override
16. public int getCount() {
17. return list.size();
18. }
19.
20. @Override
21. public String getItem(int position) {
22. return list.get(position);
23. }
24.
25. @Override
26. public long getItemId(int position) {
27. return 0;
28. }
29.
30. public void updateView(List<String> nowList)
31. {
32. this.list = nowList;
33. this.notifyDataSetChanged();//强制动态刷新数据进而调用getView方法
34. }
35. @Override
36. public View getView(int position, View convertView, ViewGroup parent) {
37. null;
38. null;
39. if(convertView == null)
40. {
41. null);
42. new ViewHolder();
43. holder.imageView = (ImageView)view.findViewById(R.id.imageView);
44. holder.textView = (TextView)view.findViewById(R.id.textView);
45. //为了复用holder
46. else
47. {
48. view = convertView;
49. holder = (ViewHolder) view.getTag();
50. }
51. holder.imageView.setImageResource(R.drawable.image);
52. holder.textView.setText(list.get(position));
53. return view;
54. }
55. static class ViewHolder
56. {
57. ImageView imageView;
58. TextView textView;
59. }
60. }
notifyDataSetChanged方法来通知适配器告诉他ListView上面需要显示的内容已经发生了改变,这时候就会调用getView方法来重新加载数据了;
接下来就是我们的主Activity
1. public class MainActivity extends Activity implements OnScrollListener{
2.
3. public View loadmoreView;
4. public LayoutInflater inflater;
5. public ListView listView;
6. public int last_index;
7. public int total_index;
8. public List<String> firstList = new ArrayList<String>();//表示首次加载的list
9. public List<String> nextList = new ArrayList<String>();//表示出现刷新之后需要显示的list
10. public boolean isLoading = false;//表示是否正处于加载状态
11. public ListViewAdapter adapter;
12.
13. @Override
14. protected void onCreate(Bundle savedInstanceState) {
15. super.onCreate(savedInstanceState);
16. setContentView(R.layout.listview);
17. this);
18. null);//获得刷新视图
19. //设置刷新视图默认情况下是不可见的
20. listView = (ListView) findViewById(R.id.listView);
21. 10, 10);
22. new ListViewAdapter(this, firstList);
23. this);
24. null,false);
25. listView.setAdapter(adapter);
26. }
27. /**
28. * 初始化我们需要加载的数据
29. * @param firstCount
30. * @param nextCount
31. */
32. public void initList(int firstCount,int nextCount)
33. {
34. for(int i = 0;i < firstCount;i++)
35. {
36. "第"+(i+1)+"个开始加载");
37. }
38. for(int i = 0;i < firstCount;i++)
39. {
40. "第"+(i+1)+"个开始加载");
41. }
42. for(int i = 0;i < nextCount;i++)
43. {
44. "刷新之后第"+(i+1)+"个开始加载");
45. }
46. }
47. @Override
48. public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
49. last_index = firstVisibleItem+visibleItemCount;
50. total_index = totalItemCount;
51. "last: "+last_index);
52. "total: "+total_index);
53. }
54.
55. @Override
56. public void onScrollStateChanged(AbsListView view, int scrollState) {
57. if(last_index == total_index && (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE))
58. {
59. //表示此时需要显示刷新视图界面进行新数据的加载(要等滑动停止)
60. if(!isLoading)
61. {
62. //不处于加载状态的话对其进行加载
63. true;
64. //设置刷新界面可见
65. loadmoreView.setVisibility(View.VISIBLE);
66. onLoad();
67. }
68. }
69. }
70.
71. /**
72. * 刷新加载
73. */
74. public void onLoad()
75. {
76. try {
77. //模拟耗时操作
78. 2000);
79. catch (InterruptedException e) {
80. e.printStackTrace();
81. }
82. if(adapter == null)
83. {
84. new ListViewAdapter(this, firstList);
85. listView.setAdapter(adapter);
86. else
87. {
88. adapter.updateView(nextList);
89. }
90. //刷新结束
91. }
92.
93. /**
94. * 加载完成
95. */
96. public void loadComplete()
97. {
98. //设置刷新界面不可见
99. false;//设置正在刷新标志位false
100. this.invalidateOptionsMenu();
101. //如果是最后一页的话,则将其从ListView中移出
102. }
103. }
onScroll和第56行的onScrollStateChanged,通过onScroll中的last_index用于获得当前页面表示在现时屏幕可以见到的最大Item的位置,total_index用于表示ListView可以加载的ListItem总数;第57行判断当前页面表示在现时屏幕可以见到的最大Item的位置如果等于ListView可以加载的ListItem总数并且滑动停止的话,则判断isLoading是否处于加载状态,如果不处于加载状态的话,则调用onLoad方法去加载,这个方法里面的Thread.sleep(2000)用于模拟耗时操作,随后利用ListAdapter的updateView方法更新ListView需要显示的数据,最后调用loadComplete来结束刷新操作,第98行设置刷新视图不可见,修改isLoading加载标志,最后将加载更多视图从当前ListView中移除;
至此,上拉加载更多讲解结束,下一篇我们将讲解一下下拉刷新的实现,谢谢大家!
点击下载源码!!!!!