顯示廣告
隱藏 ✕
※ 本文為 kewang 轉寄自 ptt.cc 更新時間: 2012-01-30 09:54:08
看板 AndroidDev
作者 givemepass (〆)
標題 Re: [問題] onClickListener的事件處理?
時間 Tue Jan 10 16:41:50 2012


我也來提供一些本身研究過的經驗好了,
有時候不知道你會不會出現一些疑問?
當你為一些元件加入事件以後, 而這些元件產生變化的時候,
為什麼系統會知道是哪一個元件產生變化的呢?
其實他是由一種設計模式產生的, 這種設計模式稱作為"觀察者模式"

什麼叫做觀察者模式,
觀察者模式由三個角色所構成, 分別是觀察者、觀察者物件、主題物件,
假設有4個觀察者物件,其中3個觀察者物件加入了觀察者名單,
每當主題物件發布了某些訊息,
有加入觀察者名單的觀察者物件就會透過觀察者收到該訊息,
沒有加入觀察者名單的觀察者物件當然就不會收到訊息,
而如果已經在觀察者名單內的物件或者不在觀察者名單內的物件,
仍然可以自由的加入觀察者名單或者從觀察者名單內移除。

呵呵,有點頭昏腦脹了嗎?舉個白話點的例子,
現在假設大家都有玩過facebook的經驗,
而facebook有一種模式叫做粉絲團,
當你加入某一個粉絲團的時候, 當該粉絲團發布某項訊息時,
該粉絲團的粉絲都會收到這項訊息,
而當你退出這個粉絲團的時候, 就在也收不到該粉絲團的訊息了!
這樣就稱作一個觀察者模式。

現在把角色換成Button物件、Listener和Event物件,
Event物件就像是粉絲, Button物件的角色就像粉絲團,
當你把某一個Event物件加入了Button物件的Listener名單,
當button物件產生變化的時候, Listener就會去通知加入的Event物件。

button1.setOnClickListener(new OnClickListener(){
   public void onClick(View v){
      textView1.setText("textview1");
   }
});

button1就是主題物件
setOnClickListener的行為就是加入觀察名單
new OnClickListener() 就是觀察者物件

當button產生變化的時候,
觀察者就去觀察者名單內查看有哪些觀察者物件加入,
然後逐一的通知它們。

我們來模擬一下Button按下去的情節,
這個程式用來模擬Android的Button按下的時候, 要處理什麼樣的動作,
首先你還是一樣要先宣告一個事件,然後把這個事件加入button的監聽器,
button1.setOnClickListener(new OnClickListener(){
   public void onClick(View v){
       textView1.setText("textview1");
   }
});
可是我們模擬的button並不是android內建的,
如果要讓android顯示出來這兩個button,
還要在寫一些button的描述, 這樣太複雜了,
因此我們就真的宣告android內建的button,
當button按下的時候, 就去呼叫我們做出來的"假Button"裡面的"onclick",
以達到模擬的效果。

而我們的重點放在模擬
android的button到底是怎麼實作出setOnClickListener()這個方法,

想像一下setOnClickListener是被Button的實體物件呼叫,
因此, 我們可以猜到上層Button這個類別一定有一個方法叫做setOnClickLister(),
並且會傳入OnClickListener這個物件的方法,
所以我們作出一個假button的類別,
interface FButton{
    public void setOnClickListener(FakeOnLister listener);
}
這樣一來, 我們就可以知道有一個類別會繼承這個介面,
然後實作setOnClickListener這個方法。

