Re: [問題] onClickListener的事件處理?

看板AndroidDev作者 (〆)時間14年前 (2012/01/10 16:41), 編輯推噓5(501)
留言6則, 6人參與, 最新討論串5/6 (看更多)
我也來提供一些本身研究過的經驗好了, 有時候不知道你會不會出現一些疑問? 當你為一些元件加入事件以後, 而這些元件產生變化的時候, 為什麼系統會知道是哪一個元件產生變化的呢? 其實他是由一種設計模式產生的, 這種設計模式稱作為"觀察者模式" 什麼叫做觀察者模式, 觀察者模式由三個角色所構成, 分別是觀察者、觀察者物件、主題物件, 假設有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 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.221.115.4

01/10 17:48, , 1F
很仔細 推
01/10 17:48, 1F

01/10 18:07, , 2F
推推推
01/10 18:07, 2F

01/11 00:41, , 3F
真的很實用,釐清好多觀念
01/11 00:41, 3F
※ 編輯: givemepass 來自: 61.221.115.4 (01/11 10:30)

01/13 22:35, , 4F
感謝~又學習到了~!
01/13 22:35, 4F

01/16 17:47, , 5F
實用 這篇該m!
01/16 17:47, 5F

01/17 10:50, , 6F
一講到m文 就想到我們的版主空缺...
01/17 10:50, 6F
文章代碼(AID): #1F2_dGDr (AndroidDev)
討論串 (同標題文章)
文章代碼(AID): #1F2_dGDr (AndroidDev)