• ListView中含有Button时setOnclickListener应写在Adapter的什么地方


    做Android开发,ListView是最常见不过了,因此对于ListView的自定义Adapter写法,应该也非常的熟悉,高效的Adapter编码,会使得携带大量ListView的数据展现显得非常容易。关于Adapter的写法,网上也有很多的例子,在此不再唠叨。为了提高ListView重绘时对已有对象的复用大抵是这样的:

     

    1. @Override  
    2. public View getView(final int position, View convertView, ViewGroup parent) {  
    3.     ViewHolder holder = null;  
    4.     if (convertView == null) {  
    5.         convertView = View.inflate(mContext, R.layout.listview_item, null);  
    6.         holder = new ViewHolder();  
    7.         holder.no = (TextView) convertView.findViewById(R.id.no);  
    8.         holder.click = (TextView) convertView.findViewById(R.id.click);  
    9.         convertView.setTag(holder);  
    10.     } else {  
    11.         holder = (ViewHolder) convertView.getTag();  
    12.     }  
    13.     String value = list.get(position);  
    14.     holder.no.setText(value);  
    15.       
    16.     OnClick listener = new OnClick(position);  
    17.     holder.click.setOnClickListener(listener);  
    18.       
    19.     Log.d(TAG,  
    20.             "position is " + position + " listener is "  
    21.                     + listener.toString());  
    22.     return convertView;  
    23. }  

    在这里我们讨论的是在ListView当中含有需要处理OnClick事件的写法,之前也写过一篇关于ListView当中含有Spinner的处理情况,这篇文章讲了如何处理Spinner的Onlick事件和对其状态的保持。虽然Onclick事件处理的比较高效,但是在方法上还有待提高。以下文章将列举出网上关于ListView中含有Onclick事件需要处理的普遍写法和本文的重点推荐高效写法。

     

    普遍写法:

     

    1. package com.yang.listviewclick.adapter;  
    2.   
    3. import java.util.List;  
    4.   
    5. import android.content.Context;  
    6. import android.util.Log;  
    7. import android.view.View;  
    8. import android.view.ViewGroup;  
    9. import android.view.View.OnClickListener;  
    10. import android.widget.BaseAdapter;  
    11. import android.widget.TextView;  
    12.   
    13. import com.yang.listviewclick.R;  
    14.   
    15. public class IneffectiveListViewAdapter extends BaseAdapter {  
    16.     private Context mContext;  
    17.     private List<String> list = null;  
    18.   
    19.     private static final String TAG = "ListViewAdapter";  
    20.   
    21.     public IneffectiveListViewAdapter(Context mContext, List<String> list) {  
    22.         this.mContext = mContext;  
    23.         this.list = list;  
    24.     }  
    25.   
    26.     @Override  
    27.     public int getCount() {  
    28.         return list.size();  
    29.     }  
    30.   
    31.     @Override  
    32.     public Object getItem(int position) {  
    33.         return list.get(position);  
    34.     }  
    35.   
    36.     @Override  
    37.     public long getItemId(int position) {  
    38.         return 0;  
    39.     }  
    40.   
    41.     class ViewHolder {  
    42.         TextView no;  
    43.         TextView click;  
    44.     }  
    45.   
    46.     @Override  
    47.     public View getView(final int position, View convertView, ViewGroup parent) {  
    48.         ViewHolder holder = null;  
    49.         if (convertView == null) {  
    50.             convertView = View.inflate(mContext, R.layout.listview_item, null);  
    51.             holder = new ViewHolder();  
    52.             holder.no = (TextView) convertView.findViewById(R.id.no);  
    53.             holder.click = (TextView) convertView.findViewById(R.id.click);  
    54.             convertView.setTag(holder);  
    55.         } else {  
    56.             holder = (ViewHolder) convertView.getTag();  
    57.         }  
    58.         String value = list.get(position);  
    59.         holder.no.setText(value);  
    60.         //问题出在这里,对于每次重绘,都新建了一个listener对象进行处理  
    61.         OnClick listener = new OnClick(position);  
    62.         holder.click.setOnClickListener(listener);  
    63.           
    64.         Log.d(TAG,  
    65.                 "position is " + position + " listener is "  
    66.                         + listener.toString());  
    67.         return convertView;  
    68.     }  
    69.   
    70.     class OnClick implements OnClickListener {  
    71.         private int position;  
    72.         public OnClick(int position){  
    73.             this.position = position;  
    74.         }  
    75.         @Override  
    76.         public void onClick(View v) {  
    77.             Log.d(TAG, list.get(position));  
    78.         }  
    79.     }  
    80. }  

    这种写法能够实现基本功能,即在点击某个组件时,它能够准确的定位到所点击的那个条目,并作出相应的处理。那么这是一种高效的写法吗?我们打印以下它的listener.

     


    大家知道

     

    1. position is 19 listener is com.yang.listviewclick.adapter.IneffectiveListViewAdapter$OnClick@4057f250  

    @后面的值是这个对象的HashCode,对于不同的对象来说,其HashCode是不同的,而这里打印出来的所有HashCode都不相同,说明每次拖动ListView,其会对每个条目重新申请一个对象,而且这些对象不是复用的,是全新的对象。你可以想象以下,如果有一千个条目,这拖动一次就是一千个对象,而且你再回到顶部又是一千个对象,效率可见一斑。

     

    推荐写法:

     

    1. package com.yang.listviewclick.adapter;  
    2.   
    3. import java.util.List;  
    4.   
    5. import com.yang.listviewclick.R;  
    6.   
    7. import android.content.Context;  
    8. import android.util.Log;  
    9. import android.view.View;  
    10. import android.view.View.OnClickListener;  
    11. import android.view.ViewGroup;  
    12. import android.widget.BaseAdapter;  
    13. import android.widget.TextView;  
    14.   
    15. public class EffectiveListViewAdapter extends BaseAdapter {  
    16.     private Context mContext;  
    17.     private List<String> list = null;  
    18.   
    19.     private static final String TAG = "ListViewAdapter";  
    20.   
    21.     public EffectiveListViewAdapter(Context mContext, List<String> list) {  
    22.         this.mContext = mContext;  
    23.         this.list = list;  
    24.     }  
    25.   
    26.     @Override  
    27.     public int getCount() {  
    28.         return list.size();  
    29.     }  
    30.   
    31.     @Override  
    32.     public Object getItem(int position) {  
    33.         return list.get(position);  
    34.     }  
    35.   
    36.     @Override  
    37.     public long getItemId(int position) {  
    38.         return 0;  
    39.     }  
    40.   
    41.     class ViewHolder {  
    42.         TextView no;  
    43.         TextView click;  
    44.     }  
    45.   
    46.     @Override  
    47.     public View getView(final int position, View convertView, ViewGroup parent) {  
    48.         ViewHolder holder = null;  
    49.         OnClick listener = null;  
    50.         if (convertView == null) {  
    51.             convertView = View.inflate(mContext, R.layout.listview_item, null);  
    52.             holder = new ViewHolder();  
    53.             holder.no = (TextView) convertView.findViewById(R.id.no);  
    54.             holder.click = (TextView) convertView.findViewById(R.id.click);  
    55.             listener = new OnClick();//在这里新建监听对象  
    56.             holder.click.setOnClickListener(listener);  
    57.             convertView.setTag(holder);  
    58.             convertView.setTag(holder.click.getId(), listener);//对监听对象保存  
    59.         } else {  
    60.             holder = (ViewHolder) convertView.getTag();  
    61.             listener = (OnClick) convertView.getTag(holder.click.getId());//重新获得监听对象  
    62.         }  
    63.         String value = list.get(position);//设置监听对象的值  
    64.         holder.no.setText(value);  
    65.         listener.setPosition(position);  
    66.         Log.d(TAG,  
    67.                 "position is " + position + " listener is "  
    68.                         + listener.toString());  
    69.         return convertView;  
    70.     }  
    71.   
    72.     class OnClick implements OnClickListener {  
    73.         int position;  
    74.   
    75.         public void setPosition(int position) {  
    76.             this.position = position;  
    77.         }  
    78.   
    79.         @Override  
    80.         public void onClick(View v) {  
    81.             Log.d(TAG, list.get(position));  
    82.         }  
    83.     }  
    84.   
    85. }  

    打印以下Listener

     



    大家可以看到,这里监听对象实现了复用。每次滑动都是第一次创建的监听对象的复用。

    实现这种机制的关键就是,使用convertView.setTag(holder.click.getId(), listener);对已有的对象进行保存,同时在使用时,使用listener = (OnClick) convertView.getTag(holder.click.getId())再获得这些对象。同时对这些复用的对象赋予不同的值listener.setPosition(position);。好了,今天就说到这里,测试项目的下载地址如下。

  • 相关阅读:
    (译+原)std::shared_ptr及std::unique_ptr使用数组
    (转+原)ipp "No dlls were found in the Waterfall procedure"
    (原)vs2013编译boost1.60库
    (原+转)VS2013:正在从以下位置加载符号
    (原)直方图的相似性度量
    (原)Opencv中直方图均衡和图像动态范围拉伸的代码
    JAVA 8 新特性 Stream API 创建
    JAVA 8 新特性 Stream API 介绍
    JAVA 8 新特性 方法引用
    JAVA 8 新特性 函数式接口
  • 原文地址:https://www.cnblogs.com/LiaoHao/p/3366055.html
Copyright © 2020-2023  润新知