使用Kotlin在Android中使用线程安全的全局资源

时间:2017-11-30 20:07:33

标签: android kotlin

我是Android应用程序的新手,活动生命周期似乎迫使对全局变量的依赖。 (即使使用Dagger,也会有有状态的全局Dagger对象执行依赖注入。)

我想创建一个名为GlobalMode的全局可用模式对象。该模式应该在运行时可以更改。这就是我到目前为止所做的:

interface Mode {
    fun doSomething(a: Int);
}

class NormalMode : Mode {
    override fun doSomething(a: Int) {
        // ...
    }
}

class DebugMode : Mode {
    override fun doSomething(a: Int) {
        // ...
    }
}

object GlobalMode : Mode {

    private var mode: Mode? = null;

    private fun getMode() : Mode {
        if (this.mode == null) {
            this.mode = NormalMode();
        }
        return this.mode!!;
    }

    fun setMode(mode: Mode) {
        this.mode = mode;
    }

    override fun doSomething(a: Int) {
        this.getMode().doSomething(a = a);
    }

}

Kotlin object声明非常适合制作全局对象。它肯定比Java中的单例模式更好。我喜欢如何声明全局对象来实现Mode接口。

我不知道该怎么做才能使以下部分线程安全。如果NormalMode的实例化是昂贵的,那么两个线程可能导致昂贵的实例化,因为null检查中没有同步化。

        if (this.mode == null) {
            this.mode = NormalMode();
        }

我考虑做类似这样的事情,因为显然lazy初始化是线程安全的。

object GlobalMode : Mode {

    private var mode: Mode? = null;

    private val defaultMode: Mode by lazy {
        NormalMode();
    }

    private fun getMode() : Mode {
        if (this.mode == null) {
            this.mode = this.defaultMode;
        }
        return this.mode!!;
    }

    // ...

}

这种lazy方法的问题在于,一旦defaultMode被分配,它就是永久性的。如果在运行时发生某些事情以更改其余应用程序生命周期的模式,defaultMode仍然保留对NormalMode对象的强引用,这意味着对象永远不会被垃圾回收。它永远不会被再次使用,但它永远不会被垃圾收集。

如何以更好的方式使以下部分线程安全?

        if (this.mode == null) {
            this.mode = NormalMode();
        }

感谢。

1 个答案:

答案 0 :(得分:2)

与Java类似,您可以使方法同步:

@Synchronized private fun getMode() : Mode {
    if (this.mode == null) {
        this.mode = this.defaultMode;
    }
    return this.mode!!;
}