You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中如何向视图传递信息?是否应遵循Tell-Don't-ask原则?

问题背景与疑问

我正在开发一款矩阵计算器Android应用,计算结果通过密封类ResultState表示:

sealed class ResultState {

    abstract fun showInfo(textView: TextView)

    data class SuccessState(private val matrixEntity: MatrixEntity): ResultState() {
        override fun showInfo(textView: TextView) {
            textView.text = matrixEntity.showMatrix()
        }
    }

    data class ErrorState(private val error: String = "Error"): ResultState() {
        override fun showInfo(textView: TextView) {
            textView.text = error
        }
    }

    object Default: ResultState() {
        override fun showInfo(textView: TextView) {
            textView.text = "Hello"
        }
    }
}

同时MatrixEntity实现了Operators接口:

interface Operators {

    fun sum(matrixEntity: MatrixEntity): MatrixEntity

    fun diff(matrixEntity: MatrixEntity): MatrixEntity

    fun multiply(matrixEntity: MatrixEntity): MatrixEntity

    fun showMatrix(): String
}

data class MatrixEntity(
    private val numbers: List<List<Int>>,
) : Operators {
// sum、diff、multiply方法的实现代码

override fun showMatrix(): String {
        var str = ""
        for (i in 0 until rows) {
            for (j in 0 until columns) {
                str += "${returnNumber(i,j)} "
            }
            str += "\n"
        }
        return str
    }
}

我为保持类字段私有,创建showInfo方法向TextView传递信息,认为符合封装原则。但有Java商业开发经验的朋友指出这种方式打断了数据流,且因字段不可变,建议将字段设为公开直接向视图提供信息。我OOP经验不足,想请教:

  • 在Android中应如何向视图提供信息?
  • 是否应遵循Tell-Don't-ask原则?
解答

1. Android中向视图提供信息的合理方式

Android开发里,数据层和视图层的解耦是核心原则之一,两种思路都有适用场景,但更推荐分层处理:

  • 别让数据类直接持有视图操作逻辑:ResultState里的showInfo方法直接操作TextView,会把数据层和UI层强耦合,后续如果要更换展示方式(比如用Jetpack Compose代替传统TextView),或者在其他地方复用ResultState,都会变得异常麻烦。
  • 数据类只负责提供数据,视图层负责渲染:把ResultState的字段改为公开(或者通过getter暴露),让视图层拿到数据后自行处理渲染逻辑。比如SuccessState公开matrixEntity,视图层调用它的showMatrix()方法获取字符串再设置给TextView。

2. Tell-Don't-ask原则的正确应用

Tell-Don't-ask的核心是“告诉对象做什么,而不是询问对象状态再自己做”,但这一原则要分场景使用:

  • 你的showInfo方法看似符合Tell-Don't-ask,但问题在于它把“渲染UI”这个属于视图层的职责交给了数据类,违背了单一职责原则。数据类的职责是承载和处理业务数据,而非操作UI组件。
  • 正确的做法是:数据类告诉视图层“我有什么数据”,视图层自己决定怎么渲染。比如ResultState作为状态载体,暴露自身的状态数据(成功时的矩阵、错误时的提示文本),视图层拿到这些数据后执行渲染操作——这既没有破坏封装(你依然可以把MatrixEntity的内部numbers字段私有,只通过showMatrix()暴露格式化后的字符串),也遵循了分层职责。

3. 封装与数据流的权衡

  • 封装的核心是隐藏内部实现细节,而非完全禁止暴露数据。MatrixEntity把numbers私有,只通过showMatrix()提供格式化后的结果,这已经是良好的封装。而ResultState作为状态容器,暴露自身的状态数据(比如SuccessState的matrixEntity),并不会破坏封装,因为它暴露的是业务层面的状态,而非内部实现。
  • 所谓“打断数据流”,本质是指showInfo方法把数据流转的逻辑封闭在了数据类内部,视图层无法感知数据变化,也无法灵活处理展示逻辑。让状态类公开数据,能让数据流更清晰:从数据层产生ResultState,传递到视图层,视图层根据状态类型渲染对应UI。

内容的提问来源于stack exchange,提问作者Eldar Orudzhev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 04:40:19