【问题标题】:Why should we 'get a stable reference' in Kotlin/Android?为什么我们要在 Kotlin/Android 中“获得稳定的参考”?
【发布时间】:2020-12-25 06:08:57
【问题描述】:

我正在阅读 Android CameraX 代码实验室:https://codelabs.developers.google.com/codelabs/camerax-getting-started#4

sn-p的简化代码是这样的:

class MainActivity : AppCompatActivity() {
    private var imageCapture: ImageCapture? = null
    
    //(some other codes here...)

    private fun takePhoto() {
        // Get a stable reference of the modifiable image capture use case
        val imageCapture = imageCapture ?: return
        
        //(some other codes here...)

    }
}

在代码实验室中,它说:

首先,获取对 ImageCapture 用例的引用。

为什么我们需要在 takePhoto() 中添加新的引用 imageCapture

我们不能只在MainActivity 中使用imageCapture 吗?

这是为了某种“最佳实践”的东西还是我错过了什么?

任何建议将不胜感激!

【问题讨论】:

  • 如果另一个线程中的一些其他代码在takePhoto 中间修改imageCapture,你认为会发生什么?
  • @Louis Wasserman 我认为这只是一个引用,而不是复制,所以修改后的imageCapture 会在takePhoto 中使用,即使是在原始的codelab 代码中也是如此,不是吗?跨度>
  • 在takePhoto的中间 -- 所以如果takePhoto没有拍快照,这个变量可能会在函数的中间被改掉,这可能会导致混乱。
  • @LouisWasserman 哦,你的意思是,拍摄“参考”的快照(克隆),而不是对象本身?好吧,我明白了。所以当你说“...如果另一个线程中的一些其他代码'修改'imageCapture...”,'修改'意味着分配一个不同的对象,而不是修改原始对象本身。我理解正确吗?因此,如果原始对象本身在不同的线程中被修改(而不是重新分配),那么无论如何都会导致混乱,除非我们深度复制对象本身。如果我理解不正确,请告诉我。感谢您的 cmets!
  • 是的,没错。如果您正确使用不可变对象,那么您只需要该引用副本。

标签: java android kotlin android-camerax


【解决方案1】:

它相当于一个空检查。

stable reference -> Not null reference 

类似

if(imageCapture==null) return;

他们也在代码实验室中提到了同样的事情。

首先,获取对 ImageCapture 用例的引用。如果用例为空,则退出函数。如果您在设置图像捕获之前点击照片按钮,这将为空。如果没有 return 语句,如果它为 null,应用程序将崩溃。

因此,基本上您正在消除可以通过多种方式完成的 NPE 的可能性,并且他们碰巧使用了另一个局部变量。也可以通过let 完成。

imageCapture?.let{
 // code goes here
   }

【讨论】:

  • "...这可以通过多种方式完成,他们碰巧使用了另一个局部变量..." 所以这只是避免的众多方法之一NPE,对吧?非常感谢!现在我明白了。
  • 它不等价,if(imageCapture==null) return; 仍然无济于事,如果变量在中间发生变化,你仍然会发生奇怪的事情,并且编译器不允许非空 . 调用即使在相同的方面进行此检查,该对象也是如此。 ?.let 将做一个浅拷贝,与问题中的 sn-p 相同,它将不受外部更改的影响。
  • 即使中间变量发生变化,浅拷贝也会发生变化。所以这就是为什么它们都是一样的。只有在克隆之后,我们才能确保本地引用不会受到实际引用的影响。
【解决方案2】:
private var imageCapture: ImageCapture? = null

通过这一行,您可以在 imageCapture 变量上分配 null。现在,当您开始使用 takePhoto() 时,编译器如何知道 imageCapture 不再为空?

正如@ADM 所述,您可以使用

imageCapture?.let{
  //your code goes here
}

如果你愿意。这基本上是确保您不会在可为空的对象上调用任何内容。

【讨论】:

    猜你喜欢
    • 2012-07-08
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 2018-02-07
    • 2013-05-28
    • 2022-11-07
    • 2021-11-02
    相关资源
    最近更新 更多