接口引用即使在初始化后也为空,这使我无法在互联网连接发生变化时显示小吃店
Interface reference is null even after it got initialized making me unable to show snackbar when internet connection changes
我正在实施 BroadcastReceiver 以在 Internet 连接发生变化时显示 Snackbar,因此我创建了一个界面并在 3 个不同的活动中对其进行了初始化,以便在 Internet 连接发生变化时执行 snackbar 代码
我的问题是,第二个和第三个 activity 中的接口引用为空,但在第一个 activity 中不为空,很奇怪
我认为问题可能是我对所有三个活动使用了相同的接口引用(我有点确定这不是问题,但我认为发生了一些我不知道的事情知道)所以我创建了 3 个不同的引用,每个引用一个 activity 但这仍然没有解决我的问题
广播接收者代码:
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()
}
}
第一个activity相关代码:
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)
}
}
秒activity相关代码:
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)
}
}
第三activity相关代码:
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 不为 null 但紧接着它再次为 null
与 thirdActivityReference 相同
知道我再也不会在我的代码的任何部分将它们分配给 null
奇怪的是,这从来没有发生在 firstActivityReference
对于任何不一致之处,这是我的第一个问题。
这是因为您在每次注册 activity 时都创建了一个新的 NetworkChangeReceiver
引用,并且您注册到 Connectivity Intent 的唯一接收者是第一个。
改变这个
-- class NetworkChangeReceiver : BroadcastReceiver() {
到
-- 对象 NetworkChangeReceiver : BroadcastReceiver() {
和
改变这个
-- val networkChangeReceiver = NetworkChangeReceiver()
到
-- val networkChangeReceiver = NetworkChangeReceiver
原因:
您正在使用此行在每个 activity 中创建一个新实例
val networkChangeReceiver = NetworkChangeReceiver()
并且仅首先 activity 使用此代码
注册
val intentFilter = IntentFilter()
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE")
registerReceiver(networkChangeReceiver,intentFilter)
解决方法:
使用对象键盘使广播接收器成为单例。
我正在实施 BroadcastReceiver 以在 Internet 连接发生变化时显示 Snackbar,因此我创建了一个界面并在 3 个不同的活动中对其进行了初始化,以便在 Internet 连接发生变化时执行 snackbar 代码
我的问题是,第二个和第三个 activity 中的接口引用为空,但在第一个 activity 中不为空,很奇怪
我认为问题可能是我对所有三个活动使用了相同的接口引用(我有点确定这不是问题,但我认为发生了一些我不知道的事情知道)所以我创建了 3 个不同的引用,每个引用一个 activity 但这仍然没有解决我的问题
广播接收者代码:
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()
}
}
第一个activity相关代码:
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)
}
}
秒activity相关代码:
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)
}
}
第三activity相关代码:
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 不为 null 但紧接着它再次为 null 与 thirdActivityReference 相同 知道我再也不会在我的代码的任何部分将它们分配给 null
奇怪的是,这从来没有发生在 firstActivityReference
对于任何不一致之处,这是我的第一个问题。
这是因为您在每次注册 activity 时都创建了一个新的 NetworkChangeReceiver
引用,并且您注册到 Connectivity Intent 的唯一接收者是第一个。
改变这个 -- class NetworkChangeReceiver : BroadcastReceiver() { 到 -- 对象 NetworkChangeReceiver : BroadcastReceiver() {
和 改变这个 -- val networkChangeReceiver = NetworkChangeReceiver() 到 -- val networkChangeReceiver = NetworkChangeReceiver
原因:
您正在使用此行在每个 activity 中创建一个新实例 val networkChangeReceiver = NetworkChangeReceiver()
并且仅首先 activity 使用此代码
注册val intentFilter = IntentFilter()
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE")
registerReceiver(networkChangeReceiver,intentFilter)
解决方法: 使用对象键盘使广播接收器成为单例。