Android实现事件监听常用的几种方法(附带源码)

🎯 义乌365便民中心电话 📅 2025-12-12 20:01:01 👤 admin 👀 3775 ❤️ 203
Android实现事件监听常用的几种方法(附带源码)

一、项目介绍

1.1 背景与意义

在 Android 应用开发中,事件驱动 是核心设计思想之一。用户与系统的交互、组件间的通信、异步消息的处理,几乎都离不开事件监听机制。掌握并灵活运用多种事件监听方式,能够帮助我们构建高内聚、低耦合、易维护的应用架构。

本篇博客旨在全面梳理并示范 Android 中常用的 事件监听实现方法,包括但不限于:

视图交互事件:OnClickListener、OnTouchListener、OnLongClickListener 等

组件回调事件:接口回调、匿名内部类、Lambda 表达式

广播事件:BroadcastReceiver(全局、局部、静态、动态注册)

内容监听:ContentObserver

系统服务:SensorEventListener、LocationListener、OnSharedPreferenceChangeListener

框架支持:LiveData 观察者、RxJava/RxAndroid、EventBus/GreenRobot、Kotlin Flow

Handler 消息机制:Handler.Callback、Message 传递

自定义事件总线:观察者模式实现

通过示例代码与深入剖析,帮助你在实际项目中,根据场景选用最合适的事件监听方案。

1.2 功能需求

视图交互:演示按钮点击、双击、长按、触摸、滑动等事件监听;

接口回调:封装自定义组件,使用接口回调方式向宿主 Activity/Fragment 通知事件;

广播注册:演示网络状态 / 屏幕开关广播的动态与静态注册;

ContentObserver:监听通讯录或系统设置变化;

传感器监听:加速度传感器、磁场传感器的实时回调;

定位监听:GPS / 网络定位更新事件;

SharedPreferences:偏好设置变化监听;

LiveData:在 MVVM 中使用 observe() 监听数据变化;

RxJava:使用 PublishSubject、Observable 监听自定义事件与 UI 事件;

EventBus:GreenRobot EventBus 注册与接收自定义事件;

Handler/Message:在子线程向主线程发送消息并处理;

自定义事件总线:手写简易观察者模式实现跨组件通信。

1.3 技术选型

语言:Kotlin

架构:MVVM + LiveData

第三方:RxJava/RxAndroid、GreenRobot EventBus

UI:ConstraintLayout + RecyclerView

权限:部分示例需电话、位置、传感器权限

模拟环境:Android 8.0+

二、相关知识

在开始实现前,请确保对以下知识有所掌握:

View 事件体系

View.OnClickListener、OnTouchListener、OnLongClickListener、OnKeyListener 等接口;

MotionEvent 中 ACTION_DOWN/MOVE/UP/POINTER_* 的意义与坐标获取;

接口回调

在自定义 View 或组件中定义接口,通过宿主注册 setListener(...) 并回调;

BroadcastReceiver

静态注册( + )与动态注册(registerReceiver());

局部广播:LocalBroadcastManager;

ContentObserver

通过 ContentResolver.registerContentObserver() 监听 URI 变化;

SensorEventListener

获取 SensorManager,注册重力、加速度、磁场传感器并在回调中处理;

LocationListener

使用 FusedLocationProviderClient 或原生 LocationManager 监听位置更新;

SharedPreferences

registerOnSharedPreferenceChangeListener() 监听键值更改;

LiveData & ViewModel

配合 DataBinding 在 Activity/Fragment 中 viewModel.data.observe(...);

RxJava/RxAndroid

Observable.create()、PublishSubject 以及在主线程订阅;

EventBus

GreenRobot EventBus 的 @Subscribe 注解、线程模型与生命周期管理;

Handler/Message

在子线程发 handler.sendMessage(msg),主线程 handleMessage() 逻辑;

自定义事件总线

观察者模式核心:接口 + 注册/注销 + 回调集合;

三、实现思路

我们将按功能模块分段落,最后整合代码:

视图交互示例:Activity 中演示 Button 点击、Touch、Long Click;

组件接口回调:自定义 MyCustomView,通过接口将事件抛给宿主;

广播监听:动态监听网络变化,静态监听关机重启;

ContentObserver:监听系统联系人变化并更新 UI;

传感器与定位监听;

SharedPreferences 监听;

LiveData 监听;

RxJava 事件监听;

EventBus 事件总线;

Handler/Message 示例;

自定义事件总线实现;

整合到一个项目中:所有示例在一个 Demo 应用里,包结构清晰。

四、整合代码

以下整合了所有示例代码到一个 Demo 项目中,用注释区分文件。请按需复制到各自文件。

