接口引用即使在初始化后仍为空,使我无法在 Internet 连接更改时显示小吃栏

Posted

技术标签:

【中文标题】接口引用即使在初始化后仍为空,使我无法在 Internet 连接更改时显示小吃栏【英文标题】:Interface reference is null even after it got initialized making me unable to show snackbar when internet connection changes 【发布时间】:2019-09-09 10:42:10 【问题描述】:

我正在实现 BroadcastReceiver 以在 Internet 连接更改时显示 Snackbar,因此我创建了一个接口并在 3 个不同的活动中对其进行了初始化,以便在 Internet 连接更改时执行 snapbar 代码

我的问题是第二个和第三个活动中的接口引用为空,但奇怪的是在第一个活动中不为空

我认为问题可能是我对所有三个活动都使用了相同的接口引用(我有点确定这不是问题,但我认为发生了一些我不知道的事情) 所以我创建了 3 个不同的引用,每个活动一个,但这仍然没有解决我的问题

广播接收方代码:

class NetworkChangeReceiver : BroadcastReceiver() 

    private var firstActivityReference: InternetSnackbarInterface? = null
    private var secondActivityReference: InternetSnackbarInterface? = null
    private var thirdActivityReference: InternetSnackbarInterface? = null

    fun registerFirstActivityInterface(snackbarInterface: InternetSnackbarInterface) 
        this.firstActivityReference= snackbarInterface
    

    fun registerSecondActivityInterface(snackbarInterface: InternetSnackbarInterface) 
        this.secondActivityReference= snackbarInterface
    

    fun registerThirdActivityInterface(snackbarInterface: InternetSnackbarInterface) 
        this.thirdActivityReference= snackbarInterface
    

    override fun onReceive(context: Context, intent: Intent?) 

        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val activeNetworkInfo = connectivityManager.activeNetworkInfo
        val isConnected = activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting
        if (isConnected)
            firstActivityReference?.hideNoInternetSnackbar()
            secondActivityReference?.hideNoInternetSnackbar()
            thirdActivityReference?.hideNoInternetSnackbar()

        else
            firstActivityReference?.showNoInternetSnackbar("No internet connection")
            secondActivityReference?.showNoInternetSnackbar("No internet connection")
            thirdActivityReference?.showNoInternetSnackbar("No internet connection")


        
    

    interface InternetSnackbarInterface 
        fun showNoInternetSnackbar(message: String)
        fun hideNoInternetSnackbar()
    


第一个活动相关代码:

class FirstActivity: AppCompatActivity(),NetworkChangeReceiver.InternetSnackbarInterface
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

         val networkChangeReceiver = NetworkChangeReceiver()
         networkChangeReceiver.registerFirstActivityInterface(this)
        val intentFilter = IntentFilter()
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE")
        registerReceiver(networkChangeReceiver,intentFilter)
   

    var internetSnackbar : Snackbar? =null
    private fun showSnackbar(message : String,length : Int)
        val parentLayout = findViewById<View>(android.R.id.content)
        internetSnackbar = Snackbar.make(parentLayout, message, length)
        internetSnackbar?.show()

    

    override fun hideNoInternetSnackbar() 
        internetSnackbar?.dismiss()
    

    override fun showNoInternetSnackbar(message: String) 
        showSnackbar(message, Snackbar.LENGTH_INDEFINITE)
    


第二个活动相关代码:


class SecondActivity: AppCompatActivity(),NetworkChangeReceiver.InternetSnackbarInterface
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

         val networkChangeReceiver = NetworkChangeReceiver()
         networkChangeReceiver.registerSecondActivityInterface(this)
   

    var internetSnackbar : Snackbar? =null
    private fun showSnackbar(message : String,length : Int)
        val parentLayout = findViewById<View>(android.R.id.content)
        internetSnackbar = Snackbar.make(parentLayout, message, length)
        internetSnackbar?.show()

    

    override fun hideNoInternetSnackbar() 
        internetSnackbar?.dismiss()
    

    override fun showNoInternetSnackbar(message: String) 
        showSnackbar(message, Snackbar.LENGTH_INDEFINITE)
    



第三个活动相关代码:

class ThirdActivity: AppCompatActivity(),NetworkChangeReceiver.InternetSnackbarInterface
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

         val networkChangeReceiver = NetworkChangeReceiver()
         networkChangeReceiver.registerThirdActivityInterface(this)
   

    var internetSnackbar : Snackbar? =null
    private fun showSnackbar(message : String,length : Int)
        val parentLayout = findViewById<View>(android.R.id.content)
        internetSnackbar = Snackbar.make(parentLayout, message, length)
        internetSnackbar?.show()

    

    override fun hideNoInternetSnackbar() 
        internetSnackbar?.dismiss()
    

    override fun showNoInternetSnackbar(message: String) 
        showSnackbar(message, Snackbar.LENGTH_INDEFINITE)
    


经过一些调试,我发现:

当 registerSecondActivityReference 被调用时,referene 不为空,但在此之后它再次为空 与第三个ActivityReference 相同 知道我再也不会在我的代码的任何部分将它们分配给 null

奇怪的是,firstActivityReference 从来没有发生过这种情况

对于任何不一致之处,这是我在这里的第一个问题。

【问题讨论】:

【参考方案1】:

改变这个 -- 类 NetworkChangeReceiver : BroadcastReceiver() 到 -- 对象 NetworkChangeReceiver : BroadcastReceiver()

和 改变这个 -- val networkChangeReceiver = NetworkChangeReceiver() 到 -- val networkChangeReceiver = NetworkChangeReceiver

原因:

您正在使用此行在每个活动中创建一个新实例 val networkChangeReceiver = NetworkChangeReceiver()

并使用此代码仅注册第一个活动

val intentFilter = IntentFilter()
    intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE")
    registerReceiver(networkChangeReceiver,intentFilter)

解决方案: 使用对象键盘制作广播接收器单例。

【讨论】:

是的!我怎么会错过这个!,onReceive 函数被注册了 BroadcastReceiver 的对象调用,这总是使其他 2 个引用为 null【参考方案2】:

这是因为您每次注册活动时都会创建一个NetworkChangeReceiver 的新引用,而您注册到连接意图的唯一接收者是第一个。

【讨论】:

以上是关于接口引用即使在初始化后仍为空,使我无法在 Internet 连接更改时显示小吃栏的主要内容,如果未能解决你的问题,请参考以下文章

Django中的JSONField即使在POST请求后仍保持为空

graphql.js:即使解析器正在为 sequilize 查询返回值,该字段仍为空

安装完NetBeans后程序显示为乱码,已更改过conf文件,打开后仍为乱码

Pentaho 数据集成,插入/更新步骤即使在发现一些错误后仍继续

RawFraction 性能计数器即使在删除性能类别后仍保持其状态

JAVA接口详细讲解