溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android 基于回調(diào)的事件處理----事件分發(fā)

發(fā)布時(shí)間:2020-06-30 13:59:47 來源:網(wǎng)絡(luò) 閱讀:1217 作者:poarry 欄目:移動開發(fā)

     Android事件處理機(jī)制有兩種:

     基于監(jiān)聽的事件處理

     基于回調(diào)的事件處理。

     基于監(jiān)聽的想必學(xué)過java或者接觸過Android的都了解,最近看了一下有關(guān)回調(diào)方面的書,今天主要是想說一下基于回調(diào)的事件處理機(jī)制。多為我自己的理解總結(jié)和借鑒別人的一些東西,有錯誤或者不理解的地方可以在評論處指出來,謝謝~

    基于回調(diào)事件處理的做法:

     重寫Android組件特定的回調(diào)方法,或者重寫activity的回調(diào)方法,Android絕大部分界面組件都提供有事件響應(yīng)的回調(diào)方法,開發(fā)者只要重寫即可。一般的,基于回調(diào)的事件處理可用于具有通用型事件,它的代碼簡潔。

    一、回調(diào)機(jī)制和監(jiān)聽機(jī)制

    對于基于回調(diào)事件處理模型來說事件源與事件監(jiān)聽器是統(tǒng)一的,就是說當(dāng)用戶在GUI組件上激發(fā)某個事件時(shí),組件自己特定的方法將負(fù)責(zé)處理該事件。為了使用回調(diào)機(jī)制類處理GUI組件上發(fā)生的事件,我們需要為該組件提供對應(yīng)的事件處理方式,但是java是靜態(tài)語言,我們無法為某個對象動態(tài)添加方法,只能繼承GUI組件類,然后重寫該類的事件處理方法來實(shí)現(xiàn)。

    為實(shí)現(xiàn)回調(diào)機(jī)制的事件處理,Android為所有GUI組件都提供了一些事件處理的回調(diào)方法。以View為例,該類包含如下方法:

  boolean onKeyDown(int keyCode,KeyEvent event):當(dāng)用戶在該組件上按下某個按鍵時(shí)觸發(fā)該方法。

 boolean onKeyLongPress(int keyCode,KeyEvent event):當(dāng)用戶在該組件上長按某個按鍵時(shí)觸發(fā)該方法。

 boolean onKeyShortcut(int keyCode,KeyEvent event):當(dāng)一個鍵盤快捷鍵事件發(fā)生時(shí)觸發(fā)該方法。

 boolean onKeyup(int keyCode,KeyEvent event):當(dāng)用戶在該組件上松開某個按鍵時(shí)觸發(fā)該方法。

 boolean onTouchEvent(MotionEvent event):當(dāng)用戶在該組件上觸發(fā)觸摸屏?xí)r觸發(fā)該方法。

 boolean onTrackballEvent(MotionEvent  event):當(dāng)用戶在該組件上軌跡球屏事件時(shí)觸發(fā)該方法。

 基于回調(diào)的事件處理機(jī)制可通過自定義View來實(shí)現(xiàn),自定義View時(shí)重寫該View的事件處理方法即可。

如下例子

自定義Button類:

package com.example.testnoew;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Button;

public class MyButton extends Button{

 public MyButton(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub
 }

 @Override
 public boolean onKeyDown(int keyCode,KeyEvent event){
  
  super.onKeyDown(keyCode, event);
  Log.v("MYPROJECT", "onKeyDown in MYBUTTON");
  //返回TRUE 表明該事件不會向外擴(kuò)散;
  return true;
 }
}

 

xml文件:

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- 自定義View用時(shí)使用全限定類名 -->
 <com.example.testnoew.MyButton
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="Click Me"
    
     />

</RelativeLayout>

然后再activity中調(diào)用這個xml文件就好了,接下來運(yùn)行起來看你的Logcat(不會過濾logcat就自己網(wǎng)上去看),因?yàn)橹貙懙腗yButton中的onKeyDown消費(fèi)了點(diǎn)擊事件,因此不會傳播出去,也就是說按鈕會自己處理事件(當(dāng)然實(shí)際開發(fā)中這個部分就是我們要自己寫東西)。


    二、基于回調(diào)的事件傳播(事件分發(fā)機(jī)制)

