你的位置:首页 > 操作系统

[操作系统]Android开发学习——ListView+BaseAdapter的使用


ListView

就是用来显示一行一行的条目的
MVC结构
 * M:model模型层,要显示的数据           ————people集合
 * V:view视图层,用户看到的界面          ————ListView
 * c:control控制层,操作数据如何显示     ————adapter对象
每一个条目都是一个View对象
BaseAdapter
* 必须实现的两个方法

 * 第一个

   //系统调用此方法,用来获知模型层有多少条数据
   @Override
   public int getCount() {
    return people.size();
   }

 * 第二个

   //系统调用此方法,获取要显示至ListView的View对象
   //position:是return的View对象所对应的数据在集合中的位置
   @Override
   public View getView(int position, View convertView, ViewGroup parent) {
    System.out.println("getView方法调用" + position);
    TextView tv = new TextView(MainActivity.this);
    //拿到集合中的元素
    Person p = people.get(position);
    tv.setText(p.toString());
    
    //把TextView的对象返回出去,它会变成ListView的条目
    return tv;
   }
屏幕上能显示多少个条目,getView方法就会被调用多少次,屏幕向下滑动时,getView会继续被调用,创建更多的View对象显示至屏幕
条目的缓存
当条目划出屏幕时,系统会把该条目缓存至内存,当该条目再次进入屏幕,系统在重新调用getView时会把缓存的条目作为convertView参数传入,但是传入的条目不一定是之前被缓存的该条目,即系统有可能在调用getView方法获取第一个条目时,传入任意一个条目的缓存

 

代码如下:

activity_main.

<LinearLayout ="http://schemas.android.com/apk/res/android"  ="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"    tools:context="com.example.list.MainActivity" >  <ListView    android:id="@+id/lv"    android:layout_width="fill_parent"    android:layout_height="fill_parent"       ></ListView></LinearLayout>

item.

<??><LinearLayout ="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical" >  <ImageView    android:id="@+id/iv"    android:src="@drawable/xing"    android:layout_width="80dp"    android:layout_height="80dp"           />  <TextView     android:id="@+id/t1"    android:layout_width="match_parent"    android:layout_height="wrap_content"        />  <TextView     android:id="@+id/t2"    android:layout_width="match_parent"    android:layout_height="wrap_content"           />  </LinearLayout>

MainActivity.java

public class MainActivity extends Activity {  List<shopInfo> l;  ListView lv;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    lv = (ListView) findViewById(R.id.lv);    //准备集合数据    l = new ArrayList<shopInfo>();    l.add(new shopInfo(R.drawable.xing, "name-1", "content-1"));    l.add(new shopInfo(R.drawable.xing, "name-2", "content-2"));    l.add(new shopInfo(R.drawable.xing, "name-3", "content-3"));    l.add(new shopInfo(R.drawable.xing, "name-4", "content-4"));    l.add(new shopInfo(R.drawable.xing, "name-5", "content-5"));    l.add(new shopInfo(R.drawable.xing, "name-6", "content-6"));    l.add(new shopInfo(R.drawable.xing, "name-7", "content-7"));    l.add(new shopInfo(R.drawable.xing, "name-8", "content-8"));  //准备BaseAdapter对象    MyAdapter a = new MyAdapter();    //设置Adapter显示数据    lv.setAdapter(a);  }//这个类可以写在里面,也可以写在外面  public class MyAdapter extends BaseAdapter {    @Override    public int getCount() {      // TODO Auto-generated method stub      return l.size();    }    @Override    public Object getItem(int arg0) {      // TODO Auto-generated method stub      return null;    }    @Override    public long getItemId(int arg0) {      // TODO Auto-generated method stub      return 0;    }

//第一种:没有任何处理,不建议这样写。如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式 @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub // 加载item的布局 View view = View.inflate(MainActivity.this, R.layout.item, null); shopInfo s = l.get(position); ImageView i = (ImageView) view.findViewById(R.id.iv); TextView t1 = (TextView) view.findViewById(R.id.t1); TextView t2 = (TextView) view.findViewById(R.id.t2); i.setImageResource(s.getIcon()); t1.setText(s.getName()); t2.setText(s.getContent()); convertView = view ; return convertView; } }}

shopInfo.java

//每行item的数据信息封装类public class shopInfo {  private int icon;  private String name;  private String content;      public int getIcon() {    return icon;  }  public void setIcon(int icon) {    this.icon = icon;  }  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  public String getContent() {    return content;  }  public void setContent(String content) {    this.content = content;  }  public shopInfo(int icon, String name, String content) {    super();    this.icon = icon;    this.name = name;    this.content = content;  }  @Override  public String toString() {    return "shopInfo [icon=" + icon + ", name=" + name + ", content="        + content + "]";  }  public shopInfo() {    super();    // TODO Auto-generated constructor stub  }  }

运行结果如下:

 

