在我的上一篇博客中简单分析了,使用ListView的好处,和通过Adapter实现了数据和界面显示的分离的好处。源代码下载
好吧,既然是界面,那我先把截图给出来。照着图我们来一步步的实现,分析代码。
从上图中可以看到,这个比之前我们自己实现的那个漂亮多了,有了固定的高度和边框,也因此而导致显示的数据少了。
1. 首先我们还是来先写一个布局文件保存在layout文件夹下创建activity_simple_list_view.xml
[xml]
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
[/xml]
同样这个布局文件也是非常的简单,仅仅只有一LinearLayout和一个ListView,和上篇博客中的思想大致一样,我们依然是把条目添加到ListView中,
2. 下面是这个布局文件对应的Activity的实现,这个类看着比较复杂,其实分开来看很简单,
其中外部类Activity只有一个方法而已,
再就是BaseAdapter的内部类,同样这个类也不是太复杂,因为我们只关注其中的两个方法而已,最起码在这个例子中是这样。
这个类我就不多解释了,看代码是最好的学习方式,代码中的注释已经足够详细,下面是这个类:
[java]
package com.comcons.testlistviewandadapter;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class SimpleListViewActivity extends Activity {
/**
* 声明一个List集合用做存放数据
*/
private List<String> data = null;
/**
* 声明一个ListView作为Layout中的那个ListView的引用
*/
private ListView listView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple_list_view);
data = new ArrayList<String>();
listView = (ListView)findViewById(R.id.listView1);
/**
* 模拟数据集合
* 向数据集合中添加50条数据
*/
for(int i=0;i<50;i++){
data.add("item —>"+i);
}
/**
* 创建一个BaseAdapter子类的实例
*/
MyAdapter adapter = new MyAdapter();
//给ListView对象添加Adapter
listView.setAdapter(adapter);
}
/**
* 每次滚动调用getCount计算总共有几条数据
* 然后逐条调用getView创建View对象,显示在屏幕上
* 如果屏幕上没有空间了,就停止创建
* 当屏幕滚动的时候,超出屏幕的部分的View的引用赋值为null让虚拟机的垃圾回收机制回收
* 然后在屏幕的下边,创建新的View并添加到屏幕也就是ListView的底部
* @author LiuQiang
*
*/
private class MyAdapter extends BaseAdapter{
/**
* 返回适配器的长度
* 也就是适配器所要处理的数据的长度
* 控制ListView中总共有多少条数据
*/
@Override
public int getCount() {
System.out.println("getCout()—>" + data.size());
return data.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
/**
* 每当有新的条目要显示在手机屏幕的可视界面中的时候才会调用这个方法
* 在ListView中逐条加载这个View
* 当当前屏幕没有空间的时候就不再(不再创建信的条目)调用这个方法
* @ position 说明下这个参数,这个参数是的变化是由ListView的setAdapter()方法调用此方法的时候控制的
* The position of the item within the adapter’s data set of the item whose view we want.
* 其余两个参数暂时没有用,我们先不去管。
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("getView—->position:" + position);
//创建一个TextView对象
TextView tv = new TextView(getApplicationContext());
//设置这个TextView中显示文字的字体大小
tv.setTextSize(20);
//从一个数据集合(也就是List)中获取position位置的集合元素,
String s = data.get(position);
//设置这个TextView要显示的内容
tv.setText(s);
//返回这个TextView对象
return tv;
}
}
}
[/java]
运行这个程序,从打印的log中可以看到,每次触摸ListView中的条目的时候适配器(MyAdapter)的getCount()方法就会被调用,重新计算适配器中的数据的多少。
每次滚动时都会调用适配器(MyAdapter)的getView()方法,返回要显示的下一条Item的View对象,使之显示在ListView中。
【分析下这个LisView和之前的那个相比的好处】
在这里所有条目对象,也就是ListView中包含50个TextView不是一次性创建的,如果用户不想上滑动屏幕的话,仅仅只会创建第一屏的14个对象,在这个例子中是14个,这个多少取决于ListView中每个条目的高度。当用户向上滑动屏幕的时候超出屏幕上方的条目对象的引用会丢失,所以条目对象会被虚拟机的垃圾回收机制回收掉,而每次从屏幕下方新出现的条目的对象会被逐个创建。周而复始,向下滑动也是同样的道理。
总而言之实现一个ListView总共是三步:
1. 首先要有一个数据集合
2. 要有一个ListView对象
3.给ListView设置适配器(这步中要实现一个适配器)
另外在BaseAdapter中还有两个没用到的方法,
public int getCount() {}和
public Object getItem(int position) {}
这两个方法在Android源码中并没有用到,只是Android工程师为开发者提供的,供开发者 “自娱自乐”的(其实深入研究你会发现并不完全是这样的,仅仅是一般情况下用不到而已),
也就是说你返回什么都无所谓,最好返回对自己有用的数据,然后在自己能用到的时候获取自己数据,一个很常见的例子就是
把一个ListView分成两部分展示。(这个就先不写了)然后在处理ListView的条目点击事件的时候,
ListView的父类AdapterView会有一个方法getItemAtPosition 这个方法会调用Adapter中的getItem(int postion)方法