颤振/飞镖中对象池模式的最佳实践是啥?
Posted
技术标签:
【中文标题】颤振/飞镖中对象池模式的最佳实践是啥?【英文标题】:Whats the best practice for object pool pattern in flutter/dart?颤振/飞镖中对象池模式的最佳实践是什么? 【发布时间】:2021-09-27 03:57:33 【问题描述】:想象一个非常简单的应用程序,它有两个页面,PostList 和 PostDetail。在前一页上,我们显示 posts 的列表,在后一页上,显示单个 post 的详细信息。
现在考虑以下情况。我们的用户点击第一个 PostItem 并导航到 PostDetail 页面。我们从服务器获取完整的 post 数据。此 post 的 likes_count 增加 1。现在,如果我们的用户导航回第一页,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 方法也有其自身的问题,并且会导致内存泄漏,因为池的大小会随着时间的推移变得越来越大。为了解决这个问题,我们需要手动计算每个池对象实例的引用数,并在该计数为零时丢弃它们。这种手动计算充满了错误,我想知道是否有更好的方法来实现这一点。
【问题讨论】:
【参考方案1】:您也可以使用 streams 和 StreamBuilders
来解决此问题。首先,您创建 流 并使用从 API 获取的初始数据填充它:
我喜欢使用rxdart
中的BehaviorSubject
,但您也可以使用普通流。
final BehaviorSubject<List<Post>> postsStream = BehaviorSubject<List<Post>>()..startWith(<Post>[]);
在构造函数主体或initState
函数中,您将获取数据并将其添加到流中。
PostPage()
_fetchPosts().then((posts) => postsStream.add(posts));
您现在可以使用StreamBuilder
在两个页面中订阅此postsStream
的更改。您需要执行的任何更新都将向流发送一个新的(更新的)List<Post>
,从而在订阅了具有新值和更新值的流的任何StreamBuilder
上触发重建。
您可以稍后处理 StreamController。
【讨论】:
嗨佩德罗,非常感谢您的详尽回答。是的,我熟悉这个概念,我知道您的方法实际上会导致同步 UI。但我的问题仍然存在。我想在整个应用程序中拥有一个 Post 对象(对于每个 post_id)。当然,还有一种解决上述内存泄漏问题的方法。 嗨@EmadHedayati,很抱歉不能为您提供更多帮助。我不熟悉这个 ObjectPool 模式,但它让我很感兴趣。希望您尽快找到更合适的解决方案并告诉我们。 没问题!您的回答实际上很有用,我从中学到了一些新东西。以上是关于颤振/飞镖中对象池模式的最佳实践是啥?的主要内容,如果未能解决你的问题,请参考以下文章
DAO(数据访问对象)最佳实践 - 我看到的示例同时使用 DAO 和服务对象,这里的最佳实践是啥?