alpha stale_time & caching support
This commit is contained in:
@@ -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(
|
||||||
|
|||||||
@@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user