幾乎所有的基于回調(diào)的事件處理方法都有一個Boolean類型的返回值,該返回值用于標(biāo)識該處理方法是否能完全處理該事件。

      如果處理事件的回調(diào)方法返回true,表明該處理方法已完全處理該事件(已消費(fèi)掉)。該事件不會傳播出去。

    如果處理事件的回調(diào)方法返回false,表明該處理方法未完全處理該事件,該事件會傳播出去。

 

對于基于回調(diào)的事件傳播而言,某組件所發(fā)生的事情不僅能夠激發(fā)該組件的回調(diào)方法,也會觸發(fā)該組件所在的activity的回調(diào)方法(只要能夠傳播到該activity,也就是說某組件不把這個事件消費(fèi)掉)。

 

 

 

主activity ,重寫onKeyDown方法,該方法會在某個按鍵被按下時(shí)被回調(diào)

public class MainActivity extends Activity {


 

 private Button testButton;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  testButton = (Button)findViewById(R.id.btn_test);
  testButton.setOnKeyListener(new OnKeyListener() {

   public boolean onKey(View Source,int kyeCode,KeyEvent event)
    {
    //只處理按下的事件
     if(event.getAction() == KeyEvent.ACTION_DOWN){
      Log.i("MYPROJECT", "in Activity Button Listener!");
     }
     //表明該事件會向外繼續(xù)傳播
     return false;
    }

  });
 }

 /*
  * (non-Javadoc)
  * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
  * onKeyDown方法可監(jiān)聽整個activity包含的所有組件的按鍵被按下事件
  *
  */
 public boolean onKeyDown(int keyCode, KeyEvent event){
  
   super.onKeyDown(keyCode, event);
   Log.i("MYPROJECT", "in Activity");
   
  return false;
  
 }
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }

}

 

自定義的MyButton類

 

 

package com.example.testnoew;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Button;

public class MyButton extends Button{

 public MyButton(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub
 }

 @Override
 public boolean onKeyDown(int keyCode,KeyEvent event){
  
  super.onKeyDown(keyCode, event);
  Log.v("MYPROJECT", "onKeyDown in MYBUTTON");
  //返回false 表明該事件沒有被空間本身自己處理,會向外傳播;
  return false;
 }
}

xml文件基本沒變,只是給自定義的Button添加了一個id;

通過我們看自己的logcat可以發(fā)現(xiàn)當(dāng)該組件上某個按鍵被按下的事件發(fā)生時(shí),Android系統(tǒng)會最先觸發(fā)該按鍵綁定的事件監(jiān)聽器,然后觸發(fā)該組件提供的事件回調(diào)方法,然后會傳播到該組件所在的activity中。當(dāng)然如果我在回調(diào)或者事件監(jiān)聽中返回true,那么意味著該事件不會繼續(xù)向外傳播 。

 


    三、重寫onTouchEvent方法響應(yīng)觸摸屏事件

    Android事件處理機(jī)制保證基于監(jiān)聽的事件監(jiān)聽器會被有限觸發(fā)。

    基于監(jiān)聽的事件模式分工明確,事件源,事件監(jiān)聽由兩個類分開,實(shí)現(xiàn),因此可維護(hù)性好點(diǎn)。

    基于回調(diào)的事件處理機(jī)制一定程度上具有高內(nèi)聚的特性。

具體的實(shí)例和上面的大同小異,比如, 我自定義控件,然后再自定義控件內(nèi)部重寫onTouchEvent事件,在這個事件中處理比如位置、大小等變化,然后返回 true,這樣所在的activity就不會再處理它。

然后再xml中直接調(diào)用這個控件就好了。

 

 

 

 

      本人也是剛工作不到半年,然后這些東西也是看了寫書才有所理解,在這里拋磚引玉,有不對的地方歡迎來噴。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI