你必须实例化一个Kotlin对象吗



我正在进行一个Android Studio项目,在该项目中我使用一个singleton类来跟踪数据(我已经研究了singleton对象的优缺点,我认为这是我项目的最佳解决方案(。然而,我遇到了一些问题,这些问题似乎指向我的singleton对象,对于这些问题,我在StackOverflow或其他开发者论坛上找不到任何好的解决方案。

  1. 我得到的第一个错误发生在我调用另一个类中的singleton对象的地方

注意:在使用它之前,我不会实例化这个singleton类,因为如果我正确理解Kotlin singleton,你就不必这么做了。

for (item in items) {
with(item.device) {
if (name == "BLE_DEVICE") {
count++
Data.addresses.add(address) >>> This is where I call the singleton object <<<
}
}
}
  1. 我得到的第二个错误来自于在singleton类中初始化SharedPreferences
var sharedPref: SharedPreferences? = MainActivity().getSharedPreferences("MySharedPreferencesFile", Context.MODE_PRIVATE)
  1. 我得到的第三个错误来自于从我的singleton对象调用这个函数
fun saveSharedPreferences() {
for ((key, value) in names) {
if (sharedPref != null) {
if (!sharedPref?.contains(key)!!) {
sharedPref
?.edit()
?.putString(key, value)
?.apply()
}
}
}
}

参考:

a。以下是我的堆栈跟踪中的重要行。。。

2022-08-30 16:07:05.422 9946-9946/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.punchthrough.blestarterappandroid, PID: 9946
>>> java.lang.ExceptionInInitializerError
>>> at com.punchthrough.blestarterappandroid.ScanResultAdapter.getItemCount(ScanResultAdapter.kt:62)
...
...
>>> Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.SharedPreferences android.content.Context.getSharedPreferences(java.lang.String, int)' on a null object reference
>>> at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:174)
>>> at com.punchthrough.blestarterappandroid.Data.<clinit>(Data.kt:35)
at com.punchthrough.blestarterappandroid.ScanResultAdapter.getItemCount(ScanResultAdapter.kt:62) 

b。这是我的singleton类,用于跟踪数据。

object Data {
// Format: <Device Address, Name>
// Used for keeping a record of all the devices, keeping
//  duplicate advertisements off the screen, and saving the
//  user-inputted names to the MAC address
var names: MutableMap<String, String> = mutableMapOf()
// Format: <Device Address>
// Used for keeping a count of how many views should be populated
//  in the RecyclerView
var addresses = mutableSetOf<String>()
// TODO: Fix this line to resolve an initialization error
var sharedPref: SharedPreferences? = MainActivity().getSharedPreferences("MySharedPreferencesFile", Context.MODE_PRIVATE)
fun saveSharedPreferences() {
for ((key, value) in names) {
if (sharedPref != null) {
if (!sharedPref?.contains(key)!!) {
sharedPref
?.edit()
?.putString(key, value)
?.apply()
}
}
}
}
}

永远不要实例化"活动"。它根本不起作用,也不能用于任何有用的目的。"活动"包含操作系统为您创建"活动"时设置的全部属性。如果你自己实例化它,你会得到一个死对象,里面充满了不应该为null的null属性。

Kotlin的内置singleton(object(不适合依赖于其他内容的singleton,因为它没有可供您调用以初始化依赖关系的构造函数。

在这种情况下,您的单例必须依赖于Context才能使用共享首选项,因此Kotlinobject不合适。

这就是创建需要上下文的单例的方法:

class Data private constructor(val context: Context) {
companion object {
private var instance: Data? = null
fun getInstance(context: Context): Data {
return instance ?: synchronized(this) {
instance ?: Data(context.applicationContext).also { instance = it }
}
}
}
val names: MutableMap<String, String> = mutableMapOf()
val sharedPref: SharedPreferences = context.getSharedPreferences("MySharedPreferencesFile", Context.MODE_PRIVATE)
fun saveSharedPreferences() { // I simplified this function a bit
sharedPref.edit {
for ((key, value) in names) {
if (!sharedPref.contains(key)) {
putString(key, value)
}
}
}
}
}

每次使用它时,都需要向Data.getInstance传递一个Context。

顺便说一句,我强烈反对将var与MutableList或MutableSet结合使用。它会导致错误,因为外部类不知道他们是应该将集合换成新实例,还是在想要进行更改时对其进行适当的更改。其他类无法知道缓存列表副本是否安全,因为它可能会根据其他类正在做的事情从它们下面更改,也可能不会更改。

实际上,我不建议公开任何类的MutableCollection(MutableList或MutableSet(或var只读Collection。当外部类可以更改一个类在内部使用的集合或多个类使用的集合时,它会让您面临许多可能类型的错误。相反,我会将集合设为私有,并公开间接修改它们的函数,如addName()

最新更新