From 4eadc99d155ce8f900288c7a5b711db70a5ba291 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Fri, 27 May 2022 13:21:58 +0600 Subject: [PATCH] alpha stale_time & caching support --- packages/example/lib/main.dart | 12 ++++++++++-- packages/fl_query/lib/query.dart | 20 ++++++++++++++++++-- packages/fl_query/lib/query_builder.dart | 13 ++++++++----- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/packages/example/lib/main.dart b/packages/example/lib/main.dart index b9d091e..3d0d5dc 100644 --- a/packages/example/lib/main.dart +++ b/packages/example/lib/main.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:fl_query/query_bowl.dart'; import 'package:fl_query/query_builder.dart'; import 'package:flutter/material.dart'; @@ -22,9 +24,14 @@ class MyApp extends StatelessWidget { } } -class MyHomePage extends StatelessWidget { +class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( @@ -35,7 +42,8 @@ class MyHomePage extends StatelessWidget { children: [ QueryBuilder( queryKey: "greetings", - task: (queryKey) => Future.value("Welcome ($queryKey)"), + task: (queryKey) => Future.value( + "Welcome ($queryKey) ${Random.secure().nextInt(100)}"), builder: (context, query) { if (query.isLoading) return const CircularProgressIndicator(); return Row( diff --git a/packages/fl_query/lib/query.dart b/packages/fl_query/lib/query.dart index 4db715e..2ab44df 100644 --- a/packages/fl_query/lib/query.dart +++ b/packages/fl_query/lib/query.dart @@ -21,13 +21,14 @@ class Query extends ChangeNotifier { QueryTaskFunction task; final int retries; final Duration retryDelay; + final Duration _staleTime; // all properties T? data; dynamic error; QueryStatus status; int retryAttempts = 0; - late DateTime updatedAt; + DateTime updatedAt; int refetchCount = 0; @protected @@ -39,15 +40,18 @@ class Query extends ChangeNotifier { Query({ required this.queryKey, required this.task, + required Duration staleTime, this.retries = 3, this.retryDelay = const Duration(milliseconds: 200), T? initialData, QueryListener? onData, QueryListener? onError, }) : status = QueryStatus.pending, + _staleTime = staleTime, data = initialData, _onData = onData, - _onError = onError; + _onError = onError, + updatedAt = DateTime.now(); // all getters & setters bool get hasData => data != null && error == null; @@ -60,6 +64,9 @@ class Query extends ChangeNotifier { bool get isSucceeded => status == QueryStatus.succeed && data != null; // all methods + + /// Calls the task function & doesn't check if there's already + /// cached data available Future _execute({bool isFetch = true}) async { try { retryAttempts = 0; @@ -95,6 +102,9 @@ class Query extends ChangeNotifier { } Future fetch() async { + if (!_isStaleData() && hasData) { + return data; + } return _execute().then((_) { fetched = true; return data; @@ -105,4 +115,10 @@ class Query extends ChangeNotifier { refetchCount++; return _execute(isFetch: false).then((_) => data); } + + bool _isStaleData() { + // when current DateTime is after [update_at + stale_time] it means + // the data has become stale + return DateTime.now().isAfter(updatedAt.add(_staleTime)); + } } diff --git a/packages/fl_query/lib/query_builder.dart b/packages/fl_query/lib/query_builder.dart index 07565da..883c8a8 100644 --- a/packages/fl_query/lib/query_builder.dart +++ b/packages/fl_query/lib/query_builder.dart @@ -18,19 +18,22 @@ class QueryBuilder extends StatefulWidget { } class _QueryBuilderState extends State> { - late Query query; @override void initState() { super.initState(); - query = Query(queryKey: widget.queryKey, task: widget.task); WidgetsBinding.instance.addPostFrameCallback((_) async { - await QueryBowl.of(context).fetchQuery(query); + await QueryBowl.of(context).fetchQuery(Query( + queryKey: widget.queryKey, + task: widget.task, + staleTime: QueryBowl.of(context).staleTime, + )); }); } @override Widget build(BuildContext context) { - final queryRT = QueryBowl.of(context).getQuery(widget.queryKey) ?? query; - return widget.builder(context, queryRT); + final query = QueryBowl.of(context).getQuery(widget.queryKey); + if (query == null) return Container(); + return widget.builder(context, query); } }