P_K*_*ing 3 architecture android kotlin mosby
在演示者创建不可变状态(模型)流和视图的情况下,尝试使用新的体系结构范式进行渲染。
无法理解如何处理只需要一次进行某些事件的情况。有几个例子。
1)Notes应用。我们有editText
和saveButton
。用户单击saveButton
,将进行一些处理,并且应清除editText。你们能描述一下ViewState
这里的内容以及大概的逻辑流程吗?
我现在看到的问题和陷阱:
editText.textChanges()
在主持人中订阅。如果我们text
在ViewState
每个渲染调用中都包含并渲染它,那么我们将陷入递归,因为它将发出新的textChange并更新状态并再次渲染。text
在ViewState
方向文本上还原它或取消/还原进程,看起来好像开箱即用。但是想象一下recyclerView
滚动位置。我们绝对需要保存它才能还原。我们无法在每个渲染调用中恢复它,因为它看起来很奇怪,不是吗?.doOnNext{ view.clearText() }
合理,那么我们在规范的MVI实现中是否有参考意见?Mosby没有它,如我所见。doOnNext
通话时视图消失。MVI应该为此提供帮助,但前提是它是的一部分ViewState
,对吗?2)Github应用。首先屏幕(组织)orgEditText
,okButton
,progressBar
。第二个屏幕(回购): recyclerView
。当用户进入组织orgEditText
并单击okButton
应用程序时,应向API提出请求,并在成功时导航到“回购”屏幕,如果成功,则显示“祝酒”。再次请您描述ViewState
一下组织屏幕,逻辑应该是什么样的?
我现在看到的问题和陷阱:
progressBar
和禁用okButton
。我们应该喜欢加载/内容/错误密封的类(我们称之为ContentState
),并将其实例放在我们的中ViewState
。View知道如何渲染ContentState.loading
并显示progressBar
和禁用okButton
。我对吗?Google提出了SingleLiveEvent
解决方案,但看起来很奇怪,然后应该有尽可能多的信息LiveData<SingleLiveEvent>
流,而不是真正的真理来源。其他人则建议从render func生成新的意图,这种意图更好,但是有些异步操作可能会再次更改状态,因此我们会在第一次显示Toast时得到第二个Toast。
1)Notes App:在一个完美的世界中:是的,text
只要用户插入文本并进行渲染,您的ViewState就会发生变化。关于递归:我可能是错的,但我认为RxBindings某个地方提供了一个Observable,它不仅包含更改的文本,而且如果此更改是由用户输入或通过编程设置文本引起的,则还包含布尔标志。无论如何,我认为如果您检查if (editText.text != viewState.text)
并仅在文本不同的情况下设置文本,也可以解决该递归问题(请记住,您可能必须使用TextWatcher回调,该回调在更改文本以启动意图后触发,而不是“之前将要更改”)。
话虽如此,在Android上,我们并不是生活在一个完美的世界中。正如您已经说过的那样,文本将由android自动恢复。因此,不要将文本作为ViewState的一部分是有意义的。
因此,听起来在这种情况下,ViewState只是这样的一个枚举:
enum ViewState {
// The user can type typing text
IDLING,
// The app is saving the note
PROCESSING,
// After having saved (PROCESSING) the note, CLEARED means, show a new empty note
CLEARED
}
Run Code Online (Sandbox Code Playgroud)
因此初始状态为IDLING
。然后,一旦应保存便笺,则下一个发出的ViewState是PROCESSING
。成功完成后,您的业务逻辑将立即触发,CLEARED
然后立即触发, IDLING
因此最终用户会再次看到一个空注释,并可以开始输入新注释。
不要doOnNext()
用于操纵视图。ViewState是视图的唯一事实来源。
关于RecyclerView:如果没有,RecyclerView会自动恢复其滚动位置(在状态恢复后,您将LayoutManager和/或适配器设置为最新)。但是,如果您想对ViewState中的滚动位置建模,那么在理想情况下,这又是最好的解决方案,您应该考虑不要在每个滚动像素上更新ViewState中的滚动位置,而是一旦用户不再滚动/拖动结束。
2)Github应用:
- 加载时,我们应该显示progressBar并禁用okButton。我们应该喜欢加载/内容/错误密封的类(我们称其为ContentState),并将其实例包含在我们的ViewState中。View知道如何呈现ContentState.loading并显示progressBar并禁用okButton。我对吗?
是
- 那如何处理导航呢?
对我来说,将其作为副作用可以很好地工作:我有一个Navigator
注入到Presenter中并在中使用的类doOnNext { navigator.goToX() }
。然后,导航器将其分派到可以临时连接/分离的另一个组件。因此,此其他组件正在观察“导航事件”的导航器。之所以这样做,是因为该组件不会泄漏活动/片段上下文。“此组件”可以直接是Activity或Fragment或其他任何东西,但是我倾向于拥有一个专用的类,让我们称它为Router
观察Navigator
导航事件并 FragmentTransactions
在应用程序中使用或做任何事情。
- 吐司-状态是否存在,还是我们认为这是副作用?同样的问题。
可以按照与您可以执行的操作类似的方式进行处理Snackbar
(请参阅此处)。Toast没有隐藏Toast的API。因此,您可以立即一个接一个地触发两个ViewState,而不是一个计时器:第一个设置了错误标志的ViewState(然后会导致Toast确实显示在屏幕上),第二个您在其中“清除”该标志。像这样:
Observable.just( ViewState(error = true, ...), new ViewState( error = false, ... )
Run Code Online (Sandbox Code Playgroud)
我希望可以澄清一些事情,但还是一如既往:不要把它们当成一团子。尽一切可能最适合您的应用和用例。别太虔诚,这总是个案决定。