android 如何在修改后得到一个新的不变对象?[已关闭]

b5lpy0ml  于 2023-03-16  发布在  Android
关注(0)|答案(1)|浏览(125)

**已关闭。**此问题正在寻求有关书籍、工具、软件库等的建议。它不符合Stack Overflow guidelines准则。当前不接受答案。

我们不允许问题寻求有关书籍、工具、软件库等的推荐。你可以编辑问题,以便可以使用事实和引用来回答问题。
昨天关门了。
这篇文章是昨天编辑并提交审查的。
Improve this question
假设您有一个巨大的嵌套对象,然后您想修改它的一个属性。

myData.x.y.z = 7;
// or...
myData.a.b.add(9);

这看起来不是什么大问题,但实际的编码并不那么简单。

data class Employee(
  val name: String
)

data class Company(
  val employees: List<Employee>
)

class MyViewModel : ViewModel() {

  // Expose screen UI state
  private val _uiState = MutableStateFlow(Company(emptyList()))
  val uiState: StateFlow<Company> = _uiState.asStateFlow()

  // Handle business logic
  fun addEmployee(employee: Employee) {
    _uiState.update { currentState ->
      currentState.copy(
        employees = buildList {
          addAll(currentState.employees)
          add(employee)
        }
      )
    }
  }
}

在真实的代码中,基于单一真实数据源和单向数据流原则,必须使用不可变数据,这在Kotlin中通过val关键字实现。
这个对象的嵌套层次不是特别深,实现的函数是add,如果要更新List中的元素,代码会比较复杂,copy一个嵌套很深的对象也会造成性能问题。
因此,我希望有一个如下所示的方法doSomeThing,它创建对象的副本,根据需要修改新对象的属性,并返回这个新对象。

fun addEmployee(employee: Employee) {
  _uiState.update { currentState ->
    doSomeThing {
      currentState.employees.add(employee)
    }
  }
}

下面添加了一些示例。

第一次编辑2023-3-14 19:47:42

将“addEmployee()”函数更改为“updateEmployee()”函数。

fun updateEmployee(employee: Employee) {
  _uiState.update { currentState ->
    currentState.copy(
      employees = buildList {
        val index = currentState.employees.indexOfFirst { it.name == employee.name }
        val temp = currentState.employees.toMutableList()
        temp[index] = Employee("jack")
        temp.toList()
      }
    )
  }
}

嵌套对象

data class A(
  val b: B
)

data class B(
  val c: C
)

data class C(
  val d: D
)

data class D(
  val name: String
)

class MyViewModel : ViewModel() {
  fun updateEmployee(employee: Employee) {
    _uiState.update { currentState ->
      currentState.copy(
        b = currentState.b.copy(
          c = currentState.b.c.copy(
            d = currentState.b.c.d.copy(
              name = "John"
            )
          )
        )
      )
    }
  }
}
wydwbb8l

wydwbb8l1#

buildList {
    addAll(currentState.employees)
    add(employee)
}

Kotlin已经可以做到这一点,而无需显式突变:

currentState.employees + employee

还有Kotlin

  • ListMutableListSetMutableSet以及其他集合之间的分隔
  • 批量操作,如mapflatMapreducefolddroptake
  • 可以执行多个批量操作而无需创建大量拷贝的序列

复制深度嵌套的对象也会导致性能问题
不多。当你修补一个字段时,副本的其他字段的值仍然指向相同的对象。

相关问题