颤振/飞镖中对象池模式的最佳实践是什么?

问题描述

想象一个非常简单的应用程序,它有两个页面PostListPostDetail。在前一个页面上,我们显示一个帖子的列表,在后一个页面上,一个帖子的详细信息。

现在考虑以下场景。我们的用户单击第一个 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。