不要将Android上下文类放在静态字段中

时间:2018-02-20 14:50:13

标签: android kotlin

我需要访问应用程序的上下文,但这样做会在第三行上显示“不要将Android上下文类放在静态字段中”。试图删除private val但没有它我无法访问copyDatabase函数的上下文。

我需要上下文将assets文件夹中的数据库复制到应用程序的数据文件夹中。

class Database constructor(private val ctx: Context) : ManagedSQLiteOpenHelper(ctx, "dex.db", null, 1) {
    companion object {
        private var instance: Database? = null

        @Synchronized
        fun getInstance(ctx: Context): Database {
            if (instance == null) {
                instance = Database(ctx.applicationContext)
            }
            return instance!!
        }
    }    

    private fun copyDatabase() {
        val input = ctx.assets.open("databases/dex.db")
        FileOutputStream(ctx.getDatabasePath("dex.db").path).use { out ->
            input.copyTo(out)
        }
    }
}

由于

2 个答案:

答案 0 :(得分:1)

public class Answer { static class OlimpicSportEvent { //private other field //private other field private final Sport sport; private final Event event; private final Phase phase; OlimpicSportEvent(Sport sport, Event event, Phase phase) throws Exception{ this.sport = sport; this.event = event; this.phase = phase; if(!this.validate()){ throw new Exception(); } } public Sport getSport() { return sport; } public Event getEvent() { return event; } public Phase getPhase() { return phase; } private boolean validate(){ return this.sport.getEvents().contains(this.event); } } public static void main(String[] args) { try { OlimpicSportEvent olSpEv = new OlimpicSportEvent( Sport.ATHLETIC, Event.SPRINT_100_M, Phase.SEMIFINAL); System.out.println("olSpEv created!"); // do whatever you want } catch (Exception ex) { System.out.println("olSpEv invalid!"); // handle ex } } } 保留在Context变量中会阻止垃圾收集器释放内存并导致内存泄漏。您应该将static传递给构造函数并初始化其中的所有内容,而不应将其保留在变量中。

答案 1 :(得分:0)

通过使用companion object,其生命周期等于加载的Database类的生存期,您创建了在数据库实例中捕获的Context与数据库实例之间的生命周期不匹配本身。

当您的应用程序被置于后台并恢复时,或者您只是旋转设备时,上下文(通常是Activity实例)将被销毁而不会破坏整个应用程序,因此数据库实例将继续存在处置背景。这将可靠地导致应用程序失败。

尽管可能小心使用Application上下文,而这很可能与生命周期相匹配,但保留上下文实例的一般做法是不明智的,因此警告

而是将数据库实例作为主活动类的属性,或者,提交使用依赖注入框架,将其作为一个单独的问题处理。

另外,您当前的代码使用了双重检查延迟初始化习惯用法的破坏变体。如果您需要延迟初始化,在Kotlin中,您应该始终将其保留给by lazy属性委托,而不是自己滚动。