I want to create an easier way to handle SharedPreferences. The way I want to call it is like this
get preference:
val email = SharedPrefs.userdata.email
val wifiOnly = SharedPrefs.connections.wifiOnly
set preference:
SharedPrefs.userdata.email = "someone@example.com"
SharedPrefs.connections.wifiOnly = true
I'm able to do so like this:
App.instance
returns a Context
object in the following snippet
object SharedPrefs {
val userdata by lazy { UserPreferences() }
val connections by lazy { ConnectionPreferences() }
class UserPreferences {
private val prefs: SharedPreferences = App.instance.getSharedPreferences("userdata", Context.MODE_PRIVATE)
var email: String
get() = prefs.getString("email", null)
set(value) = prefs.edit().putString("email", value).apply()
}
class ConnectionPreferences {
private val prefs: SharedPreferences = App.instance.getSharedPreferences("connections", Context.MODE_PRIVATE)
var wifyOnly: Boolean
get() = prefs.getBoolean("wifiOnly", false)
set(value) = prefs.edit().putBoolean("wifyOnly", value).apply()
}
}
The problem is that this can still be called: SharedPrefs.UserPreferences()
Can I make this constructor private to this file or object only?
You can separate the interface and the implementation class, and make the latter private
to the object:
object SharedPrefs {
val userdata: UserPreferences by lazy { UserPreferencesImpl() }
interface UserPreferences {
var email: String
}
private class UserPreferencesImpl : UserPreferences {
private val prefs: SharedPreferences =
App.instance.getSharedPreferences("userdata", Context.MODE_PRIVATE)
override var email: String
get() = prefs.getString("email", null)
set(value) = prefs.edit().putString("email", value).apply()
}
// ...
}
Alternatively, if you are developing a library or you have a modular architecture, you can make use of the internal
visibility modifier to restrict the visibility to the module:
class UserPreferences internal constructor() { /* ... */ }