【问题标题】:Broadcast receiver with activity inheritance具有活动继承的广播接收器
【发布时间】:2022-01-25 08:48:26
【问题描述】:

我有一个问题。我在每个活动中都有 2 个活动,我初始化广播接收器以获取 Internet 连接更改。收到更改后,我会通过在屏幕上显示一些文本来通知用户。

为了不多次写代码,我创建了继承自AppCompatActivity的BroadcastActivity。

现在我将使用 super() 的视图传递给 BroadcastActivity 并使用视图进行操作(更改文本、可见性等)。

问题是:这样做是最佳做法还是有更优雅的解决方案?以及是否会导致内存泄漏?

感谢您的帮助!

BroadcastActivity 示例

open class BroadcastActivity : AppCompatActivity(), OnConnectionChangeListener {
    //some code
}

以及活动示例(二级活动结构类似这样)

public class MainActivity extends BroadcastActivity{
    //some code
}

附: BroadcastActivity 写在 Kotlin 上,MainActivity 写在 Java 上。

附: 2 目前我无法切换到单一活动并寻求临时解决方案。

【问题讨论】:

  • Is it best practice to do so or is there a more elegant solution? 不要使用多个活动。有一个带有片段的活动。您的活动可以处理这些类型的需求,然后每个片段只处理您需要它们做的任何事情,但是您可以使用这种方法更好地共享数据
  • @a_local_nobody 目前我无法切换到单个活动并寻找解决方法。我还修改了问题以添加此说明。谢谢你。
  • 我对监听 Internet 连接变化不太熟悉,但您或许可以将该代码移至 Application 类?
  • @IvoBeckers yip,这也是个好建议
  • 真的是离题了,因为您只需将 BroadcastReceiver 提取到它自己的类中,然后将其与activityLifecycle 挂钩。

标签: java android kotlin inheritance


【解决方案1】:

为了进一步详细说明我的评论,这里有一些“更好”的东西(再次,在我个人看来)......

ActivityKtx.kt:

fun Activity.applyBroadcastReceiver(broadcastReceiver: BroadcastReceiver) {
    lifecycle.addObserver(
        BroadcastReceiverObserver(
            BroadcastReceiverConfigurationImpl(broadcastReceiver, this)
        )
    )
}

BroadcastReceiverObserver.kt:

/**
 * Class implementing [DefaultLifecycleObserver] which is in charge of delegating setting the
 * [BroadcastReceiver]'s registration status.
 * Registers in [Activity.onResume] and unregisters in [Activity.onPause]
 */
class BroadcastReceiverObserver(
    val broadcastReceiverConfig: BroadcastReceiverConfiguration
) : DefaultLifecycleObserver {
    var isBroadcastReceiverRegistered = false

    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        if (isBroadcastReceiverRegistered.not()) {
            broadcastReceiverConfig.registerBroadcastReceiver()
            isBroadcastReceiverRegistered = true
        }

    }

    override fun onStop(owner: LifecycleOwner) {
        if (isBroadcastReceiverRegistered) {
            isBroadcastReceiverRegistered = false
            broadcastReceiverConfig.unregisterBroadcastReceiver()
        }
        super.onStop(owner)
    }

    // add same things for onStart() and onPause()
}

/**
 * Base class for handling a [BroadcastReceiver] registration status
 */
abstract class BroadcastReceiverConfiguration {
    abstract fun registerBroadcastReceiver()
    abstract fun unregisterBroadcastReceiver()
}

/**
 * Base class for handling the broadcast receiver
 *
 * @see [BroadcastReceiverObserver]
 */
class BroadcastReceiverConfigurationImpl constructor(
    private val broadcastReceiver: BroadcastReceiver,
    private val hostActivity: Activity
) : BroadcastReceiverConfiguration() {
    
    override fun registerBroadcastReceiver() {
        //ConnectivityManager.CONNECTIVITY_ACTION - deprecated
        hostActivity.registerReceiver(broadcastReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
    }

    override fun unregisterBroadcastReceiver() {
        hostActivity.unregisterReceiver(broadcastReceiver)
    }
}

然后像这样使用它:

SomeActivity.kt:

class SomeActivity extends AppCompatActivity {
    
    override fun onCreate() {
        super.onCreate()
        applyBroadcastReceiver(myBroadcastReceiver)
    }

瞧。零需要子类化 Activity / AppCompatActivity / MyBaseActivity 或其他。

【讨论】:

  • 感谢您的回答,顺便问一下您认为适合本案的主题名称是什么?
  • @PavelMaltsev none,不是主题名称有问题;这是问题的内容。任何仅围绕“你认为......”或“你建议我使用 A 还是 B”而没有关于为什么考虑 A 和 B 的问题都是题外话,原因与我之前提到的基于意见的原因相同。它从字面上归结为“我应该把我的房子漆成红色还是蓝色?”,喜欢红色的人会选红色,喜欢蓝色的人会选蓝色,不喜欢红色的人会说把它漆成黑色,有些人会说“随便大家否则正在做,把它涂成白色”,答案并不是很有用。
  • 但如果我们真的要重构这个问题,那么更合适的名称应该是“如何应用 BroadcastReceiver 来监听 API 21+ 及以下版本的互联网连接变化?”然后从那里开始工作。显示您尝试过的内容,人们会建议为此使用存储库,您将使用 BroadcastReceiverActivity 更新您的答案,有人出现并将此答案作为答案发布,因未回答问题而被否决,但我的答案适用于 pre -Q(或 P)API。这样一来,你就真的把它伪装成一个 X/Y 问题了。
  • @PavelMaltsev 您真正的问题是“如何在 pre-P 和 post-P API 上监听互联网连接变化”。您将其掩盖为“我如何使用广播接收器优雅地做到这一点,我应该继承 Activity 来做到这一点”。然而,虽然第一个问题的答案与此不同,但第二个问题的答案是 远离您无法控制的事物的继承,并改用组合。一旦事情发生变化,您的代码就会中断并出现意外行为。基于组合的方法没有这个问题。而这个答案使用了组合。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多