ListView的分页加载问题

来源:互联网 发布:ubuntu 12.04 安装jdk 编辑:程序博客网 时间:2024/06/09 04:45

ListView的优化一直是Android中比较常见的问题,那么一些比较基本的ListView的优化还是应该要掌握的,其中就涉及到ListView的分页加载问题,主要是将数据一页一页的加载出来,提高流畅度,一般是一次加载10项,下面看看具体的代码。

xml的代码比较简单,就是在activity_main中显示一个listview

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <ListView        android:id="@id/android:list"        android:layout_width="match_parent"        android:layout_height="wrap_content" /></LinearLayout>

 


显示ListView中item的内容list_item

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:id="@+id/list_item_text"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:gravity="center"        android:paddingBottom="10dp"        android:paddingTop="10dp"        android:textSize="20sp" /></LinearLayout>

定义一个分页加载的Button load_more

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:orientation="vertical" >    <Button        android:id="@+id/loadMoreButton"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:onClick="loadMore"        android:text="加载更多" /></LinearLayout>


 


定义一个ListViewAdpater适配器继承BaseAdapter,需要重写里面的getCount(),getItem(),getItem(),getView()方法。此适配器需要一个Context对象来获取LayoutInflater实例和一个集合对象来充当适配器的数据集。

package com.example.mikasa_list;import java.util.List;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;public class ListViewAdapter extends BaseAdapter{private List<String> items;private LayoutInflater inflater;public ListViewAdapter(Context context, List<String> list){items = list;inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn items.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn items.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubViewHolder viewholder = null;if(convertView == null){convertView = inflater.inflate(R.layout.list_item, null);viewholder = new ViewHolder();viewholder.text = (TextView)convertView.findViewById(R.id.list_item_text);convertView.setTag(viewholder);}else{viewholder = (ViewHolder)convertView.getTag();}viewholder.text.setText(items.get(position));return convertView;}class ViewHolder{private TextView text;}public void additem(String item){items.add(item);}}


可以看到在getView()方法中使用了对ListView的基本优化,如果convertView为空,则使用LayoutInflater的inflate方法去加载布局,如果不为空,则直接重用。同时增加了一个ViewHolder的内部类来对空间进行缓存,这样就不用每次都重新加载空间的实例,提高了ListView的运行效率。

主MainActivity也比较简单

package com.example.mikasa_list;import java.util.ArrayList;import java.util.List;import android.app.ListActivity;import android.os.Bundle;import android.os.Handler;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.Button;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends ListActivity implements OnScrollListener {private ListView lv;private Button btn;private View loadMoreView; private int visibleLastIndex = 0;private int visibleItemCount;private ListViewAdapter adapter;private Handler mhandler = new Handler();    private Boolean islast = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);loadMoreView = getLayoutInflater().inflate(R.layout.load_more, null);btn = (Button)loadMoreView.findViewById(R.id.loadMoreButton);lv = getListView();lv.addFooterView(loadMoreView);intiadater();setListAdapter(adapter);lv.setOnScrollListener(this);}private void intiadater() {ArrayList<String> list = new ArrayList<String>();for(int i = 0; i < 10; i++){list.add(String.valueOf(i + 1));}adapter = new ListViewAdapter(this, list);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml.int id = item.getItemId();if (id == R.id.action_settings) {return true;}return super.onOptionsItemSelected(item);}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){//public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {// TODO Auto-generated method stubvisibleLastIndex = firstVisibleItem;if(firstVisibleItem + visibleItemCount == totalItemCount){islast = true;}}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {//public void onScrollStateChanged(AbsListView arg0, int arg1) {// TODO Auto-generated method stubint itemsLastIndex = adapter.getCount();int lastIndex = itemsLastIndex + 1 ;if(scrollState == OnScrollListener.SCROLL_STATE_IDLE && islast){Log.i("TAG", "loading...");loadData();Toast.makeText(this, "正在加载中...", Toast.LENGTH_SHORT).show();islast = false;}}public void loadMore(View view) {  btn.setText("加载中...");loadData();}private void loadData() {mhandler.postDelayed(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubint count = adapter.getCount();for(int i = count; i < count + 10; i++){adapter.additem(String.valueOf(i + 1));}adapter.notifyDataSetChanged();lv.setSelection(visibleLastIndex);btn.setText("加载更多...");}}, 2000);}}

 

主要是设置ListView的监听事件ListView.setOnScrollListener(this);并重写onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)和onScrollStateChanged(AbsListView view, int scrollState)方法,注意到这里的几个参数。

firstVisibleItem表示当前能看到的第一个列表项id(从0开始,不完整的也算)

visibleItemCount表示当前页面能看到的列表总数(不完整的也算),即整个页面能显示多少个item

totalItemCount表示ListView的列表总数

scrollState表示正在滚动的回调次数,为0的时候表示没有滑动,为1的时候表示正在滑动,为2的时候表示手指离开屏幕

islast是判断是否在最后一行,初始值为false,注意加载的数据一般在异步完成。

 

还有几个问题是在滑动过程中,向上滑动有时也会自动加载,应该是要加判断是向上还是向下,还有一个是会连续加载两次,有时会因为firstVisibleItem和visibleItemCount的数值问题导致不能自动加载,猜想应该是因为在底部加了一个Button的原因,有待考证。希望能一起讨论

0 0