gpt4 book ai didi

kotlin - 根据传入的状态类类型构成 UI 操作的层次结构

转载 作者:行者123 更新时间:2023-12-05 05:50:36 24 4
gpt4 key购买 nike

我正在使用一个可组合 View ,它显示不同类型对象的 View 。

@Composable
fun Details(
liveData: LiveData<State>,
onAction: ((Action) -> Unit)? = null
) {
val state = liveData.observeAsState()
when (state.value) {
is AuthorState -> {
AuthorDetails(state, onAction)
}
is BookState -> {
BookDetails(state, onAction)
} else -> {
DefaultState(state, onAction)
}
}
}


sealed class Action<T> {
class Name<T>(val id: T): Action<T>()
}

sealed class AuthorAction {
class Name(val id: Long): Action<Long>()
class Address(val author: AuthorState): AuthorAction()
}

@Composable
fun AuthorDetails(
authorState: AuthorState,
onAction: (AuthorAction) -> Unit
) {
...
onAction(AuthorAction.Address(authorState))
...
}

sealed class BookAction {
class Name(val id: String): Action<String>()
class Location(val book: BookState): BookAction()
}

@Composable
fun BookDetails(
bookState: BookState,
onAction: (BookAction) -> Unit
) {
...
onAction(BookAction.Location(bookState))
...
}

在事件中:

view.bottom_sheet.setContent {
Details(viewModel.details) { action ->
when(action) {
is BookAction -> onBookAction(action)
is AuthorAction -> onAuthorAction(action)
is DefaultAction -> onDefaultAction(action)
}
}
}

我正在尝试定义一个基于传递给可组合项的状态的操作层次结构。

问题是“Details”可组合项需要“Action”类型,而不是 BookAction 或 AuthorAction。我尝试过继承,但通常以大量重复结束。

编辑:使用@broot 回答,从可组合项调用操作时遇到问题:

在“id”模板中添加回来:

sealed interface Action<I>
sealed interface AuthorAction<I> : Action<I>
sealed interface BookAction<I> : Action<I>

class Name<I>(val id: I) : Action<I>, AuthorAction<I>, BookAction<I>
class Address(val author: AuthorState) : AuthorAction<Long>
class Location(val book: BookState) : BookAction<String>

interface State<I, out A : Action>
interface BookState : State<String, BookAction>
interface AuthorState : State<Long, AuthorAction>
interface DefaultState<I> : State<I, Action>

fun <I, A : Action<I> Details(
liveData: LiveData<State<I, A>>,
onAction: ((A) -> Unit)? = null
) {
onAction?.invoke(Name("id"))
}

这样做会给我一个编译错误:

Type mismatch. 
Required: A
Found: Action<I>

我可以更改“详细信息”功能:

fun <I, A : Action> Details(
liveData: LiveData<State<I, A>>,
onAction: ((A: Action<I>) -> Unit)? = null
) {
onAction?.invoke(Name("id"))
}

但是,当我这样做时,客户端调用代码中的操作始终是“Action”,而不是 BookAction 或 AuthorAction。

最佳答案

两个问题在这里解决了。

首先是如何构造 Action ,使它们是密封的,但同时一个 Action 可以属于多个 Action 组。例如,Name Action 是 AuthorActionBookAction 和基础 Action 组的一部分。

我们可以通过用密封接口(interface)替换密封类并从其中的多个继承来做到这一点。例如:

sealed interface Action
sealed interface AuthorAction : Action
sealed interface BookAction : Action

class Name(val id: String) : Action, AuthorAction, BookAction
class Address(val author: AuthorState) : AuthorAction
class Location(val book: BookState) : BookAction

(我特意从 NameAction 中删除了 T 只是为了简化代码并专注于重要的事情。)

第二个问题是如何根据状态对象的类型选择一组合适的 Action 。我们可以通过相关操作参数化状态来做到这一点:

interface State<out A : Action>
interface BookState : State<BookAction>
interface AuthorState : State<AuthorAction>
interface DefaultState : State<Action>

我们还必须参数化 Details() 函数:

fun <A : Action> Details(
liveData: LiveData<State<A>>,
onAction: ((A) -> Unit)? = null
) {
when (val state = liveData.observeAsState().value) {
is AuthorState -> {
onAction?.invoke(Name("foo") as A)
onAction?.invoke(Address(state) as A)

// or:

AuthorDetails(state, onAction as ((AuthorAction) -> Unit)?)
}
...
}
}

然后我们可以这样使用它:

val authorState: LiveData<AuthorState> = TODO()
Details(authorState) { action -> // action is AuthorAction
when (action) { // when is exhaustive
is Name -> TODO()
is Address -> TODO()
}
}

val bookState: LiveData<BookState> = TODO()
Details(bookState) { action -> // action is BookAction
when (action) { // when is exhaustive
is Name -> TODO()
is Location -> TODO()
}
}

关于kotlin - 根据传入的状态类类型构成 UI 操作的层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70498922/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com