• 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传值就不是每一个实例都做了

  • 相关阅读:
    PredictionIO+Universal Recommender快速开发部署推荐引擎的问题总结(1)
    SpringJDBC的JdbcTemplate在MySQL5.7下不支持子查询的问题
    POP3接收邮件
    发送邮件
    电子邮件介绍
    线程优先级队列
    线程同步
    threading模块
    _thread模块
    使用线程
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4717378.html
Copyright © 2020-2023  润新知