【问题标题】:So what is the simplest approach for Caching in Flutter? [closed]那么在 Flutter 中缓存最简单的方法是什么? [关闭]
【发布时间】:2018-11-24 15:31:12
【问题描述】:

该应用程序是一个简单的新闻阅读器,它显示 WordPress 帖子,没有什么花哨的,不使用 BLOC,继承的 Widget,Firebase。 即使用户离线,我也希望它显示缓存的数据(即最新的 10 个帖子)。

所以如果用户离线显示缓存数据;或者不知何故默认数据是缓存数据。

从 WP REST API 获取 firstPost[Id] 如果缓存的 Json 文件包含 Post[id] 则显示缓存的数据; 否则 getPosts();并显示加载指示器。还请更新本地 JSON 文件。

获取 JSON 数据的代码:

// Function to fetch list of posts
 Future<String> getPosts() async {
 var res = await http
    .get(Uri.encodeFull(apiUrl + "posts?_embed&per_page=10"), //TODO make it unlimited
        headers: {"Accept": "application/json"});

setState(() {
  var resBody = json.decode(res.body);

  posts = resBody;
});

return "Success!";
}

未来获取帖子并显示加载指示器:

  body: FutureBuilder<List<String>>(
      future: getPosts(),
      builder: (context, snapshot) {
        if (snapshot.hasError) print(snapshot.error);

        return snapshot.hasData
            ? ListViewPosts(posts: snapshot.data)
            : Center(child: CircularProgressIndicator());
      },
    ),

【问题讨论】:

  • LruMap 可能吗?
  • 我知道你在问题中声明了 NO FIREBASE,但你知道它已经提供了,对吧?您可以获取帖子,将其保存在 firebase 数据库中,然后就可以离线使用了。 (待定)
  • 我制作了this search and found 一些有趣的包。 This one 看起来正是您要找的东西,如果您有大型对象,this one 可能更适合移动环境。

标签: dart flutter


【解决方案1】:

简单的基于时间的缓存不需要太多代码。

这可能会对您有所帮助。它使用ScopedModel,但它可以很容易地成为一个简单的类,尽管如果您希望模型触发 UI 刷新,您必须删除notifyListeners() 调用或用您自己的机制替换它。

class MyModel extends Model{
    Duration _cacheValidDuration;
    DateTime _lastFetchTime;
    List<MyRecord> _allRecords;



    MyModel(){
        _cacheValidDuration = Duration(minutes: 30);
        _lastFetchTime = DateTime.fromMillisecondsSinceEpoch(0);
        _allRecords = [];
    }



    /// Refreshes all records from the API, replacing the ones that are in the cache.
    /// Notifies listeners if notifyListeners is true.
    Future<void> refreshAllRecords(bool notifyListeners) async{
        _allRecords = await MyApi.getAllRecords(); // This makes the actual HTTP request
        _lastFetchTime = DateTime.now();
        if( notifyListeners ) this.notifyListeners();
    }


    /// If the cache time has expired, or forceRefresh is true, records are refreshed from the API before being returned.
    /// Otherwise the cached records are returned.
    Future<List<MyRecord>> getAllRecords({bool forceRefresh = false}) async{
        bool shouldRefreshFromApi = (null == _allRecords || _allRecords.isEmpty || null == _lastFetchTime || _lastFetchTime.isBefore(DateTime.now().subtract(_cacheValidDuration)) || forceRefresh);

        if( shouldRefreshFromApi )
           await refreshAllRecords(false);

        return _allRecords;
    }
}

要从MyModel 获取数据,用户界面只需调用getAllRecords()。这将从内存中获取记录(即从_allRecords)或触发刷新,从而进行HTTP调用并更新记录。缓存数据30分钟后自动过期,如果要强制刷新(比如用户明确点击刷新按钮),可以传递forceRefresh: true

【讨论】:

  • 好人,简单的回答。
【解决方案2】:

在体验了许多缓存解决方案之后,以下是我所学到的按复杂度排序的内容:

1- 使用共享首选项 2-使用蜂巢数据库 3-使用firestore离线服务 4- 使用 sqflite

【讨论】:

  • 1 最复杂还是最简单?
  • 您能否推荐/分享有用的链接以使用共享偏好来实现这一目标。
【解决方案3】:

另一种缓存方式是使用 hive 一个 No-SQL 数据库,它可以更快地检索文档并且易于使用。当用户上线时,只需刷新 hive 中的数据

更多详情请查看:https://github.com/shashiben/Anime-details 了解如何使用 hive 进行缓存

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 2013-06-15
    • 2010-09-05
    相关资源
    最近更新 更多