// ---------------- 文件: build.gradle ----------------

/*

plugins {

id 'com.android.application'

id 'kotlin-android'

}

android {

compileSdkVersion 34

defaultConfig {

applicationId "com.example.eventdemo"

minSdkVersion 21

targetSdkVersion 34

versionCode 1

versionName "1.0"

}

buildFeatures { dataBinding true }

}

dependencies {

implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0"

implementation "androidx.core:core-ktx:1.10.1"

implementation "androidx.appcompat:appcompat:1.7.0"

implementation "com.google.android.material:material:1.9.0"

implementation "androidx.constraintlayout:constraintlayout:2.1.4"

implementation "androidx.recyclerview:recyclerview:1.3.1"

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1"

implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1"

implementation "io.reactivex.rxjava3:rxjava:3.3.0"

implementation "io.reactivex.rxjava3:rxandroid:3.0.0"

implementation "org.greenrobot:eventbus:3.4.0"

}

*/

// ---------------- 文件: AndroidManifest.xml ----------------

xmlns:android="http://schemas.android.com/apk/res/android">

android:name=".App"

android:label="EventDemo"

android:theme="@style/Theme.App">

// ---------------- 文件: App.kt ----------------

package com.example.eventdemo

import android.app.Application

class App: Application()

// ---------------- 文件: ui/MainActivity.kt ----------------

package com.example.eventdemo.ui

import android.Manifest

import android.content.*

import android.net.ConnectivityManager

import android.os.*

import android.provider.ContactsContract

import android.view.MotionEvent

import android.widget.Toast

import androidx.activity.result.contract.ActivityResultContracts

import androidx.appcompat.app.AppCompatActivity

import androidx.core.content.ContextCompat

import androidx.databinding.DataBindingUtil

import androidx.lifecycle.lifecycleScope

import com.example.eventdemo.R

import com.example.eventdemo.databinding.ActivityMainBinding

import com.example.eventdemo.event.CustomEvent

import com.example.eventdemo.ui.sensor.MySensorListener

import com.example.eventdemo.ui.view.MyCustomView

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers

import io.reactivex.rxjava3.subjects.PublishSubject

import org.greenrobot.eventbus.EventBus

import org.greenrobot.eventbus.Subscribe

import org.greenrobot.eventbus.ThreadMode

import java.util.*

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

// 广播接收器(动态)

private val netReceiver = object: BroadcastReceiver() {

override fun onReceive(ctx: Context?, intent: Intent?) {

val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

val info = cm.activeNetworkInfo

Toast.makeText(this@MainActivity,

"网络状态:${if(info?.isConnected==true)"已连接" else "未连接"}",

Toast.LENGTH_SHORT).show()

}

}

// 联系人内容观察者

private lateinit var contactObserver: ContentObserver

// RxJava 事件流

private val rxSubject = PublishSubject.create()

// Handler 消息

private val handler = Handler(Looper.getMainLooper()) { msg ->

if(msg.what==1) {

Toast.makeText(this, "收到 Handler 消息", Toast.LENGTH_SHORT).show()

}

true

}

// ActivityResult 注册示例

private val requestReadContacts =

registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->

if(granted) observeContacts() else Toast.makeText(this,"拒绝权限",Toast.LENGTH_SHORT).show()

}

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

// 1. 视图事件监听

binding.btnClick.setOnClickListener {

Toast.makeText(this, "按钮点击", Toast.LENGTH_SHORT).show()

}

binding.btnLong.setOnLongClickListener {

Toast.makeText(this, "按钮长按", Toast.LENGTH_SHORT).show()

true

}

binding.customView.setOnCustomEventListener(object: MyCustomView.OnCustomEventListener {

override fun onCustomEvent(data: String) {

Toast.makeText(this@MainActivity, "接口回调: $data", Toast.LENGTH_SHORT).show()

}

})

binding.customView.onTouchListener = { ev ->

if(ev.action==MotionEvent.ACTION_DOWN){

Toast.makeText(this, "TouchListener: 按下", Toast.LENGTH_SHORT).show()

}

false

}

// 2. 动态广播注册

registerReceiver(netReceiver, IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"))

// 静态广播由 Manifest 注册

// 3. 内容观察者

if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)

!= android.content.pm.PackageManager.PERMISSION_GRANTED) {

requestReadContacts.launch(Manifest.permission.READ_CONTACTS)

} else observeContacts()

// 4. 传感器监听

MySensorListener.start(this){ x,y,z ->

// 加速度更新

}

// 5. RxJava 事件

rxSubject

