Kotlin:调用函数从 BroadcastReceiver onReceive 更新 UI

Kotlin: Call a function to update UI from BroadcastReceiver onReceive

我是 Kotlin 的新手,它看起来很棒!虽然今天,我一直在尝试做一些在 Java 中非常简单的事情,但我完全卡住了。

我正在使用广播接收器来确定设备何时连接/断开电源。我需要做的就是相应地更新我的 UI。


我的代码

这是我的 BroadcastReceiver class,它似乎工作正常。

class PlugInReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val action = intent.action

        if (action == Intent.ACTION_POWER_CONNECTED) {
            // Do stuff when power connected
        } 
        else if (action == Intent.ACTION_POWER_DISCONNECTED) {
            // Do more stuff when power disconnected
        }
    }
}

现在在我的 MainActivity 中(但在其他地方,稍后),我想在触发意图时更新我的​​ UI,例如在下面的函数中,背景颜色发生变化。

private fun updateBackgroundColor( newBgColorId: Int = R.color.colorAccent){
    val mainLayout = findViewById<View>(R.id.mainLayout)
    val colorFade = ObjectAnimator.ofObject(
            mainLayout, "backgroundColor", ArgbEvaluator(), oldBgColor, newBgColor)
    colorFade.start()
}

问题

How can I call a function on the MainActivity, or update my UI when the BroadcastReceiver fires an event?


到目前为止我尝试了什么

令人沮丧的是,我在 SO 上发现了几个非常相似的问题。然而,他们的实现似乎都使用了 Java 特定的功能:


我敢肯定这对大多数 Android 开发人员来说是一个微不足道的问题,但我迷路了!如果您需要更多详细信息,请告诉我。非常感谢!

onReceive(...) 方法在主线程上运行。您可以在 onStart() 中注册您的 Activity 并在 onStop() 中注销它,这将保证您的 UI 在收到事件时存在。

共享信息以在 Kotlin 中注册 BroadcastReceiver

第 1 步。在 MainActivity.kt

中创建 BroadcastReceiver
private val mPlugInReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        when (intent?.action) {
            Intent.ACTION_POWER_CONNECTED -> {
                //update your main background color
                updateBackgroundColor()
            }
            Intent.ACTION_POWER_DISCONNECTED -> {
                //update your main background color
                updateBackgroundColor()
            }
        }
    }
}

步骤 2. 创建 IntentFilter

private fun getIntentFilter(): IntentFilter {
    val iFilter = IntentFilter()
    iFilter.addAction(Intent.ACTION_POWER_CONNECTED)
    iFilter.addAction(Intent.ACTION_POWER_DISCONNECTED)
    return iFilter
}

步骤 3. 在 onStart() 注册接收器

override fun onStart() {
    super.onStart()
    registerReceiver(mPlugInReceiver, getIntentFilter())
}

第 4 步。在 onStop() 取消注册接收器

override fun onStop() {
    super.onStop()
    unregisterReceiver(mPlugInReceiver)
}

如果您有自定义 BroadcastReceiver,您可以使用 LocalBroadcastManager 注册并创建您的本地 IntentFilter

private val mLocalBroadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        when (intent?.action) {
            AnyService.UPDATE_ANY -> {

            }
        }
    }
}

private fun getLocalIntentFilter(): IntentFilter {
    val iFilter = IntentFilter()
    iFilter.addAction(AnyService.UPDATE_ANY)
    return iFilter
}

注册本地接收器 LocalBroadcastManager.getInstance(applicationContext).registerReceiver(mLocalBroadcastReceiver, getLocalIntentFilter())

注销本地接收器LocalBroadcastManager.getInstance(applicationContext).unregisterReceiver(mLocalBroadcastReceiver)

最好的实现方法是在 BroadcastReceiver 中创建一个抽象方法,当调用 onReceive() 方法时,您可以调用将由您的 activity 实现的方法。

BroadcastReceiver 示例:

abstract class ConnectionBroadcastReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
     //Do the checks or whatever you want
     var isConnected = true

    broadcastResult(isConnected)
}

protected abstract fun broadcastResult(connected: Boolean)

}

以及您 activity 中的代码(例如在 onCreate 或 onStart 中)。在这里您使用方法实现注册广播接收器,在这里您可以更新 UI:

    var connectionBroadcastReceiver = object : ConnectionBroadcastReceiver() {
        override fun broadcastResult(connected: Boolean) {
            if(isConnected){
                refreshList()
            }
        }
    }
    val intentFilter = IntentFilter()
    intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
    this.registerReceiver(connectionBroadcastReceiver, intentFilter)

不要忘记在 (onPause||onStop||onDestroy) 中注销接收器,但这不是绝对必要的。