问题描述
想象一个非常简单的应用程序,它有两个页面,PostList 和 PostDetail。在前一个页面上,我们显示一个帖子的列表,在后一个页面上,一个帖子的详细信息。
现在考虑以下场景。我们的用户单击第一个 PostItem 并导航到 PostDetail 页面。我们从服务器获取完整的post 数据。此帖子的likes_count增加一。现在,如果我们的用户导航回第一页,PostItem 应该更新并显示新的 likes_count。
一种可能的解决方案是创建一个帖子池。现在,当我们从服务器获取一些新数据时,我们可以更新相应的池实例对象,而不是创建新的 post 对象。例如,如果我们导航到 id=3 的帖子,我们可以这样做:
Post oldPost = PostPool.get(3)
oldPost.updateFromJson(servers_new_json_for_post_3)
由于在 PostDetail 页面上使用了相同的对象,我们在 PostList 页面上的 PostItem 也将更新。
在整个应用程序中不使用 Post 对象的唯一“单个实例”的其他方法实施起来并不干净,并且需要一些技巧来保持 UI 同步。
但是 ObjectPool 方法也有其自身的问题,并且会导致内存泄漏,因为池的大小会随着时间的推移变得越来越大。为了解决这个问题,我们需要手动计算每个池对象实例的引用数量,并在计数为零时丢弃它们。这个手动计算充满了错误,我想知道是否有更好的方法来实现这一点。
解决方法
您也可以使用流和StreamBuilders
来解决这个问题。首先,您创建流并使用从 API 获取的初始数据填充它:
我喜欢使用 BehaviorSubject
中的 rxdart
,但您也可以使用普通流。
final BehaviorSubject<List<Post>> postsStream = BehaviorSubject<List<Post>>()..startWith(<Post>[]);
在构造函数体或 initState
函数中,您将获取数据并将其添加到流中。
PostPage() {
_fetchPosts().then((posts) => postsStream.add(posts));
}
您现在可以在两个页面中使用 postsStream
订阅此 StreamBuilder
上的更改。您需要执行的任何更新都会向流发出一个新的 (updated) List<Post>
,从而触发对使用新值和更新值订阅流的任何 StreamBuilder
的重建。
您可以稍后配置StreamController。