在來我們想一下既然有傳入OnClickListener這個物件,
而且會實作onClick()這個方法
那麼我們也來定義一個假的Listener
interface FakeOnLister {
    void onClick(int index);
}
由前面知道觀察者模式, 因此我們的Button裡面會出現幾個必要的方法,
首先是加入觀察者物件,移除觀察者物件,以及通知所有觀察者,
所以類別可以這樣寫出來,
class FakeButton implements FButton{
    private List<FakeOnLister> listenerList;
    public FakeButton(){
        listenerList = new ArrayList<FakeOnLister>();
    }
    public void setOnClickListener(FakeOnLister listener) {
        listenerList.add(listener);
    }
    public void removeOnClickListener(FakeOnLister listener){
        int index = listenerList.indexOf(listener);
        if(index>=0){
            listenerList.remove(index);
    }
    public void onClick() {
        for (int i=0; i<listenerList.size(); i++) {
            listenerList.get(i).onClick(i);
        }
    }
}
加入觀察者物件
public void setOnClickListener(FakeOnLister listener)
移除觀察者物件
public void removeOnClickListener(FakeOnLister listener)
通知所有觀察者
public void onClick()

所以可以開始使用這個"假Button"了
private FakeButton fakeButton1;
private FakeButton fakeButton2;

public void onCreate(Bundle savedInstanceState) {
   fakeButton1 = new FakeButton();
   fakeButton2 = new FakeButton();
   fakeButton1.setOnClickListener(new FakeOnLister(){

      @Override
      public void onClick(int index) {
         // TODO Auto-generated method stub
         Toast.makeText(getApplicationContext(), "button1 click",
                           Toast.LENGTH_SHORT).show();
         }

      });
   fakeButton2.setOnClickListener(new FakeOnLister(){

      @Override
      public void onClick(int index) {
         // TODO Auto-generated method stub
         Toast.makeText(getApplicationContext(), "button2 click",
                           Toast.LENGTH_SHORT).show();
      }

   });
}

當我們按下假button 1號就會跳出Toast訊息顯示我們按下的是假button 1號
同理, 假button 2號。

接著我們重複剛剛所說的用真的button去模擬我們寫出來的假button,
借用一下他們的onClick動作來證實我們的button是可以動的。

button1 = (Button)findViewById(R.id.a_button);
button2 = (Button)findViewById(R.id.b_button);
button1.setOnClickListener(new OnClickListener(){

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        fakeButton1.onClick();
    }

});
button2.setOnClickListener(new OnClickListener(){

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        fakeButton2.onClick();
    }

});

如此一來, 我們可以在畫面看到兩個button,
http://uploadingit.com/file/wa6dhpapqo8ifzbs/button1.png
http://uploadingit.com/file/ak5fyrsmnhakrlmz/button2.png
[圖]
 
[圖]
 
當按下去的時候, 的確可以跑到我們一開始所期望的情況。

如果觀念有錯 請指教 謝謝:)

完整程式碼
http://uploadingit.com/file/zqfevrlk7miglqqx/ButtonEventSimulateDemo.zip
Downloading: ButtonEventSimulateDemo.zip - Uploadingit
Uploadingit allows you to upload, download, sync and share files easily across the web. Sign up today and get 10 GB of free storage! ...
 

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.221.115.4
LaPass:很仔細 推1F 01/10 17:48
tericky:推推推2F 01/10 18:07
eplis:真的很實用,釐清好多觀念3F 01/11 00:41
※ 編輯: givemepass      來自: 61.221.115.4         (01/11 10:30)
godpro:感謝~又學習到了~!4F 01/13 22:35
ENEP:實用 這篇該m!5F 01/16 17:47
mamaya3:一講到m文 就想到我們的版主空缺...6F 01/17 10:50

--
※ 看板: FW 文章推薦值: 0 目前人氣: 0 累積人氣: 195 
作者 givemepass 的最新發文:
  • +37 [新聞] 部落少女深夜遭父強姦 隔天一早...拿刀 - Gossiping 板
    作者: 61.224.86.33 (台灣) 2013-06-18 14:24:33
    1.媒體來源: ETtoday國際新聞| ETtoday 新聞雲 2.完整新聞標題/內文: 部落少女深夜遭父強姦 隔天一早...拿刀割下爸爸人頭 國際中心/綜合報導 文明?野蠻?巴布亞新幾內亞一名18 …
    60F 37推
  • +40 [新聞] 台灣網友,一個月上線23.5小時 - Gossiping 板
    作者: 1.170.124.32 (台灣) 2013-05-23 14:25:35
    1.媒體來源: 時報資訊 2.完整新聞標題/內文: 台灣網友,一個月上線23.5小時 時報記者莊丙農台北報導 創市際ARO公佈comScore Media Metrix台灣2013年4月網路流量報告, …
    81F 44推 4噓
  • +5 Re: [問題] onClickListener的事件處理? - AndroidDev 板
    作者: 61.221.115.4 (台灣) 2012-01-10 16:41:50
    我也來提供一些本身研究過的經驗好了, 有時候不知道你會不會出現一些疑問? 當你為一些元件加入事件以後, 而這些元件產生變化的時候, 為什麼系統會知道是哪一個元件產生變化的呢? 其實他是由一種設計模式產 …
    6F 5推
  • +5 Re: [問題] onClickListener的事件處理? - AndroidDev 板
    作者: 61.221.115.4 (台灣) 2012-01-10 10:38:24
    假設你有兩個元件要建立事件 也許你會這樣做 button1 = (Button)findViewById(R.id.btn1); button2 = (Button)findViewById(R.id …
    7F 5推
  • +38 [好雷] 啟動原始碼-用source code看Source Code - movie 板
    作者: 61.221.115.4 (台灣) 2011-04-25 10:31:46
    class Task extends TimerTask { public void run() { //計時八分鐘 } } public class SourceCode { //建立一個Sean …
    56F 38推
點此顯示更多發文記錄
分享網址: 複製 已複製
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