ListView的Item中設置Button點擊事件優化,避免重複new Listener

原文地址:http://blog.csdn.net/gao_chun/article/details/41249131


在應用開發中經常會用到ListView,並且每一個Item裏面都會有按鈕之類的需要進行事件監聽的控件。在給按鈕添加OnClickListener的時候,一開始很下意識的會想在ListView的adapter的getView方法中找到每個Button並new一個OnClickListener分配給這個button。

但是當數據量很大的時候,new出來這麼多個監聽器勢必會對內存造成一定的壓力,而且每個Listener的功能完全一樣,Listener裏面所需知道的,不過是調用者所在的Item的index而已。怎麼樣才能更好地利用內存呢?既然每個Listener的功能一樣,那麼完全可以用單例模式構造一個Listener。


如下:

  1. class MyOnClickListener implements OnClickListener {  
  2.   
  3.    private static MyOnClickListener instance = null;  
  4.        
  5.    private MyOnClickListener() {  
  6.     }  
  7.   
  8.    public static MyOnClickListener getInstance() {  
  9.        if (instance == null)  
  10.             instance = new MyOnClickListener() ;  
  11.         return instance;  
  12.     }  
  13.   
  14.    @Override  
  15.      public void onClick(View view) {  
  16.         //TODO: do something here  
  17.    }  
  18. }  


而在getView方法中,獲取到button實例之後,只需要通過button.setOnClickListener(MyOnClickListener.getInstance());對按鈕設置監聽器了。這樣的話每一個按鈕便必然用的是同一個Listener對象。


但是我們的需求並不止於此,很多時候,我們還需要知道具體是哪個position的button被點擊了,我們需要根據position在
Listener裏面做出不一樣的動作。


想要在Listener內部瞭解外部控件的屬性,我們首先想到的是傳參,但是由於我們的Listener使用的是單例模式,每個按鈕往Listner裏面傳的參數必然會

覆蓋前一個按鈕傳的參數。於是我們的解決方案只剩下一種,那就是通過onClick函數的參數(View view)來獲取該信息。然而,此處的view應該是一個Button,

而Button是不具備position信息的。又於是,自然而然的,解決方案出來了:重載Button類


  1. class MyButton extends Button {  
  2.   
  3.     private int index = -1;  
  4.   
  5.     public int getIndex() {  
  6.         return index;  
  7.     }  
  8.   
  9.    public void setIndex(int index) {  
  10.         this.index = index;  
  11.    }  
  12.   
  13.     public MyButton(Context context) {  
  14.         super(context);  
  15.          // TODO: do something here if you want  
  16.      }  
  17.   
  18.     public MyButton(Context context, AttributeSet attrs) {  
  19.          super(context, attrs);  
  20.          // TODO: do something here if you want  
  21.     }  
  22.   
  23.     public MyButton(Context context, AttributeSet attrs, int defStyle) {  
  24.        super(context, attrs, defStyle);  
  25.         // TODO: do something here if you want  
  26.      }  
  27.  }  



接下來我們需要做的,就是在xml文件中,將item裏面的Button的類型改成我們自定義的MyButton。

即將<Button> </Button>改成<your.package.name.MyButton> </your.package.name.MyButton>,而在adapter的getView函數裏面則把findViewById()獲得的返回值強制轉換成爲MyButton,並調用其setIndex函數設置Index值。同時MyOnClickListener中重載的的onClick函數也一樣將view對象轉換成MyButton類型,並通過調用getIndex函數獲取position信息,以做相應操作。


Adapter中:

  1. // ....  
  2. MyButton button = null;  
  3. // ....  
  4. @Override  
  5. public View getView(int position, View convertView, ViewGroup parentView) {  
  6.    View view = convertView;  
  7.    if (convertView == null) {  
  8.         view = LayoutInflater.from(activity).inflate(R.layout.company_detail_campus_talk_item, null);  
  9.      }  
  10.   
  11.     // ....  
  12.   
  13.    button = (MyButton) view.findViewById(R.id.YOUR_BUTTON_ID);  
  14.     button.setIndex(position);  
  15.     button.setOnClickListener(MyOnClickListener.getInstance());  
  16. }  



MyOnClickListener中:

  1. // ....  
  2. @Override  
  3. public void onClick(View view) {  
  4.   
  5.     int index = ((MyButton)view).getIndex();  
  6.   
  7.    // ....  
  8. }  


這樣,我們便實現了使用同一個Listener對ListView中不同Item的按鈕進行事件監聽處理的業務邏輯。

如果需要在Adapter和Listener之間共享數據的話,可以通過增加Listener的getInstance函數的參數以及Listener類的成員變量實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章