原文地址: https://proandroiddev.com/flutter-lazy-loading-data-from-network-with-caching-b7486de57f11
首先,我不是很熟悉 Flutter,因此在Flutter专家眼中许多地方也许比较幼稚、低效或不够优雅。不论如何, 我们都是从那个阶段开始的,所以让我们从脏脏的地方开始。
让我们开始一个练习, 目标是一个非常典型的任务 : 从网络懒加载一个集合数据并且显示到它们到手机的列表上. 数据可以从后端获取, 有一些微小的限制:
- 假如我们需要展示碰巧在一个’页面’中的 #2 和 #3 , 我们不能发送两次相同的请求.
- 假如我们已经加载了一个特殊的条目, 当他滑出列表之后再次展示 (或者也许这个View已经被RecycleView回收) , 然后短时间内需要再次展示之前的条目, 这时候我不想发送其他的网络请求. 是的, 我们需要一些缓存.
我们必须怎么做呢? 假设有这样一个API, 通过它能够简单的拉取页面数据:
1 | import 'dart:async'; |
它很简洁, 只有一个公开的异步方法. 现在让我们创建能够解析JSON响应填充自己的一个产品类和产品页对象模型:
1 | class Product { |
… 和 …
1 | class Products { |
现在, 我们有必要在页面中刷新数据, 但是我们应用的其他部分需要知道这个吗? 答案肯定是不需要, 我们必须有一个通过索引获取数据的抽象层, 让他来判断是否需要进行网络请求, 或者使用本地可供使用的缓存数据. 我们将这个层叫做Repository; 让我们开始为Repository本身定义接口, 并且我保证我们会更接近一些有趣的东西, 我会定义:
1 | abstract class Repository { |
和 Cache:
1 | abstract class Cache<T> { |
现在, 定义分页和缓存的抽象逻辑. 这很简单 - 每次在App中请求其他分页的产品数据, 我们首先在缓存中查找,如果存在, 我们就使用它. 假如不存在并且我们没有正在向后端发送请求, 我们将请求它并且返回一个 Feture 对象给调用的地方. 然后当这个页面的数据从服务器返回之后, 我们完成所有阻塞的请求并且解析这个页面的数据. 听起来很复杂? 我保证实际其实很简单:
1 |
|
每次我们想展示一个产品的时候, 我们会设法获取它; 可是等等! 我们的 Repository 返回的不是一个 Product, 它是一个 Future 对象, 所以我们应该如何在屏幕上展示它? 或许, 可以在等待服务器响应的时候监听他的流? 这是一个选择, 但是在Flutter上我们有更好的选择, 它叫FutureBuilder, 它为我们提供了所有的细节 :
1 | Widget _buildProductRow(Future<Product> productFuture) { |
加入假数据, 让我们看看:
当然, 这是一个快速简陋的解决方案. 没有任何错误处理. 有些地方能做的更好. 但是, 它至少能够工作, 所有代码能在这儿找到:
https://github.com/chelomin/flute/tree/Medium_v1
感谢阅读, 欢迎任何的反馈和夸奖!