.observeOn(AndroidSchedulers.mainThread())

.subscribe{ evt ->

Toast.makeText(this, "RxJava 收到: $evt", Toast.LENGTH_SHORT).show()

}

binding.btnRx.setOnClickListener{

rxSubject.onNext("Hello Rx at ${Date()}")

}

// 6. EventBus 注册

EventBus.getDefault().register(this)

binding.btnBus.setOnClickListener{

EventBus.getDefault().post(CustomEvent("Hello EB"))

}

// 7. LiveData 示例(略,见 ViewModel)

// 8. Handler 示例

binding.btnHandler.setOnClickListener{

handler.sendEmptyMessageDelayed(1, 500)

}

}

private fun observeContacts(){

contactObserver = object: ContentObserver(Handler(Looper.getMainLooper())){

override fun onChange(selfChange: Boolean) {

Toast.makeText(this@MainActivity, "联系人变动", Toast.LENGTH_SHORT).show()

}

}

contentResolver.registerContentObserver(

ContactsContract.Contacts.CONTENT_URI,

true, contactObserver)

}

@Subscribe(threadMode = ThreadMode.MAIN)

fun onCustomEvent(evt: CustomEvent){

Toast.makeText(this, "EventBus 收到: ${evt.msg}", Toast.LENGTH_SHORT).show()

}

override fun onDestroy() {

super.onDestroy()

unregisterReceiver(netReceiver)

contentResolver.unregisterContentObserver(contactObserver)

MySensorListener.stop(this)

EventBus.getDefault().unregister(this)

}

}

// ---------------- 文件: ui/view/MyCustomView.kt ----------------

package com.example.eventdemo.ui.view

import android.content.Context

import android.util.AttributeSet

import android.view.View

/**

* MyCustomView:自定义组件示例,接口+Lambda 回调

*/

class MyCustomView @JvmOverloads constructor(

ctx: Context, attrs: AttributeSet? = null

): View(ctx, attrs) {

interface OnCustomEventListener {

fun onCustomEvent(data: String)

}

private var listener: OnCustomEventListener? = null

var onTouchListener: ((android.view.MotionEvent)->Boolean)? = null

fun setOnCustomEventListener(l: OnCustomEventListener){

listener = l

}

// 模拟事件触发

fun doCustom(){

listener?.onCustomEvent("事件数据")

}

}

// ---------------- 文件: ui/sensor/MySensorListener.kt ----------------

package com.example.eventdemo.ui.sensor

import android.content.Context

import android.hardware.*

/**

* MySensorListener:封装加速度传感器监听

*/

object MySensorListener: SensorEventListener {

private var manager: SensorManager? = null

private var listener: ((Float,Float,Float)->Unit)? = null

fun start(ctx: Context, l: (x:Float,y:Float,z:Float)->Unit){

manager = ctx.getSystemService(Context.SENSOR_SERVICE) as SensorManager

val sensor = manager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

listener = l

manager!!.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL)

}

fun stop(ctx: Context){

manager?.unregisterListener(this)

}

override fun onSensorChanged(event: SensorEvent) {

listener?.invoke(event.values[0],event.values[1],event.values[2])

}

override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}

}

// ---------------- 文件: event/CustomEvent.kt ----------------

package com.example.eventdemo.event

data class CustomEvent(val msg:String)

// ---------------- 文件: receiver/PowerReceiver.kt ----------------

package com.example.eventdemo.receiver

import android.content.BroadcastReceiver

import android.content.Context

import android.content.Intent

import android.widget.Toast

/**

* 静态广播示例:关机事件

*/

class PowerReceiver: BroadcastReceiver() {

override fun onReceive(ctx: Context, intent: Intent) {

Toast.makeText(ctx, "检测到关机", Toast.LENGTH_SHORT).show()

}

}

// ---------------- 文件: res/layout/activity_main.xml ----------------

android:layout_width="match_parent"

android:layout_height="match_parent">

android:orientation="vertical"

android:padding="16dp"

android:layout_width="match_parent"

android:layout_height="wrap_content">

🎯 相关推荐

德国世界杯战绩历年排名,德国世界杯战绩历年排名
🎯 义乌365便民中心电话

德国世界杯战绩历年排名,德国世界杯战绩历年排名

📅 06-27 👀 9729
全新「热吻棒」哑光唇膏
🎯 速发国际365的最新网站

全新「热吻棒」哑光唇膏

📅 08-31 👀 2026
《放逐之城》综合攻略
🎯 义乌365便民中心电话

《放逐之城》综合攻略

📅 10-13 👀 2945

🎁 合作伙伴