{"action":"created","comment":{"url":"https://api.github.com/repos/xitu/gold-miner/pulls/comments/176388744","pull_request_review_id":106070601,"id":176388744,"diff_hunk":"@@ -2,22 +2,23 @@\n > * 原文作者：[Hannes Dorfmann](http://hannesdorfmann.com/)\n > * 译文出自：[掘金翻译计划](https://github.com/xitu/gold-miner)\n > * 本文永久链接：[https://github.com/xitu/gold-miner/blob/master/TODO/mosby3-mvi-6.md](https://github.com/xitu/gold-miner/blob/master/TODO/mosby3-mvi-6.md)\n-> * 译者：\n-> * 校对者：\n+> * 译者：[pcdack](https://github.com/pcdack)\n+> * 校对者：[hanliuxin5](https://github.com/hanliuxin5)\n \n-# REACTIVE APPS WITH MODEL-VIEW-INTENT - PART6 - RESTORING STATE\n+# 使用 MVI 编写响应式 APP—第六部分—状态恢复\n \n-In the previous blog posts we have discussed Model-View-Intent (MVI) and the importance of unidirectional data flow. That simplifies state restoration a lot. How and why? We will discuss that in this blog post.\n+在前面博客中，我们讨论了 Model-View-Intent （MVI）和单项数据流的重要性。这极大的简化了状态恢复。这如何做到和为什么能够做到咧？我们将在这篇博客讨论。\n \n-There are two scenarios we will focus on in this blog post: Restoring state “in memory” (for example during screen orientation change) and restoring a “persistent state” (for example from Bundle previously saved in Activity.onSaveInstanceState()).\n+我们在这篇博客中将要关注两种场景: 在内存中恢复状态（例如屏幕的方向发生改变）和恢复一个“持续状态”（从先前存储在 Activity.onSaveInstanceState() 的 Bundle 中恢复）。\n \n-## In Memory\n+## 在内存中\n \n-That is the simple case. We just have to keep our RxJava stream that emits new state over time out of android components lifecylce (i.e. Activity, Fragment or even ViewGroups). For example Mosby’s **MviBasePresenter** establishes such a RxJava stream internally by using **PublishSubject** for View intents and **BehaviorSubject** to render the state on the view. I have already described these implementation details at the end of [Part 2](http://hannesdorfmann.com/android/mosby3-mvi-2). The main idea is that MviBasePresenter is such a component that lives outside View’s lifecylce so that a view can be attached and detached to such a Presenter. In Mosby the Presenter gets “destroyed” (garbage collected) when the view is destroyed permanently. Again, this is just an implementation detail of Mosby. Your MVI implementation might be entirely different. The important bit is that such a component like a Presenter lives outside of View’s lifecycle because then it’s easy to deal with View attached and detached events: whenever the View gets (re)attached to the Presenter we simply call **view.render(previousState)** (therefore Mosby uses BehaviorSubject internally). This is just one solution of how to deal with screen orientation changes. It also works with back stack navigation, i.e. Fragments on the back stack: if we come back from back stack we simply call view.render(previousState) again and the view is displaying the correct state. Actually, state can still be updated even if no view is attached because Presenter lives outside of that lifecycle and keeps RxJava state stream alive. Imagine receiving a push notification that changes data (part of state) while no view is attached. Again, whenever view gets reattached the latest state (containing updated data from push notification) is hand over to the view to render.\n+这是一个简单的情况。我们只需要让我们的 RxJava 随着时间的变化遵从安卓组件的生命周期（例如，Acitivity，Fragment 甚至是 ViewGroups）继续发射新的数据。例如，Mosby（作者写的一个库） 的 **MviBasePresenter** 建立在一个 RxJava 流内部通过使用 **PublishSubject** 来管理 view 的意图，和通过 **BehaviorSubject** 去渲染状态到 view 上。我已经在[第二部分](http://hannesdorfmann.com/android/mosby3-mvi-2)结尾处描述这些实现细节。最重要的一点是 MviBasePresenter 是独立与 view 生命周期的一个组件，因此一个 view 可以在 Presenter 中被分离和附着。在 Mosby 中只有当 view 永久销毁 Presenter 才会被“摧毁”（垃圾回收）。这仅仅是 Mosby 的实现细节。你的 MVI 实现可能和这个完全不一样。最重要的是这种组件比如 Presenter 需要独立与 view 的生命周期。因为这样它能够简单的处理 view 的附着和分离事件，无论何时 view 需要重新附着到 Presenter 我们只需简单的调用 **view.render(previousState)** (因此 Mosby 用内部 BehaviorSubject 来处理)。这仅仅是如何解决屏幕方向的一种解决方案。它也可以工作在返回栈导航中，例如，Fragment 在返回栈中，我们如果从返回栈中返回，我们可以简单的再次调用 view.render(previousState) 并且，view 也会显示正确的状态。 事实上，状态就算没有 view 附着也可以被改变。因为 Presenter 的独立于生命周期，并且保持 RxJava 状态流在内存中。想象接收一个改变数据（状态的一部分）的通知，没有 view 附着。无论何时 view 被重新附着，最后的状态（包括从通知中更新的数据）都会交给 view 去渲染。\n \n-## Persistent State\n+## 持久化状态\n \n-That scenario is also much simpler with a unidirectional data flow pattern like MVI. Let’s say we want that state of our View (i.e. Activity) not only survives in memory, but also through process death. Typically in Android one would use **Activity.onSaveInstanceState(Bundle)** to save that state. In contrast to MVP or MVVM where you not necessarily have a Model that represents state (see [Part1](http://hannesdorfmann.com/android/mosby3-mvi-1)) in MVI your View has a **render(state)** method which makes it easy to keep track of the latest state. So the obvious solution is to make state Parcelable and store it into the bundle and then restore it afterwards like this:\n+这种场景在单项数据流模式比如 MVI 的情况下也非常简单。假设，我们想让我们的状态或者我们的 view（例如 Activity）不仅仅在内存中存活，而且还能在进程死亡时被暂存。通常的在 Android 中一个被用来存储状态的是 **Activity.onSaveInstanceState(Bundle bundle)** 这个回调函数。对比 MVP 或者 MVVM 你不使用 Model 来代表状态 (看 [第一部分](http://hannesdorfmann.com/android/mosby3-mvi-1)) 在 MVI 你的 view 有一个 render（state）","path":"TODO/mosby3-mvi-6.md","position":28,"original_position":28,"commit_id":"61b1a4ddfb122864afb97ce30906cb159b52ddbf","original_commit_id":"61b1a4ddfb122864afb97ce30906cb159b52ddbf","user":{"login":"allenlongbaobao","id":3255868,"avatar_url":"https://avatars3.githubusercontent.com/u/3255868?v=4","gravatar_id":"","url":"https://api.github.com/users/allenlongbaobao","html_url":"https://github.com/allenlongbaobao","followers_url":"https://api.github.com/users/allenlongbaobao/followers","following_url":"https://api.github.com/users/allenlongbaobao/following{/other_user}","gists_url":"https://api.github.com/users/allenlongbaobao/gists{/gist_id}","starred_url":"https://api.github.com/users/allenlongbaobao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/allenlongbaobao/subscriptions","organizations_url":"https://api.github.com/users/allenlongbaobao/orgs","repos_url":"https://api.github.com/users/allenlongbaobao/repos","events_url":"https://api.github.com/users/allenlongbaobao/events{/privacy}","received_events_url":"https://api.github.com/users/allenlongbaobao/received_events","type":"User","site_admin":false},"body":"这一段翻译得比较生硬。因此我整段重新翻译了一下：\r\n这种场景在 MVI 这种单向数据流模式下也很简单。假设我们希望 View 的状态 （比如 Activity）不仅存活在内存中，还能在进程死亡后被暂存。通常，在安卓中我们使用 **Activity.onSaveInstanceState(Bundle)** 来保存那样的状态。在 MVP 或者 MVVM 中，你不需要使用 Model 来代表状态 (见 [第一部分](http://hannesdorfmann.com/android/mosby3-mvi-1)) ，与之不同的是， 在 MVI 中，View 有一个 **render(state)** 方法来记录最新的状态","created_at":"2018-03-22T11:37:43Z","updated_at":"2018-03-22T11:55:52Z","html_url":"https://github.com/xitu/gold-miner/pull/3487#discussion_r176388744","pull_request_url":"https://api.github.com/repos/xitu/gold-miner/pulls/3487","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/xitu/gold-miner/pulls/comments/176388744"},"html":{"href":"https://github.com/xitu/gold-miner/pull/3487#discussion_r176388744"},"pull_request":{"href":"https://api.github.com/repos/xitu/gold-miner/pulls/3487"}}},"pull_request":{"url":"https://api.github.com/repos/xitu/gold-miner/pulls/3487","id":176208789,"html_url":"https://github.com/xitu/gold-miner/pull/3487","diff_url":"https://github.com/xitu/gold-miner/pull/3487.diff","patch_url":"https://github.com/xitu/gold-miner/pull/3487.patch","issue_url":"https://api.github.com/repos/xitu/gold-miner/issues/3487","number":3487,"state":"open","locked":false,"title":"使用 MVI 编写响应式 APP—第六部分—状态恢复","user":{"login":"pcdack","id":28782180,"avatar_url":"https://avatars3.githubusercontent.com/u/28782180?v=4","gravatar_id":"","url":"https://api.github.com/users/pcdack","html_url":"https://github.com/pcdack","followers_url":"https://api.github.com/users/pcdack/followers","following_url":"https://api.github.com/users/pcdack/following{/other_user}","gists_url":"https://api.github.com/users/pcdack/gists{/gist_id}","starred_url":"https://api.github.com/users/pcdack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pcdack/subscriptions","organizations_url":"https://api.github.com/users/pcdack/orgs","repos_url":"https://api.github.com/users/pcdack/repos","events_url":"https://api.github.com/users/pcdack/events{/privacy}","received_events_url":"https://api.github.com/users/pcdack/received_events","type":"User","site_admin":false},"body":"译文翻译完成，resolve #3468 \r\n","created_at":"2018-03-20T14:29:20Z","updated_at":"2018-03-22T11:55:52Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2ac0fffcc80621568672068ffc4cced452e6f4b4","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":514335558,"url":"https://api.github.com/repos/xitu/gold-miner/labels/Android","name":"Android","color":"1d76db","default":false},{"id":322084033,"url":"https://api.github.com/repos/xitu/gold-miner/labels/%E6%AD%A3%E5%9C%A8%E6%A0%A1%E5%AF%B9","name":"正在校对","color":"c2e0c6","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/xitu/gold-miner/pulls/3487/commits","review_comments_url":"https://api.github.com/repos/xitu/gold-miner/pulls/3487/comments","review_comment_url":"https://api.github.com/repos/xitu/gold-miner/pulls/comments{/number}","comments_url":"https://api.github.com/repos/xitu/gold-miner/issues/3487/comments","statuses_url":"https://api.github.com/repos/xitu/gold-miner/statuses/61b1a4ddfb122864afb97ce30906cb159b52ddbf","head":{"label":"pcdack:translation/mosby3-mvi6","ref":"translation/mosby3-mvi6","sha":"61b1a4ddfb122864afb97ce30906cb159b52ddbf","user":{"login":"pcdack","id":28782180,"avatar_url":"https://avatars3.githubusercontent.com/u/28782180?v=4","gravatar_id":"","url":"https://api.github.com/users/pcdack","html_url":"https://github.com/pcdack","followers_url":"https://api.github.com/users/pcdack/followers","following_url":"https://api.github.com/users/pcdack/following{/other_user}","gists_url":"https://api.github.com/users/pcdack/gists{/gist_id}","starred_url":"https://api.github.com/users/pcdack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pcdack/subscriptions","organizations_url":"https://api.github.com/users/pcdack/orgs","repos_url":"https://api.github.com/users/pcdack/repos","events_url":"https://api.github.com/users/pcdack/events{/privacy}","received_events_url":"https://api.github.com/users/pcdack/received_events","type":"User","site_admin":false},"repo":{"id":120565484,"name":"gold-miner","full_name":"pcdack/gold-miner","owner":{"login":"pcdack","id":28782180,"avatar_url":"https://avatars3.githubusercontent.com/u/28782180?v=4","gravatar_id":"","url":"https://api.github.com/users/pcdack","html_url":"https://github.com/pcdack","followers_url":"https://api.github.com/users/pcdack/followers","following_url":"https://api.github.com/users/pcdack/following{/other_user}","gists_url":"https://api.github.com/users/pcdack/gists{/gist_id}","starred_url":"https://api.github.com/users/pcdack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pcdack/subscriptions","organizations_url":"https://api.github.com/users/pcdack/orgs","repos_url":"https://api.github.com/users/pcdack/repos","events_url":"https://api.github.com/users/pcdack/events{/privacy}","received_events_url":"https://api.github.com/users/pcdack/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pcdack/gold-miner","description":"🥇掘金翻译计划，可能是世界最大最好的英译中技术社区，最懂读者和译者的翻译平台：","fork":true,"url":"https://api.github.com/repos/pcdack/gold-miner","forks_url":"https://api.github.com/repos/pcdack/gold-miner/forks","keys_url":"https://api.github.com/repos/pcdack/gold-miner/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pcdack/gold-miner/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pcdack/gold-miner/teams","hooks_url":"https://api.github.com/repos/pcdack/gold-miner/hooks","issue_events_url":"https://api.github.com/repos/pcdack/gold-miner/issues/events{/number}","events_url":"https://api.github.com/repos/pcdack/gold-miner/events","assignees_url":"https://api.github.com/repos/pcdack/gold-miner/assignees{/user}","branches_url":"https://api.github.com/repos/pcdack/gold-miner/branches{/branch}","tags_url":"https://api.github.com/repos/pcdack/gold-miner/tags","blobs_url":"https://api.github.com/repos/pcdack/gold-miner/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pcdack/gold-miner/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pcdack/gold-miner/git/refs{/sha}","trees_url":"https://api.github.com/repos/pcdack/gold-miner/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pcdack/gold-miner/statuses/{sha}","languages_url":"https://api.github.com/repos/pcdack/gold-miner/languages","stargazers_url":"https://api.github.com/repos/pcdack/gold-miner/stargazers","contributors_url":"https://api.github.com/repos/pcdack/gold-miner/contributors","subscribers_url":"https://api.github.com/repos/pcdack/gold-miner/subscribers","subscription_url":"https://api.github.com/repos/pcdack/gold-miner/subscription","commits_url":"https://api.github.com/repos/pcdack/gold-miner/commits{/sha}","git_commits_url":"https://api.github.com/repos/pcdack/gold-miner/git/commits{/sha}","comments_url":"https://api.github.com/repos/pcdack/gold-miner/comments{/number}","issue_comment_url":"https://api.github.com/repos/pcdack/gold-miner/issues/comments{/number}","contents_url":"https://api.github.com/repos/pcdack/gold-miner/contents/{+path}","compare_url":"https://api.github.com/repos/pcdack/gold-miner/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pcdack/gold-miner/merges","archive_url":"https://api.github.com/repos/pcdack/gold-miner/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pcdack/gold-miner/downloads","issues_url":"https://api.github.com/repos/pcdack/gold-miner/issues{/number}","pulls_url":"https://api.github.com/repos/pcdack/gold-miner/pulls{/number}","milestones_url":"https://api.github.com/repos/pcdack/gold-miner/milestones{/number}","notifications_url":"https://api.github.com/repos/pcdack/gold-miner/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pcdack/gold-miner/labels{/name}","releases_url":"https://api.github.com/repos/pcdack/gold-miner/releases{/id}","deployments_url":"https://api.github.com/repos/pcdack/gold-miner/deployments","created_at":"2018-02-07T05:04:23Z","updated_at":"2018-03-20T08:44:04Z","pushed_at":"2018-03-21T08:18:24Z","git_url":"git://github.com/pcdack/gold-miner.git","ssh_url":"git@github.com:pcdack/gold-miner.git","clone_url":"https://github.com/pcdack/gold-miner.git","svn_url":"https://github.com/pcdack/gold-miner","homepage":"https://juejin.im/tag/掘金翻译计划","size":30979,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"xitu:master","ref":"master","sha":"c3d0a9df2ae1e6f3242208622b0e9094712f740e","user":{"login":"xitu","id":10482599,"avatar_url":"https://avatars2.githubusercontent.com/u/10482599?v=4","gravatar_id":"","url":"https://api.github.com/users/xitu","html_url":"https://github.com/xitu","followers_url":"https://api.github.com/users/xitu/followers","following_url":"https://api.github.com/users/xitu/following{/other_user}","gists_url":"https://api.github.com/users/xitu/gists{/gist_id}","starred_url":"https://api.github.com/users/xitu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xitu/subscriptions","organizations_url":"https://api.github.com/users/xitu/orgs","repos_url":"https://api.github.com/users/xitu/repos","events_url":"https://api.github.com/users/xitu/events{/privacy}","received_events_url":"https://api.github.com/users/xitu/received_events","type":"Organization","site_admin":false},"repo":{"id":45512989,"name":"gold-miner","full_name":"xitu/gold-miner","owner":{"login":"xitu","id":10482599,"avatar_url":"https://avatars2.githubusercontent.com/u/10482599?v=4","gravatar_id":"","url":"https://api.github.com/users/xitu","html_url":"https://github.com/xitu","followers_url":"https://api.github.com/users/xitu/followers","following_url":"https://api.github.com/users/xitu/following{/other_user}","gists_url":"https://api.github.com/users/xitu/gists{/gist_id}","starred_url":"https://api.github.com/users/xitu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xitu/subscriptions","organizations_url":"https://api.github.com/users/xitu/orgs","repos_url":"https://api.github.com/users/xitu/repos","events_url":"https://api.github.com/users/xitu/events{/privacy}","received_events_url":"https://api.github.com/users/xitu/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/xitu/gold-miner","description":"🥇掘金翻译计划，可能是世界最大最好的英译中技术社区，最懂读者和译者的翻译平台：","fork":false,"url":"https://api.github.com/repos/xitu/gold-miner","forks_url":"https://api.github.com/repos/xitu/gold-miner/forks","keys_url":"https://api.github.com/repos/xitu/gold-miner/keys{/key_id}","collaborators_url":"https://api.github.com/repos/xitu/gold-miner/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/xitu/gold-miner/teams","hooks_url":"https://api.github.com/repos/xitu/gold-miner/hooks","issue_events_url":"https://api.github.com/repos/xitu/gold-miner/issues/events{/number}","events_url":"https://api.github.com/repos/xitu/gold-miner/events","assignees_url":"https://api.github.com/repos/xitu/gold-miner/assignees{/user}","branches_url":"https://api.github.com/repos/xitu/gold-miner/branches{/branch}","tags_url":"https://api.github.com/repos/xitu/gold-miner/tags","blobs_url":"https://api.github.com/repos/xitu/gold-miner/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/xitu/gold-miner/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/xitu/gold-miner/git/refs{/sha}","trees_url":"https://api.github.com/repos/xitu/gold-miner/git/trees{/sha}","statuses_url":"https://api.github.com/repos/xitu/gold-miner/statuses/{sha}","languages_url":"https://api.github.com/repos/xitu/gold-miner/languages","stargazers_url":"https://api.github.com/repos/xitu/gold-miner/stargazers","contributors_url":"https://api.github.com/repos/xitu/gold-miner/contributors","subscribers_url":"https://api.github.com/repos/xitu/gold-miner/subscribers","subscription_url":"https://api.github.com/repos/xitu/gold-miner/subscription","commits_url":"https://api.github.com/repos/xitu/gold-miner/commits{/sha}","git_commits_url":"https://api.github.com/repos/xitu/gold-miner/git/commits{/sha}","comments_url":"https://api.github.com/repos/xitu/gold-miner/comments{/number}","issue_comment_url":"https://api.github.com/repos/xitu/gold-miner/issues/comments{/number}","contents_url":"https://api.github.com/repos/xitu/gold-miner/contents/{+path}","compare_url":"https://api.github.com/repos/xitu/gold-miner/compare/{base}...{head}","merges_url":"https://api.github.com/repos/xitu/gold-miner/merges","archive_url":"https://api.github.com/repos/xitu/gold-miner/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/xitu/gold-miner/downloads","issues_url":"https://api.github.com/repos/xitu/gold-miner/issues{/number}","pulls_url":"https://api.github.com/repos/xitu/gold-miner/pulls{/number}","milestones_url":"https://api.github.com/repos/xitu/gold-miner/milestones{/number}","notifications_url":"https://api.github.com/repos/xitu/gold-miner/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/xitu/gold-miner/labels{/name}","releases_url":"https://api.github.com/repos/xitu/gold-miner/releases{/id}","deployments_url":"https://api.github.com/repos/xitu/gold-miner/deployments","created_at":"2015-11-04T03:29:13Z","updated_at":"2018-03-22T11:35:20Z","pushed_at":"2018-03-22T11:35:17Z","git_url":"git://github.com/xitu/gold-miner.git","ssh_url":"git@github.com:xitu/gold-miner.git","clone_url":"https://github.com/xitu/gold-miner.git","svn_url":"https://github.com/xitu/gold-miner","homepage":"https://juejin.im/tag/掘金翻译计划","size":31169,"stargazers_count":12568,"watchers_count":12568,"language":null,"has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2249,"mirror_url":null,"archived":false,"open_issues_count":29,"license":null,"forks":2249,"open_issues":29,"watchers":12568,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/xitu/gold-miner/pulls/3487"},"html":{"href":"https://github.com/xitu/gold-miner/pull/3487"},"issue":{"href":"https://api.github.com/repos/xitu/gold-miner/issues/3487"},"comments":{"href":"https://api.github.com/repos/xitu/gold-miner/issues/3487/comments"},"review_comments":{"href":"https://api.github.com/repos/xitu/gold-miner/pulls/3487/comments"},"review_comment":{"href":"https://api.github.com/repos/xitu/gold-miner/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/xitu/gold-miner/pulls/3487/commits"},"statuses":{"href":"https://api.github.com/repos/xitu/gold-miner/statuses/61b1a4ddfb122864afb97ce30906cb159b52ddbf"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"allenlongbaobao"}}