 接下来实现getView()的方法和上边的实现一样的功能。

第二种ListView优化:通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,提升了性能

public View getView(int position, View convertView, ViewGroup parent) {      if(convertView == null)      {        convertView = mInflater.inflate(R.layout.list_item, null);      }            ImageView img = (ImageView)convertView.findViewById(R.id.iv) ;      TextView title = (TextView)convertView.findViewById(R.id.t1);      TextView info = (TextView)ConvertView.findViewById(R.id.t2);      img.setImageResource(R.drawable.xing);      title.setText("Hello");      info.setText("world");            return convertView;    }

第三种ListView优化:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。

当我们判断 convertView == null  的时候,如果为空,就会根据设计好的List的Item布局(

如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。

public View getView(int position, View convertView, ViewGroup parent) {      // LayoutInflater mInflater = null;      ViewHolder holder = null;      shopInfo s = l.get(position);      if (convertView == null) {        holder = new ViewHolder();//         convertView = LinearLayout.inflate(MainActivity.this,//         R.layout.item, null);        convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item, null);        /* 得到各个控件的对象 */        holder.iv = (ImageView) convertView.findViewById(R.id.iv);        holder.t1 = (TextView) convertView.findViewById(R.id.t1);        holder.t2 = (TextView) convertView.findViewById(R.id.t2); // to                                      // ItemButton        convertView.setTag(holder); // 绑定ViewHolder对象      } else {        holder = (ViewHolder) convertView.getTag(); // 取出ViewHolder对象      }      /* 设置TextView显示的内容,即我们存放在动态数组中的数据 */      holder.iv.setImageResource(s.getIcon());      holder.t1.setText(s.getName());      holder.t2.setText(s.getContent());      return convertView;    }    /* 存放控件 的ViewHolder */    public final class ViewHolder {      public ImageView iv;      public TextView t1;      public TextView t2;    }

 

在上述的代码中方法getView(int position, View convertView, ViewGroup parent)的方法体中,holder这个变量其实就是一个每一个item的View的结构。

这个holder结构存储了item对应布局里面的一些组件,而convertView.setTag(holder),就是把convertView中的Tag关联到holder这个结构中。

而convertView.getTag(),就是把convertView中的Tag取出来。

最后的holder.textView.setText(mData.get(position));就是把holder中的对应的组件初始化或者重定义(改变一些值),然后就可以显示出不同的内容了。

 

 

如果要实现单双行颜色交替

MainActivity.java:

加下边三个语句就可以了。

public class MainActivity extends Activity {  List<shopInfo> l;  ListView lv;  private int[] colors = new int[] { 0xff3cb371, 0xffa0a0a0 };  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    lv = (ListView) findViewById(R.id.lv);    // 准备集合数据    l = new ArrayList<shopInfo>();    l.add(new shopInfo(R.drawable.xing, "name-1", "content-1"));    l.add(new shopInfo(R.drawable.xing, "name-2", "content-2"));    l.add(new shopInfo(R.drawable.xing, "name-3", "content-3"));    l.add(new shopInfo(R.drawable.xing, "name-4", "content-4"));    l.add(new shopInfo(R.drawable.xing, "name-5", "content-5"));    l.add(new shopInfo(R.drawable.xing, "name-6", "content-6"));    l.add(new shopInfo(R.drawable.xing, "name-7", "content-7"));    l.add(new shopInfo(R.drawable.xing, "name-8", "content-8"));    // 准备BaseAdapter对象    MyAdapter a = new MyAdapter();    // 设置Adapter显示数据    lv.setAdapter(a);  }  // 这个类可以写在里面,也可以写在外面  public class MyAdapter extends BaseAdapter {    @Override    public int getCount() {      // TODO Auto-generated method stub      return l.size();    }    @Override    public Object getItem(int arg0) {      // TODO Auto-generated method stub      return null;    }    @Override    public long getItemId(int arg0) {      // TODO Auto-generated method stub      return arg0;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {      // TODO Auto-generated method stub      // 加载item的布局      // View view = View.inflate(MainActivity.this, R.layout.item, null);      //      // shopInfo s = l.get(position);      // ImageView i = (ImageView) view.findViewById(R.id.iv);      // TextView t1 = (TextView) view.findViewById(R.id.t1);      // TextView t2 = (TextView) view.findViewById(R.id.t2);      //      // i.setImageResource(s.getIcon());      // t1.setText(s.getName());      // t2.setText(s.getContent());      // convertView = view ;      // return convertView;      // LayoutInflater mInflater = null;      //      if(position%2==0){//        lv.setBackgroundColor(Color.argb(250 , 255 , 255 , 255 ));//      }else{//        lv.setBackgroundColor(Color.argb(250 , 224 , 243 , 250 ));//      }                  ViewHolder holder = null;      shopInfo s = l.get(position);      if (convertView == null) {        holder = new ViewHolder();//         convertView = LinearLayout.inflate(MainActivity.this,//         R.layout.item, null);        convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item, null);        /* 得到各个控件的对象 */        holder.iv = (ImageView) convertView.findViewById(R.id.iv);        holder.t1 = (TextView) convertView.findViewById(R.id.t1);        holder.t2 = (TextView) convertView.findViewById(R.id.t2); // to                                      // ItemButton        convertView.setTag(holder); // 绑定ViewHolder对象      } else {        holder = (ViewHolder) convertView.getTag(); // 取出ViewHolder对象      }      /* 设置TextView显示的内容,即我们存放在动态数组中的数据 */      holder.iv.setImageResource(s.getIcon());      holder.t1.setText(s.getName());      holder.t2.setText(s.getContent());            int colorPos = position % colors.length;      convertView.setBackgroundColor(colors[colorPos]);      return convertView;    }    /* 存放控件 的ViewHolder */    public final class ViewHolder {      public ImageView iv;      public TextView t1;      public TextView t2;    }  }}

效果如图: