Adapter之大数据滑动效率优化和分页加载数据

         在Android中如果要做到大数据分页加载则需要我们的Activity实现OnScrollListener滚动条监听接口。当如果要做的更加高大上。比如需要在用户滑动至列表的底部,触碰摸个区域,则需要实现OnTouchListener接口,等等。

       这里先讲加载大数据

       首先需要在main.xml申明一个ListView,存放数据  

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:paddingLeft="3dp"  
    android:paddingRight="3dp">
    
    <!-- 当ListActivity时,ListView中就需要@id/android:list,否则logCat会报错
    	 Android内置的名为list的id,因为我们后面要使用到ListActivity,我们的MainActivity继承于它 -->
    <TextView android:id="@+id/txtView"
        android:text="编号"
        android:textSize="24dp"
        android:textColor="#ff00FF"
        android:background="#80D640"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"/>	 
    <ListView android:id="@id/android:list"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"/>  
</LinearLayout>  
       由于ListView试图组件中,需要封装每一个item,所以需要layout中申明:

        list_item.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent">  
    <!-- 它是ListView中单个列表项的布局文件,从效果图中可以看到,这里只使用到了一个TextView组件 -->
    <!-- 在getView或者bindview里面首先用一文本TextView显示在本地,同时启动线程去网上获取图片资源,一旦某TextView的数据得到就立马刷新将那张本地的TextView换掉 -->
    <TextView  android:id="@+id/list_item_text"  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent"  
        android:gravity="center"  
        android:textSize="20sp"  
        android:paddingTop="10dp"  
        android:paddingBottom="10dp"/>  
</LinearLayout> 
       在加上我们的效果时,当滑动至列表的底部也就是应用程序窗体底部时,想要加载下一行,所以需要一个按钮来触发 load_more.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout  
  xmlns:android="http://schemas.android.com/apk/res/android"  
  android:orientation="vertical"  
  android:layout_width="fill_parent"  
  android:layout_height="wrap_content">  
  <Button android:id="@+id/loadMoreButton"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="load more"  
        android:onClick="loadMore"/>  
</LinearLayout>  
        在使用BaseAdapter适配器加载大量数据

        

package com.lol.huixin.adapter;

import java.util.List;
import java.util.Map;

import com.lol.huixin.loaddatamore.R;
import com.lol.huixin.views.ViewHolder;

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<Map<String,Object>> items;  
    private LayoutInflater inflater;
	
    public ListViewAdapter(Context context, List<Map<String,Object>> items) {  
        this.items = items;  
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);        
    }
    
	@Override
	public int getCount() {
		return items.size();
	}

	@Override
	public Object getItem(int position) {
		return items.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder=null;
		if (convertView == null) {  
			holder=new ViewHolder();
			convertView = inflater.inflate(R.layout.list_item, null);  
			holder.list_item_text=(TextView) convertView.findViewById(R.id.list_item_text);
			convertView.setTag(holder);
        } else{
        	holder=(ViewHolder)convertView.getTag();
        } 
		holder.list_item_text.setText((String)items.get(position).get("bianhao"));
        return convertView; 
	}

	/** 
     * 添加列表项 
     * @param item 
     */  
    public void addItem(Map<String,Object> listmap) {  
        items.add(listmap);  
    }
}
      MainActivity.java中调用

 

package com.lol.huixin.loaddatamore;

import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.lol.huixin.adapter.ListViewAdapter;

import android.app.ListActivity;
import android.view.Menu;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.ListView;

