alpha stale_time & caching support

This commit is contained in:
Kingkor Roy Tirtho
2022-05-27 13:21:58 +06:00
parent 64c852fddc
commit 4eadc99d15
3 changed files with 36 additions and 9 deletions
+10 -2
View File
@@ -1,3 +1,5 @@
import 'dart:math';
import 'package:fl_query/query_bowl.dart'; import 'package:fl_query/query_bowl.dart';
import 'package:fl_query/query_builder.dart'; import 'package:fl_query/query_builder.dart';
import 'package:flutter/material.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); const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@@ -35,7 +42,8 @@ class MyHomePage extends StatelessWidget {
children: [ children: [
QueryBuilder<String>( QueryBuilder<String>(
queryKey: "greetings", queryKey: "greetings",
task: (queryKey) => Future.value("Welcome ($queryKey)"), task: (queryKey) => Future.value(
"Welcome ($queryKey) ${Random.secure().nextInt(100)}"),
builder: (context, query) { builder: (context, query) {
if (query.isLoading) return const CircularProgressIndicator(); if (query.isLoading) return const CircularProgressIndicator();
return Row( return Row(
+18 -2
View File
@@ -21,13 +21,14 @@ class Query<T> extends ChangeNotifier {
QueryTaskFunction<T> task; QueryTaskFunction<T> task;
final int retries; final int retries;
final Duration retryDelay; final Duration retryDelay;
final Duration _staleTime;
// all properties // all properties
T? data; T? data;
dynamic error; dynamic error;
QueryStatus status; QueryStatus status;
int retryAttempts = 0; int retryAttempts = 0;
late DateTime updatedAt; DateTime updatedAt;
int refetchCount = 0; int refetchCount = 0;
@protected @protected
@@ -39,15 +40,18 @@ class Query<T> extends ChangeNotifier {
Query({ Query({
required this.queryKey, required this.queryKey,
required this.task, required this.task,
required Duration staleTime,
this.retries = 3, this.retries = 3,
this.retryDelay = const Duration(milliseconds: 200), this.retryDelay = const Duration(milliseconds: 200),
T? initialData, T? initialData,
QueryListener<T>? onData, QueryListener<T>? onData,
QueryListener<dynamic>? onError, QueryListener<dynamic>? onError,
}) : status = QueryStatus.pending, }) : status = QueryStatus.pending,
_staleTime = staleTime,
data = initialData, data = initialData,
_onData = onData, _onData = onData,
_onError = onError; _onError = onError,
updatedAt = DateTime.now();
// all getters & setters // all getters & setters
bool get hasData => data != null && error == null; bool get hasData => data != null && error == null;
@@ -60,6 +64,9 @@ class Query<T> extends ChangeNotifier {
bool get isSucceeded => status == QueryStatus.succeed && data != null; bool get isSucceeded => status == QueryStatus.succeed && data != null;
// all methods // all methods
/// Calls the task function & doesn't check if there's already
/// cached data available
Future<void> _execute({bool isFetch = true}) async { Future<void> _execute({bool isFetch = true}) async {
try { try {
retryAttempts = 0; retryAttempts = 0;
@@ -95,6 +102,9 @@ class Query<T> extends ChangeNotifier {
} }
Future<T?> fetch() async { Future<T?> fetch() async {
if (!_isStaleData() && hasData) {
return data;
}
return _execute().then((_) { return _execute().then((_) {
fetched = true; fetched = true;
return data; return data;
@@ -105,4 +115,10 @@ class Query<T> extends ChangeNotifier {
refetchCount++; refetchCount++;
return _execute(isFetch: false).then((_) => data); 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));
}
} }
+8 -5
View File
@@ -18,19 +18,22 @@ class QueryBuilder<T> extends StatefulWidget {
} }
class _QueryBuilderState<T> extends State<QueryBuilder<T>> { class _QueryBuilderState<T> extends State<QueryBuilder<T>> {
late Query<T> query;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
query = Query<T>(queryKey: widget.queryKey, task: widget.task);
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
await QueryBowl.of(context).fetchQuery(query); await QueryBowl.of(context).fetchQuery(Query<T>(
queryKey: widget.queryKey,
task: widget.task,
staleTime: QueryBowl.of(context).staleTime,
));
}); });
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final queryRT = QueryBowl.of(context).getQuery<T>(widget.queryKey) ?? query; final query = QueryBowl.of(context).getQuery<T>(widget.queryKey);
return widget.builder(context, queryRT); if (query == null) return Container();
return widget.builder(context, query);
} }
} }