Android与Kotlin中的事件模式

程序员咋不秃头 2024-08-20 01:50:36

事件模式通常指软件设计模式,用于处理和传播应用程序内的事件或通知。这些模式通常用于促进应用程序不同组件之间的通信,例如UI层和业务逻辑层之间的通信。

常见的事件模式

1. 观察者模式(Observer Pattern)

观察者模式是一种行为设计模式,其中一个对象(称为“主题”)维护其依赖者(称为“观察者”)的列表,并在状态变化时通知它们。在 Android 中,这种模式通常与 LiveData 或 RxJava 一起使用,以观察数据的变化并相应地更新 UI 组件。

import androidx.lifecycle.LiveDataimport androidx.lifecycle.MutableLiveDataimport androidx.lifecycle.ViewModelclass DataViewModel : ViewModel() { // 持有数据的 LiveData private val _data = MutableLiveData<String>() val data: LiveData<String> = _data // 模拟从存储库中获取数据的函数 fun fetchData() { // 在实际情况下,从存储库中获取数据 val newData = "New Data from Repository" // 用新数据更新 LiveData _data.value = newData }}import android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport androidx.lifecycle.Observerimport androidx.lifecycle.ViewModelProviderimport kotlinx.android.synthetic.main.activity_main.*class MainActivity : AppCompatActivity() { private lateinit var viewModel: DataViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化 ViewModel viewModel = ViewModelProvider(this).get(DataViewModel::class.java) // 观察 LiveData 的数据变化 viewModel.data.observe(this, Observer { newData -> // 用新数据更新 UI textViewData.text = newData }) // 点击按钮时获取数据 buttonFetchData.setOnClickListener { viewModel.fetchData() } }}

2. 监听器模式(Listener Pattern)

监听器模式涉及定义接口或回调,允许一个组件监听并响应另一个组件触发的事件。例如,在 Android 中,onClickListeners 通常用于处理用户与按钮等 UI 元素的交互。

<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click Me" />import android.os.Bundleimport android.widget.Buttonimport android.widget.Toastimport androidx.appcompat.app.AppCompatActivityclass MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 根据ID找到按钮 val button = findViewById<Button>(R.id.button) // 设置 OnClickListener 以处理按钮点击事件 button.setOnClickListener { // 按钮点击时显示 Toast 消息 Toast.makeText(this, "Button Clicked!", Toast.LENGTH_SHORT).show() } }}

创建一个自定义监听器:

interface OnDataLoadedListener { fun onDataLoaded(data: String)}class DataRepository { fun fetchData(listener: OnDataLoadedListener) { // Simulated data fetching process val data = "Data from Repository" // Notify the listener when data is loaded listener.onDataLoaded(data) }}import android.os.Bundleimport android.widget.TextViewimport androidx.appcompat.app.AppCompatActivityclass MainActivity : AppCompatActivity(), OnDataLoadedListener { private lateinit var repository: DataRepository private lateinit var textViewData: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Initialize views textViewData = findViewById(R.id.textViewData) // Initialize repository repository = DataRepository() // Fetch data from repository repository.fetchData(this) } override fun onDataLoaded(data: String) { // Update UI with loaded data textViewData.text = data }}

发布者-订阅者模式 (Publisher-Subscriber Pattern):

发布者-订阅者模式是观察者模式的扩展,其中发布者发布事件或消息,订阅者接收并处理这些事件。在 Android 中,可以使用 EventBus 库(例如 EventBus 或 Kotlin 的协程通道)来实现此模式。

implementation 'org.greenrobot:eventbus:3.2.0'

使用 EventBus 发布和订阅的自定义事件:

class DataLoadedEvent(val data: String)import org.greenrobot.eventbus.EventBusclass DataPublisher { fun fetchData() { // Simulated data fetching process val data = "Data from Publisher" // Publish the data loaded event EventBus.getDefault().post(DataLoadedEvent(data)) }}

创建订阅事件的订阅者组件:

class DataSubscriber { init { // Register this as an EventBus subscriber EventBus.getDefault().register(this) } @Subscribe fun onDataLoaded(event: DataLoadedEvent) { // Handle data loaded event println("Data loaded: ${event.data}") } // Unregister from EventBus to avoid memory leaks fun unregister() { EventBus.getDefault().unregister(this) }}

Activity中:

class MainActivity : AppCompatActivity() { private lateinit var dataPublisher: DataPublisher private lateinit var dataSubscriber: DataSubscriber override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Initialize publisher and subscriber dataPublisher = DataPublisher() dataSubscriber = DataSubscriber() // Fetch data when activity is created dataPublisher.fetchData() } override fun onDestroy() { super.onDestroy() // Unregister subscriber to avoid memory leaks dataSubscriber.unregister() }}

使用 Kotlin 协程和通道:

class DataViewModel: ViewModel() { private val dataChannel = Channel<String>() fun fetchData() = runBlocking { // Simulate data fetching process val data = "Data from ViewModel" // Send the data through the channel dataChannel.send(data) } fun observeData(): Channel<String> { return dataChannel }}class MainActivity : AppCompatActivity() { private lateinit var viewModel: DataViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewModel = ViewModelProvider(this).get(DataViewModel::class.java) // Observe data changes from the ViewModel GlobalScope.launch(Dispatchers.Main) { viewModel.observeData().receive().let { data -> // Update UI with the received data updateUI(data) } } // Fetch data when activity is created viewModel.fetchData() } private fun updateUI(data: String) { // Update UI with the received data // For example, set text to TextView findViewById<TextView>(R.id.textViewData).text = data }}

命令模式(Command Pattern):

命令模式将请求封装为对象,从而允许使用队列、请求和操作对客户端进行参数化。在Android中,该模式与ViewModel结合使用,将UI相关的操作封装为命令。

创建一个名为Command接口,声明用于执行命令的方法。

interface Command { fun execute()}

创建具体的命令类来实现不同操作的Command接口。

class LightOnCommand(private val light: Light) : Command { override fun execute() { light.turnOn() }}class LightOffCommand(private val light: Light) : Command { override fun execute() { light.turnOff() }}

创建一个执行实际操作的接收器类。在此示例中,创建一个代表灯泡的Light类。

class Light { fun turnOn() { println("Light is turned on") } fun turnOff() { println("Light is turned off") }}

创建一个保存并执行命令的调用程序类。在此示例中,创建一个RemoteControl类。

class RemoteControl { private var command: Command? = null fun setCommand(command: Command) { this.command = command } fun pressButton() { command?.execute() }}

如何使用它:

fun main() { // 创建接收者 val light = Light() // 创建命令 val lightOnCommand = LightOnCommand(light) val lightOffCommand = LightOffCommand(light) // 创建调用者 val remoteControl = RemoteControl() // 设置命令 remoteControl.setCommand(lightOnCommand) // 按下按钮以执行命令 remoteControl.pressButton() // 输出: 灯已打开 // 更改命令 remoteControl.setCommand(lightOffCommand) // 按下按钮以执行新命令 remoteControl.pressButton() // 输出: 灯已关闭}

回调模式(Callback Pattern):

回调模式涉及将函数或闭包(回调)作为参数传递给另一个函数,允许被调用函数在满足某些条件时调用回调。这种模式广泛应用于 Kotlin 和 Android 的异步编程中,例如网络请求回调或数据库操作。

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) fetchDataFromNetwork { result -> // 处理从网络获取的数据结果 println("从网络获取的数据: $result") } } private fun fetchDataFromNetwork(callback: (String) -> Unit) { // 异步模拟网络请求 GlobalScope.launch(Dispatchers.IO) { val data = fetchDataFromServer() // 使用获取到的数据调用回调函数 callback(data) } } private suspend fun fetchDataFromServer(): String { // 模拟从服务器获取数据 kotlinx.coroutines.delay(2000) // 模拟网络延迟 return "来自服务器的数据" }}fun main() { executeTaskAsynchronously { // 处理任务完成后的结果 println("任务成功完成") }}fun executeTaskAsynchronously(callback: () -> Unit) { GlobalScope.launch(Dispatchers.Default) { // 异步模拟任务执行 delay(2000) // 模拟任务执行时间 // 任务完成后调用回调函数 callback() }}
0 阅读:0