Estoy tratando de implementar el siguiente patrón singleton: SingletonClass.getInstance(context).callMethod()
Si bien hay una variedad de tutoriales que explican cómo crear singletons en Kotlin, ninguno aborda el hecho de que mantener un context en un campo estático provocará pérdidas de memoria en Android.
¿Cómo creo el patrón anterior sin crear una pérdida de memoria?
Actualizar:
Aquí está mi implementación de la solución #2 de CommonsWare. Usé Koin.
clase singleton:
class NetworkUtils(val context: Context) { }Clase de aplicación:
class MyApplication : Application() { val appModule = module { single { NetworkUtils(androidContext()) } } override fun onCreate() { super.onCreate() startKoin(this, listOf(appModule)) } }Clase de actividad:
class MainActivity : AppCompatActivity() { val networkUtils : NetworkUtils by inject() }Opción n.º 1: haz que getInstance(Context) llame a applicationContext en el Context proporcionado y mantenlo así. El singleton de la Application se crea cuando su proceso es y vive durante la vida del proceso. Está prefiltrado; no puedes filtrarlo más.
Opción #2: Deshazte de getInstance() y configura algún tipo de inyección de dependencia (Dagger 2, Koin, etc.). Hay recetas para estos marcos DI para que suministren el singleton de la Application a los singletons que crean e inyectan aguas abajo.
Cuando llama a getInstance() por primera vez, el Context que pasa a esta función se guarda para siempre. Por lo tanto, el contexto en otras llamadas a getInstance() no tiene nada que ver allí. Nunca guardo este Context .
Esto es lo que estoy haciendo:
Cree un object en Kotlin e inicialice el objeto con un contexto tan pronto como se inicie la aplicación. En lugar de almacenar el contexto, realizo cualquier operación requerida con ese contexto.
object PreferenceHelper { private var prefs: SharedPreferences? = null fun initWith(context: Context){ if(prefs == null) this.prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE) } fun someAction(){ .... } } y dentro de la clase de Application :
class MyApp: Application(){ override fun onCreate(){ PreferenceHelper.initWith(this) } }y luego en cualquier parte de la aplicación:
PreferenceHelper.someAction() Puede hacer esto si no necesita una referencia al Context cada vez que realiza algo con la clase Singleton.
No almacenaría el contexto en SingletonClass, simplemente pasaría el contexto a cada método de la clase a través de la inyección de dependencia. Algo como:
SingletonClass.callMethod(context)Defina el método "estático" en el objeto complementario así:
companion object { fun callMethod(context: Context) { // do Something } }Luego llámalo desde tu actividad con:
SingletonClass.callMethod(this)Espero que ayude :)