android - patron - Clase de aplicación Kotlin Singleton
patron singleton kotlin (4)
Así que en Android quiero hacer de mi clase de aplicación un singleton.
Haciéndolo así:
object MyApplication: Application(){}
no funcionará Siguiendo erros es lanzado en tiempo de ejecución:
java.lang.IllegalAccessException: private com....is not accessible from class android.app.Instrumentation.
Hacer esto tampoco es posible:
class MyApp: Application() {
private val instance_: MyApp
init{
instance_ = this
}
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree());
}
}
companion object{
fun getInstance() = instance_
}
}
Entonces, ¿cómo puedo obtener una instancia de mi clase de aplicación en cualquier parte de mi aplicación? Me gustaría usar MyApp.instance()
lugar de (applicationContext as MyApp)
.
También una explicación de por qué quiero esto: tengo clases en mi aplicación, por ejemplo, un Singleton SharedPreference que se inicializa con un contexto, y como es un singleton, no puede tener argumentos.
No puedes hacer eso porque Android crea una instancia de Application
utilizando su constructor sin parámetros.
El problema que quieres resolver se puede resolver fácilmente con DI. Simplemente cree instancias con un inyector para que el Context
pueda ser inyectado en objetos como una dependencia.
Puede hacer lo mismo que haría en Java, es decir, poner la instancia de la Application
en un campo estático. Kotlin no tiene campos estáticos, pero las propiedades en los objetos son accesibles de forma estática.
class MyApp: Application() {
override fun onCreate() {
super.onCreate()
instance = this
}
companion object {
lateinit var instance: MyApp
private set
}
}
A continuación, puede acceder a la propiedad a través de MyApp.instance
.
Si desea usarlo para acceder a algunas propiedades estáticas que tiene allí: solo tendrá una instancia de su aplicación, así que simplemente use el nombre que le dio a la clase. No te preocupes por no ser un singleton real, puedes usarlo de la misma manera.
Ejemplo:
class MyApp : Application() {
companion object {
const val CONSTANT = 12
lateinit var typeface: Typeface
}
override fun onCreate() {
super.onCreate()
typeface = Typeface.createFromAsset(assets, "fonts/myFont.ttf")
}
}
Luego puedes usar MyApp.CONSTANT
y MyApp.typeface
en cualquier lugar de tu aplicación.
-
Si lo que desea es usarlo como un contexto de aplicación , puede crear una propiedad de extensión para Context:
val Context.myApp: MyApp
get() = applicationContext as MyApp
Luego, puede usar myApp
para obtener el contexto de la aplicación en cualquier lugar donde tenga un contexto.
class AppController : Application() {
init {
instance = this
}
companion object {
private var instance: AppController? = null
fun applicationContext() : AppController {
return instance as AppController
}
}
override fun onCreate() {
super.onCreate()
}
}