Android 这是Kotlin';s";“懒惰”吗;?

Android 这是Kotlin';s";“懒惰”吗;?,android,kotlin,Android,Kotlin,我一直在努力追踪这个奇怪的异常现象,相信这是Kotlin的一个bug。每当我在UI中单击前两个按钮中的一个时,最后一个按钮会镜像其背景,就像它也被单击一样 我相信这个bug与我使用的“by lazy”有关,因为如果我修改代码并使用一个函数来分配背景,bug就会消失 我做了。该应用程序很简单,只有3个切换按钮,如下所示: 在这个屏幕截图中,我只点击了按钮#1,注意到按钮#3的背景也根据指定的背景绘制而改变,即使您检查按钮#3,它也会显示为“checked=false” 这是我的片段代码: cla

我一直在努力追踪这个奇怪的异常现象,相信这是Kotlin的一个bug。每当我在UI中单击前两个按钮中的一个时,最后一个按钮会镜像其背景,就像它也被单击一样

我相信这个bug与我使用的“by lazy”有关,因为如果我修改代码并使用一个函数来分配背景,bug就会消失

我做了。该应用程序很简单,只有3个切换按钮,如下所示:

在这个屏幕截图中,我只点击了按钮#1,注意到按钮#3的背景也根据指定的背景绘制而改变,即使您检查按钮#3,它也会显示为“checked=false”

这是我的片段代码:

class FirstFragment : Fragment() {

    private val buttonBackgroundDrawable by lazy {
        context?.let { context ->
            ContextCompat.getDrawable(context, R.drawable.button_background)
        }
    }

    private fun getButtonBackground(): Drawable? {
        return context?.let { context ->
            ContextCompat.getDrawable(context, R.drawable.button_background)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Bugged
        buttonBackgroundDrawable?.let { bgDrawable ->
            toggleButton1.background = bgDrawable
            toggleButton2.background = bgDrawable
            toggleButton3.background = bgDrawable
        }

        // Works
//            toggleButton1.background = getButtonBackground()
//            toggleButton2.background = getButtonBackground()
//            toggleButton3.background = getButtonBackground()

    }
}

以下是背景可绘制代码:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true">
        <shape android:shape="oval">
            <corners android:radius="6dp" />
            <solid android:color="#f00" />
        </shape>
    </item>
    <item>
        <shape android:shape="oval">
            <corners android:radius="6dp" />
            <solid android:color="#aaa" />
            <stroke android:width="3dp" android:color="#fff" />
        </shape>
    </item>
</selector>


如果有人确认这是一个bug,或者向我解释我在代码中做错了什么,我很乐意听到,因为我对这一点完全感到困惑。

这是预期的行为
lazy
只在第一次访问属性时初始化属性一次,因此您正在实例化一个由所有按钮共享的可绘制属性。更改可绘制实例的属性值将影响共享同一可绘制实例的任何内容

至于为什么您的第二个按钮没有改变,这可能只是由于在多个视图上使用StateListDrawable实例而导致的未定义的行为,这是从未打算执行的操作,但显然不会触发任何警告


另一方面,您的
getButtonBackground()
函数每次调用时都会实例化一个不同的可绘制实例,因此每个按钮都会获得自己的不同可绘制实例。

这是预期的行为
lazy
只在第一次访问属性时初始化属性一次,因此您正在实例化一个由所有按钮共享的可绘制属性。更改可绘制实例的属性值将影响共享同一可绘制实例的任何内容

至于为什么您的第二个按钮没有改变,这可能只是由于在多个视图上使用StateListDrawable实例而导致的未定义的行为,这是从未打算执行的操作,但显然不会触发任何警告


另一方面,您的
getButtonBackground()
函数每次调用时都会实例化一个不同的可绘制实例,因此每个按钮都会获得自己的不同可绘制实例。

这不是一个
懒惰的
错误,这是由单个可绘制实例引起的
getButtonBackground()
每次调用它时都会创建新实例。drawable单个实例属性的更改会影响应用到的其他视图。
因此,您需要为所有按钮或xml中的集合创建新的drawable。

这不是一个
惰性
错误,这是由drawable的单个实例引起的
getButtonBackground()
每次调用它时都会创建新实例。drawable单个实例属性的更改会影响应用到的其他视图。 因此,您需要为所有按钮或集合创建新的可绘制xml