//由于我们这里模拟加载大量数据的样本,所以就需要有个滚动条,所以需要实现滚动条的接口
public class MainActivity extends ListActivity implements OnScrollListener{
	private ListView listView;  
    private int visibleLastIndex = 0;   //最后的可视项索引  
    private int visibleItemCount;       // 当前窗口可见项总数  
    private ListViewAdapter adapter;    //数据适配器
    private View loadMoreView;  
    private Button loadMoreButton;  
    private Handler handler = new Handler(); 
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//相当于实例化一个Layout,并在这个实例化的Layout中加一个按钮
		loadMoreView = getLayoutInflater().inflate(R.layout.load_more, null);  
        loadMoreButton = (Button) loadMoreView.findViewById(R.id.loadMoreButton);  
        listView = getListView();               //获取id是list的ListView  
        listView.addFooterView(loadMoreView);   //设置列表底部视图  
        //初始化数据
        initAdapter();  
        setListAdapter(adapter);                //自动为id是list的ListView设置适配器  
        listView.setOnScrollListener(this);     //添加滑动监听
	}

	@Override
	public 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;
	}
	
	/** 
     * 初始化适配器 
     */  
    private void initAdapter() {  
    	List<Map<String,Object>> listMap=new ArrayList<Map<String,Object>>();
        for (int i = 0; i < 10; i++) {  
        	Map<String,Object> map=new HashMap<String,Object>();
        	map.put("bianhao",String.valueOf(i+1)); 
        	listMap.add(map);
        }  
        adapter = new ListViewAdapter(this, listMap);  
    }

    /** 
     * 滑动状态改变时被调用 
     */
	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		int itemsLastIndex = adapter.getCount() - 1;    //数据集最后一项的索引  
        int lastIndex = itemsLastIndex + 1;             //加上底部的loadMoreView项  
        if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && visibleLastIndex == lastIndex) {  
            //如果是自动加载,可以在这里放置异步加载数据的代码  
            Log.i("LOADMORE", "loading...");  
        }
	}

	/** 
     * 滑动时被调用 
     */
	@Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		this.visibleItemCount = visibleItemCount;  
        visibleLastIndex = firstVisibleItem + visibleItemCount - 1;  
	}

	  /** 
     * 点击按钮事件 
     * @param view 
     */  
    public void loadMore(View view) {  
        loadMoreButton.setText("loading...");   //设置按钮文字loading  
        handler.postDelayed(new Runnable() {  
            @Override  
            public void run() {  
                loadData();  
                adapter.notifyDataSetChanged(); //数据集变化后,通知adapter  
                listView.setSelection(visibleLastIndex - visibleItemCount + 1); //设置选中项  
                  
                loadMoreButton.setText("load more");    //恢复按钮文字  
            }  
        }, 2000);  
    }  
      
    /** 
     * 模拟加载数据 
     */  
    private void loadData() {  
        int count = adapter.getCount();  
        for (int i = count; i < count + 10; i++) {  
        	Map<String,Object> map=new HashMap<String,Object>();
        	map.put("bianhao",String.valueOf(i+1));
            adapter.addItem(map);  
        }  
    }  
    
}
   这个时候我们注意到了一个奇怪的现象:ViewHolder类

   

package com.lol.huixin.views;

import java.io.Serializable;

import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

@SuppressWarnings("serial")
public class ViewHolder implements Serializable{
	public ImageView img;
	//public TextView title;
	public TextView list_item_text;
	public TextView info;
	public Button viewBtn;
}
      项目结构:

      
        运行效果:也是ok的。

        然后我就在想为什么这样写了?

       1.首先ListViewAdapter中有一个有参构造方法,我们在MainActivity调用时传入了两个参数,参数一是需要装载值ListView中的数据,参数二是当前上下文对象Context,

        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)

        从当前layout的上下文作用域中得到SystemService中的LAYOUT_INFLATER_SERVICE东东,那么LAYOUT_INFLATER_SERVICE是什么东东,Android官网给与了解释:

Open Declaration String android. content. Context.LAYOUT_INFLATER_SERVICE = "layout_inflater"

Use with getSystemService to retrieve a android.view.LayoutInflater for inflating layout resources in this context.

See Also:
getSystemService
android.view.LayoutInflater
Google说:使用带有getSystemService检索android.view.LayoutInflater进行充气布局资源于该上下文。
也就是说我们通过LayoutInflater这个类实例化一个layout,将我们 load_more.xml中的按钮给动态加至ListView中
2.我们知道Android中提高滑动效率,就意味着需要修改GetView方法,那么我们那样写的目的何在
   原因有两点:
          一>adapter每次加载时,都需要去创建一个item中的内容,也就是Layout和其中的组件,很影响效率,如果我们把组件进行封装是不是会优化效率呢?在这,如果在内存中已经分配了使用LayoutInflater创建了一个Layout呢?我们是不是不需要在此创建
         二>我们都知道在看书的时候,要想定位到上次看过的地方,最简单的方法就是在书中做个标记,同样的android也支持这样一种写法
       convertView.setTag(holder);   //做数据标记





 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值