当参数更改时更新UI的最简单方法?

发布于 2025-02-04 17:46:21 字数 2446 浏览 2 评论 0原文

下面的代码对我有用,但我必须单击以查看luvText字符串的最新值。

    class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var cameraExecutor: ExecutorService
    private var imageCapture: ImageCapture? = null
    var luvText = "Luv values"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //val dataBinding: PlainActivityBinding =
        //    DataBindingUtil.setContentView(this, binding.colourValueText)
        //dataBinding.setLifecycleOwner(this)

        // Request camera permissions
        if (allPermissionsGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(
                this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }

        binding.viewFinder.setOnClickListener { binding.colourValueText.text = luvText }
        cameraExecutor = Executors.newSingleThreadExecutor()
    }

我看过很多示例,并试图复制他们的工作,但到目前为止没有成功。

两种绑定如何重叠?我正在为UI使用ViewBinding,但是大多数示例都使用FindViewById()开始。对于我的实验,我需要在build.gradle中要求两个...

    buildFeatures {
        viewBinding true
        dataBinding true
    }

我已经将Activity_main.xml转换为布局。对于可能跟随的其他人,如果您右键单击标头后的第一行,选择“显示上下文动作”,然后选择布局选项,Android Studio将为您执行此操作。这些例子很少提到这一点。

有必要吗?一个消息来源使用mutableLivedata,不需要它...

https://developer.android.android。 com/topic/库/架构/livedata

这建议mutableLivedata在viewModel()实例中。这有必要吗?

我的代码包含一些评论的视图,以供早期尝试。似乎有很多不同和不兼容的方法来做几乎相同的事情。因此,让我问一下这个漫不经心的问题...

当相机Executor更改一个字符串变量时,最简单的(最少的行)将我的一个文本视图更新?

不同的工具相当吗?还是有明显的“最新和最大”选择?

PS:

luvText字符串是这样设置的...

            val imageAnalyzer = ImageAnalysis.Builder()
                .build()
                .also {
                    it.setAnalyzer(cameraExecutor, LuvAnalyzer { LUV ->
                        // Log.d(TAG, "Average LUV: %.1f %.1f %.1f".format(LUV[0], LUV[1], LUV[2]))
                        luvText = "Average LUV: %.1f %.1f %.1f".format(LUV[0], LUV[1], LUV[2])
                    })
                }

原始代码(注释)将新值写入日志。我可以设置luvText字符串,但是我不能从这里显示它,因为这是另一个线程。

The code below works for me but I have to click to see the latest value of the luvText string.

    class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var cameraExecutor: ExecutorService
    private var imageCapture: ImageCapture? = null
    var luvText = "Luv values"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //val dataBinding: PlainActivityBinding =
        //    DataBindingUtil.setContentView(this, binding.colourValueText)
        //dataBinding.setLifecycleOwner(this)

        // Request camera permissions
        if (allPermissionsGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(
                this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }

        binding.viewFinder.setOnClickListener { binding.colourValueText.text = luvText }
        cameraExecutor = Executors.newSingleThreadExecutor()
    }

I have looked at many examples, and tried to copy what they do, but so far without success.

How do the two sorts of binding overlap? I was using viewBinding for the UI, but most of the examples start off using findViewById(). For my experiments, I needed to ask for both in build.gradle...

    buildFeatures {
        viewBinding true
        dataBinding true
    }

I have converted activity_main.xml to a layout. For others that may follow, Android Studio will do this for you if you right click on the first line after the header, select 'Show Context Actions', and pick the layout option. The examples rarely mention this.

Is it necessary? One source uses MutableLiveData and does not need it...

https://developer.android.com/topic/libraries/architecture/livedata

This recommends that the MutableLiveData is in a ViewModel() instance. Is this necessary?

My code contains some commented out views for earlier attempts. There seem to be a lot of different and incompatible ways of doing almost the same thing. So, let me tie up this rambling question by asking...

What's the simplest (fewest lines) way of getting my one TextView to update when the one string variable is changed by the cameraExecutor?

Are the different sets of tools equivalent? Or is there an obvious 'latest and greatest' choice?

PS:

The luvText string is set like this...

            val imageAnalyzer = ImageAnalysis.Builder()
                .build()
                .also {
                    it.setAnalyzer(cameraExecutor, LuvAnalyzer { LUV ->
                        // Log.d(TAG, "Average LUV: %.1f %.1f %.1f".format(LUV[0], LUV[1], LUV[2]))
                        luvText = "Average LUV: %.1f %.1f %.1f".format(LUV[0], LUV[1], LUV[2])
                    })
                }

The original code (commented out) wrote the new value to the log. I can set the luvText string, but I cannot cause it to be displayed from here, as this is a different thread.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

樱花落人离去 2025-02-11 17:46:21

这是我发现的最简单的解决方案。不属于解决方案一部分的删除代码被省略号(...)替换为

class MainActivity : AppCompatActivity() {

    var xyzText = MutableLiveData<String>()
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        xyzText.observe(this) {
            binding.colourValueText.text = xyzText.value
        }

    }   
    private fun startCamera() {
        ...
        cameraProviderFuture.addListener(...)
            ...

            val imageAnalyzer = ImageAnalysis.Builder()
                .build()
                .also {
                    it.setAnalyzer(cameraExecutor, RgbAnalyzer { XYZ ->
                        xyzText.postValue("Average XYZ: %.1f %.1f %.1f".format(XYZ[0], XYZ[1], XYZ[2]))
                    })
                }
 
         }
    }

我使用PostValue()设置字符串,因为它是在另一个线程中生成的。这标志着MutableLivedAta已更改,观察者更新UI。

我刚刚检查了一下。在build.gradle中不需要“数据框”线。

textView binding.colourvaluetext.text不需要更改,我没有更改布局。我不能保证这不会泄漏或做其他坏事,但似乎有效。

Here is the simplest solution I have found. Deleted code that is not part of the solution is replaced by an ellipsis (...)

class MainActivity : AppCompatActivity() {

    var xyzText = MutableLiveData<String>()
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        xyzText.observe(this) {
            binding.colourValueText.text = xyzText.value
        }

    }   
    private fun startCamera() {
        ...
        cameraProviderFuture.addListener(...)
            ...

            val imageAnalyzer = ImageAnalysis.Builder()
                .build()
                .also {
                    it.setAnalyzer(cameraExecutor, RgbAnalyzer { XYZ ->
                        xyzText.postValue("Average XYZ: %.1f %.1f %.1f".format(XYZ[0], XYZ[1], XYZ[2]))
                    })
                }
 
         }
    }

I set string using postValue() because it is generated in another thread. This marks the MutableLiveData as having been changed, and the Observer update the UI.

I have just checked this. The 'dataBinding true' line is not needed in build.gradle.

The TextView binding.colourValueText.text did not need changing, and I have not changed the layout. I cannot promise this does not leak or do something else bad, but it seems to work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文