亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

全部開發者教程

Android 入門教程

菜單類控件
菜單:Menu
并發編程
多線程

基于監聽的事件處理機制

在前面的章節我們都是以開發布局為主,涉及到的邏輯非常少,這樣安排是因為編寫 UI 會更加直觀,寫完即能看到效果,可以增加我們的學習興趣,并能夠對 Android 開發有一個直觀的感受。在我們設計出精美的 UI 之后,需要讓它服務于我們的應用程序,這就需要有事件處理機制了,讓各個 View 進行操作的時候它會執行相應的邏輯,完成我們給它分配的任務。

1. 事件處理

事件對應一個行為,它通常發生在用戶和App進行交互的時候,比如輸入文字、點擊按鈕、手勢等等。Android系統將事件處理設計成了一種先進先出(FIFO)的隊列形式,所以我們可以按照用戶操作的順序來依次處理用戶事件

2. 事件監聽

在系統發生了一個事件之后,我們如何接收到這個事件呢?這就需要在事件發生之前提前向系統注冊一個事件監聽器,告訴 Android 系統我關心那些事件,那么系統就會在事件發生的相應時間點給你一個回調通知,常見的事件監聽器有以下幾個:

  • OnClickListener:
    用來監聽控件的點擊事件,即在用戶點擊某個 View 的時候回調此接口。(這也是開發過程中最最最常見的接口,一定要牢牢掌握!
  • OnLongClickListener:
    顧名思義,在 View 被長按的時候回調
  • OnFocusChangeListener:
    當控件的焦點發生變化的時候回調
  • OnKeyListener:
    當用戶點擊手機上的按鍵的時候回調此接口,通常可以用來攔截按鍵事件,然后針對特殊場景做特殊處理
  • OnTouchListener:
    當用戶觸摸屏幕的時候回調,此接口會發生在OnClickListener回調的前面,所以我們可以在Touch事件進行一些更早期的預處理事務。
  • OnMenuItemClickListener:
    當用戶點擊菜單的時候調用

以上就是 Android 系統提供的常用事件處理監聽器,其中最為常見的就是OnClickListener,未來的開發中會大量的使用到,所以必須掌握。所以接下來會以OnClickListener為例子來演示如何完成事件處理,其他的監聽器使用方式也都大同小異。

3. 事件處理方式

事件處理要經過以下 4 大步驟:

  1. 注冊監聽器
  2. 用戶進行相應操作,系統將事件入隊
  3. 事件經過系統層層分發,最終回調步驟 1 中注冊的接口
  4. 執行回調中的邏輯,完成事件處理

Android 中所有的事件處理都會經過以上 4 個步驟,但是具體的處理方式會有所不同,接下來介紹一下幾種不同的處理方式,最終達到的效果是每次點擊 Button 的時候彈出一個 Toast,如下圖:

圖片描述

3.1 聲明內部類

通過新增內部類的形式實現OnClickListener接口,代碼如下:


package com.emercy.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.bottom);
        button.setOnClickListener(new EventHandle());
    }

    private class EventHandle implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this, "Button被點擊了", Toast.LENGTH_LONG).show();
        }
    }
}

3.2 匿名內部類

匿名內部類的寫法會比較簡單直接,但是缺點是只能用一次,并且代碼會集中在方法體內,如果處理邏輯過于復雜會導致方法代碼冗余。所以通常在只需要使用一次并且內部邏輯不太復雜的時候使用。


package com.emercy.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        // 創建匿名內部類綁定點擊監聽器
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 在回調中處理點擊事件
                Toast.makeText(MainActivity.this, "Button被點擊了", Toast.LENGTH_LONG).show();
            }
        });
    }
}

3.3 外部類

如果你的事件處理邏輯需要在多個類中使用,那么以上兩種方式都無法滿足,這時候就需要聲明一個外部類來實現OnClickListener接口了:

package com.emercy.myapplication;

import android.content.Context;
import android.view.View;
import android.widget.Toast;

public class EventHandle implements View.OnClickListener {

    Context mContext;

    public EventHandle(Context context) {
        mContext = context;
    }

    @Override
    public void onClick(View v) {
        // 點擊回調中處理事件
        Toast.makeText(mContext.getApplicationContext(), "Button被點擊了", Toast.LENGTH_LONG).show();
    }
}

由于需要彈 Toast,所以這里在構造器中傳入了一個 Context 對象,這樣一來 MainActivity 就可以更整潔一些了:


package com.emercy.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        // 綁定點擊監聽器
        button.setOnClickListener(new EventHandle(this));
    }
}

3.4 Activity 自身實現接口

我們也可以讓 Activity 去實現 OnClickListener接口,這樣就可以直接在 Activity 中覆寫 OnClick方法,將所有的邏輯都封裝在了 Activity 內部:


package com.emercy.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        // 直接綁定Activity即可
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // 在回調中處理點擊事件
        Toast.makeText(MainActivity.this, "Button被點擊了", Toast.LENGTH_LONG).show();
    }
}

3.5 通過 xml 標簽指定

以上四種本質上其實都是通過實現OnClickListener接口去監聽點擊事件的,除此之外還可以在通過布局文件中添加onClick標簽的方式靜態綁定點擊事件。這種寫法非常少見,在某些場景下可以幫助簡化很多代碼,但是它不太靈活,大家了解一下即可:
首先在 xml 中找到對應的 <Button/> 標簽,然后添加onClick屬性:

<?xml version="1.0" encoding="utf-8"?>

<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:onClick="eventHandle"
    android:text="點擊事件處理">

</Button>

接著在 Activity 中聲明eventHandle方法,這樣就不需要手動獲取 Button 實例,也不用綁定點擊事件了。(注意eventHandle的方法簽名必須是固定的)

package com.emercy.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // Java代碼中無需綁定,直接實現處理函數即可
    public void eventHandle(View v) {
        Toast.makeText(getApplicationContext(), "Button被點擊了", Toast.LENGTH_LONG).show();
    }
}

4. 總結

本節介紹了 Android 的事件處理機制以及主要常用的集中事件,并以最常用的OnClickListener為例詳細講解了集中實現方式,其他的集中事件幾乎都是照壺畫瓢,大家有興趣的也可以模仿本節示例自行實現一下。在本節之前的內容大多是為 UI 布局為主,本節之后大家將會見到很多事件相應及邏輯控制,只有將 UI 和事件處理和在一起,才能寫出各式各樣的App,你打算寫一個什么樣的呢?