Android(java)学习笔记88:BaseAdapter适配器重写之getView()

1. BaseAdapter适配器重写 之getView():

(1)View getview(int position, View convertview, ViewGroup parent )

第一个参数position----------该视图在适配器数据中的位置 
第二个参数convertView-----旧视图 
第三个参数parent------------此视图最终会被附加到的父级视图

特别注意:convertview参数

首先讲下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。

如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。

Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说convertView 我们可以复用它,这样就省去了new View的大量开销。

(2)ViewHolder(自定义的):

getView方法:

public View getView(int position, View convertView, ViewGroup parent) {
    System.out.println("getView " + position + " " + convertView);
    ViewHolder holder = null;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.lv_item, null);
        holder = new ViewHolder();
        holder.textView = (TextView)convertView.findViewById(R.id.tv_text);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder)convertView.getTag();
    }
    holder.textView.setText(mData.get(position));
    return convertView;
}

ViewHolder:

package com.shinylife.smalltools;

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

public class ViewHolder {
    public ImageView imgView;
    public TextView textView;
}

为什么要ViewHolder(自定义的)这样一个东西, 因为无论convertView是不是null, 都需要对ViewHolder中的TextView和ImageView进行赋值操作, 貌似没有什么必要.
其实不是这么简单, 这样做是一种拿空间换时间的方式. 增加一个对象ViewHolder , 却省去了一系列的findViewById()的时间,家都知道, 在一个View的树形结构上使用findViewById()查找控件是需要时间的, 而且这个树形结构越复杂, 花费的时间越多。

注意:

我们都知道在getView方法中的操作是这样的:先从xml中创建view对象inflate操作,我们采用了重用convertView方法优化),然后在这个view去findViewById,找到每一个子View,如:一个TextView等。

这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,就是使用viewHolder,把每一个子View都放在Holder中,当第一次创建convertView对象时,把这些子view找出来。

然后用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。当第二次重用convertView时,只需从convertView中getTag取出来就可以。

(3)setTag()/getTag():View中的setTag(Onbect)表示给View添加一个格外的数据,以后可以用getTag()将这个数据取出来

可以用在多个Button添加一个监听器,每个Button都设置不同的setTag。这个监听器就通过getTag来分辨是哪个Button 被按下:

 1 import android.app.Activity;
 2 
 3  import android.os.Bundle; 
 4 
 5 import android.view.View; 
 6 
 7 import android.widget.Button;   
 8 
 9     public class Main extends Activity {   
10 
11             @Override   
12 
13            public void onCreate(Bundle savedInstanceState) {   
14 
15                    super.onCreate(savedInstanceState);   
16                    setContentView(R.layout.main);  
17  
18                    Button button1 = (Button) findViewById(R.id.Button01);   
19                    Button button2 = (Button) findViewById(R.id.Button02);   
20                    Button button3 = (Button) findViewById(R.id.Button03);   
21                    Button button4 = (Button) findViewById(R.id.Button04);   
22 
23                    MyListener listener = new MyListener();   
24                    button1.setTag(1);   
25                    button1.setOnClickListener(listener);   
26                   
27                    button2.setTag(2);   
28                    button2.setOnClickListener(listener);   
29 
30                    button3.setTag(3);   
31                    button3.setOnClickListener(listener);   
32 
33                    button4.setTag(4);   
34                    button4.setOnClickListener(listener);  
35 
36        }   
37 
38                 public class MyListener implements View.OnClickListener {   
39 
40                         @Override   
41                          public void onClick(View v) {   
42                               int tag = (Integer) v.getTag();   
43 
44                              switch (tag) {   
45                            case 1:   
46                                       System.out.println("button1 click");  
47                                     break;   
48 
49                            case 2:   
50                                        System.out.println("button2 click");   
51                                        break;   
52 
53                           case 3:   
54                                        System.out.println("button3 click");   
55                                        break;   
56 
57                            case 4:   
58                                        System.out.println("button4 click");   
59                                        break;   
60                                }  
61                        }  
62              } 
63 
64 }
65             

在写ListView 时候要重写BaseAdapter:

 需要在没个item都加上button 点击button做相应操作

 这个时候需要button里面设置下 这行的属性

button.setTag(item.user.name);

 然后处理button事件。

 这个东西在一些需要用到Adapter自定控件显示方式的时候非常有用

Adapter 有个getView方法,可以使用setTag把查找的view缓存起来方便多次重用:

public View getView(int position, View convertView, ViewGroup parent) {

  ViewHolder vh;

  if (convertView == null) {

      LayoutInflater inflater = (LayoutInflater) mWidgetsSwitchApp.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

      convertView = inflater.inflate(R.layout.app_gallery_item, null);

      vh = new ViewHolder();

      vh.view1 = (ImageView) convertView.findViewById(R.id.view1);

      vh.view2 = (ImageView) convertView.findViewById(R.id.view2);

      vh.view3 = (ImageView) convertView.findViewById(R.id.view3);

      vh.view4 = (ImageView) convertView.findViewById(R.id.view4);

      convertView.setTag(vh);

  } else {

      vh = (ViewHolder) convertView.getTag();

  }

  //其他的代码可以直接使用 vh.view1、vh.view2、vh.view3 、vh.view4

  }

你可以看看android的源码,特别有listview的,你就会发现这个函数很多时候有妙用!呵呵!

我的一点理解是,绑定数据,特别是绑定数据到view。而且可以用getTag()取得,很方便,而且是任意类型的数据,真的很酷。

在实例BaseAdapter()的getView(position, convertView, par)里有用到。convertView这里会用到setTag() getTag()。就可以生成convertView并复用里面的widget,一直觉得这个东西没啥用setTag(),不过只要能用上 就是比较巧的了

在一个程序中呢 我有好多个button 我想点击一个出现1, 点击第二个出现2

 for (int i = 0; i < 20; i++) {

  cells[i] = (ImageView) findViewById(cellIDs[i]);

  cells[cellnumber++].setOnClickListener(new OnClickListener() {

          public void onClick(View v){

                 cellClicked(cellnumber, v);

      }});

  }

上面的代码效率不高 而且 无论点击哪一个都会出现21 当然这是我逻辑错误

那怎么实现呢

  OnClickListener listener = new OnClickListener() {

       public void onClick(View v) {

       int cellId = (Integer) v.getTag();

       cellClicked(cellId, v);

   }

 }

  View v;

  for (int i = 0; i < 20; i++) {

       v = findViewById(cellIDs[i]);

       v.setOnClickListener(listener);

       v.setTag(i);

  }

这样呢就实例话一个listener,同时通过tag传值就不是每一个实例都做了

原文地址:https://www.cnblogs.com/hebao0514/p/4717378.html