docs: update installation and overview to support new one
This commit is contained in:
@@ -8,6 +8,7 @@ Fl-Query is just another Flutter "package" so no extra installation step needed
|
|||||||
```bash
|
```bash
|
||||||
$ flutter pub add fl_query
|
$ flutter pub add fl_query
|
||||||
```
|
```
|
||||||
|
<br/>
|
||||||
|
|
||||||
### Using with `flutter_hooks`
|
### Using with `flutter_hooks`
|
||||||
|
|
||||||
@@ -22,4 +23,50 @@ The hooks can be imported as follows:
|
|||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'package:fl_query/fl_query_hooks.dart';
|
import 'package:fl_query/fl_query_hooks.dart';
|
||||||
|
```
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
### Add offline support in your App (Optional)
|
||||||
|
|
||||||
|
Fl-Query supports refetching queries when internet connection is restored. To enable this feature you need to install:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ flutter pub add fl_query_connectivity_plus_adapter
|
||||||
|
```
|
||||||
|
|
||||||
|
Add following in your `main.dart` file
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:fl_query_connectivity_plus_adapter/fl_query_connectivity_plus_adapter.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
// ....
|
||||||
|
await QueryClient.initialize(
|
||||||
|
connectivity: FlQueryConnectivityPlusAdapter(),
|
||||||
|
);
|
||||||
|
// ....
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
### Try out the new devtools✨
|
||||||
|
|
||||||
|
FL-Query now offers a devtool. It is still in alpha phase but it is expected to be complete in some time
|
||||||
|
|
||||||
|
Install the devtools:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ flutter pub add fl_query_devtools
|
||||||
|
```
|
||||||
|
|
||||||
|
Add following to `MaterialApp`'s or `CupertinoApp`'s `builder` parameter:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
MaterialApp.router(
|
||||||
|
title: 'FL Query Example',
|
||||||
|
builder: (context, child) {
|
||||||
|
return FlQueryDevtools(child: child!);
|
||||||
|
},
|
||||||
|
//...
|
||||||
|
)
|
||||||
```
|
```
|
||||||
@@ -5,32 +5,174 @@ id: overview
|
|||||||
|
|
||||||
# Overview
|
# Overview
|
||||||
|
|
||||||
Fl-Query is a asynchronous data manager for Flutter that caches, fetches, automatically refetches stale data. Basically, its [Tanstack-Query](https://tanstack.com/query/) (formerly React-Query) but for Flutter. But that doesn't mean it's a direct port of Tanstack-Query. Instead the concept of Tanstack-Query is implemented by Fl-Query
|
Asynchronous data caching, refetching & invalidation library for Flutter. FL-Query lets you manage & distribute your async data without touching any global state
|
||||||
|
|
||||||
## What does it offer?
|
Fl-Query makes asynchronous server state management a breeze in flutter
|
||||||
|
|
||||||
- Async data caching & invalidation
|
# Features
|
||||||
- Smart refetch in the background every time data becomes stale
|
|
||||||
- Declarative way to define asynchronous operations
|
- Async data caching & management
|
||||||
- Code & data reusability because of persisted data & Query/Mutation **Job** API
|
- Smart + effective refetching
|
||||||
- Optimistic data support
|
- Optimistic updates
|
||||||
- Lazy Loading/Fetching support
|
- Automatically cached data invalidation & unneeded query/mutation garbage collection
|
||||||
- Zero Configuration out of the box & never have to touch any Global Store
|
- Infinite pagination via `InfiniteQuery`
|
||||||
- [Flutter Hooks](https://pub.dev/packages/flutter_hooks) support out of the box
|
- Lazy persistent cache (Uses [hive](https://pub.dev/packages/hive) for persisting query results to disk) (optional)
|
||||||
|
- Easy to write & understand code. Follows DRY (Don't repeat yourself) convention
|
||||||
|
- Compatible with both vanilla Flutter & elite [flutter_hooks](https://pub.dev/packages/flutter_hooks)
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
Regular installation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ flutter pub add fl_query
|
||||||
|
```
|
||||||
|
|
||||||
|
For elite flutter_hooks user (Welcome to the flutter cool community btw😎)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ flutter pub add flutter_hooks fl_query_hooks
|
||||||
|
```
|
||||||
|
|
||||||
|
# Docs
|
||||||
|
|
||||||
|
You can find the documentation of fl-query at https://fl-query.vercel.app/
|
||||||
|
|
||||||
|
# Basic Usage
|
||||||
|
|
||||||
|
Initialize the cache databases in your `main` method
|
||||||
|
|
||||||
|
> fl-query uses [hive](https://pub.dev/packages/hive) for persisting data to disk
|
||||||
|
|
||||||
|
```dart
|
||||||
|
void main()async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await QueryClient.initialize(cachePrefix: 'fl_query_example');
|
||||||
|
runApp(MyApp());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
In `MyApp` Widget's build method wrap your `MaterialApp` with with `QueryClientProvider` widget
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return QueryClientProvider(
|
||||||
|
child: MaterialApp(
|
||||||
|
title: 'Fl-Query Example App',
|
||||||
|
theme: ThemeData(
|
||||||
|
useMaterial3: true,
|
||||||
|
primarySwatch: Colors.blue,
|
||||||
|
),
|
||||||
|
home: const MyHomePage(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's write use a `Query` now
|
||||||
|
FL-Query provides a `QueryBuilder` widget that creates and listens to the specified `Query`
|
||||||
|
and re-runs the builder function whenever there's an update
|
||||||
|
|
||||||
|
It has 2 required parameters `key`(unnamed) & `builder`
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class MyApp extends StatelessWidget{
|
||||||
|
MyApp({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
build(context){
|
||||||
|
return QueryBuilder<String, dynamic>(
|
||||||
|
'hello',
|
||||||
|
() {
|
||||||
|
return Future.delayed(
|
||||||
|
const Duration(seconds: 6), () => 'Hello World!');
|
||||||
|
},
|
||||||
|
initial: 'A replacement',
|
||||||
|
jsonConfig: JsonConfig(
|
||||||
|
fromJson: (json) => json['data'],
|
||||||
|
toJson: (data) => {'data': data},
|
||||||
|
),
|
||||||
|
onData: (value) {
|
||||||
|
debugPrint('onData: $value');
|
||||||
|
},
|
||||||
|
onError: (error) {
|
||||||
|
debugPrint('onError: $error');
|
||||||
|
},
|
||||||
|
builder: (context, query) {
|
||||||
|
if (query.isLoading) {
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
} else if (query.hasError) {
|
||||||
|
return Center(
|
||||||
|
child: Text(query.error.toString()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Center(
|
||||||
|
child: Text(query.data ?? "Unfortunately, there's no data"),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And if you're using **flutter_hooks** you got that too
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class MyApp extends HookWidget{
|
||||||
|
MyApp({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
build(context){
|
||||||
|
final query = useQuery<String, dynamic>(
|
||||||
|
'hello',
|
||||||
|
() {
|
||||||
|
return Future.delayed(
|
||||||
|
const Duration(seconds: 6), () => 'Hello World!');
|
||||||
|
},
|
||||||
|
initial: 'A replacement',
|
||||||
|
jsonConfig: JsonConfig(
|
||||||
|
fromJson: (json) => json['data'],
|
||||||
|
toJson: (data) => {'data': data},
|
||||||
|
),
|
||||||
|
onData: (value) {
|
||||||
|
debugPrint('onData: $value');
|
||||||
|
},
|
||||||
|
onError: (error) {
|
||||||
|
debugPrint('onError: $error');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (query.isLoading) {
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
} else if (query.hasError) {
|
||||||
|
return Center(
|
||||||
|
child: Text(query.error.toString()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Center(
|
||||||
|
child: Text(query.data ?? "Unfortunately, there's no data"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*To master the fl-query follow the official blog at https://fl-query.krtirtho.dev/blog*
|
||||||
|
|
||||||
# Why?
|
# Why?
|
||||||

|
<p align="center">
|
||||||
|
<img src="https://media.giphy.com/media/1M9fmo1WAFVK0/giphy.gif" alt="The hell, why?"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
The main purpose of Fl-Query is providing the easiest way to manage the messy server-state part requiring the least amount of code with code reusability & performance
|
The main purpose of Fl-Query is providing the easiest way to manage the messy server-state part requiring the least amount of code with code reusability & performance
|
||||||
|
This let's you focus more on those cool UI animations & transitions✨. Leave the boring stuff to fl-query
|
||||||
|
|
||||||
Some Questions and their answers:
|
**Q. Isn't `FutureBuilder` good?**
|
||||||
- **Isn't `FutureBuilder` good enough?**
|
|
||||||
|
|
||||||
Yes but it is only if your commercial server has huge load of power & you're made of money or your app is simple or mostly offline & barely requires internet connection
|
|
||||||
`FutureBuilder` isn't good for data persistency & its impossible to share data across the entire application using it. Also if you call your fetching function directly in the `build` method as `future: getData("random-id")` it'll run every time the component rebuilds & it can be mitigated only if you call the method inside `initState` which involves lots of boilerplate
|
|
||||||
|
|
||||||
- **`FutureProvider` from [riverpod](https://riverpod.dev/) or [provider](https://github.com/rrousselGit/provider) should be enough, right?**
|
No, of course not. Unless you're from 2013 or your app is a purely offline app
|
||||||
|
|
||||||
Yeah, indeed its more than enough for many applications but what if your app needs Optimistic Updates & proper server-state synchronization or simply want a custom `cacheTime`? Although `FutureProvider` is a viable solution for most of the `Future` but still you've to manually manage the cache & it still have no support for _Lazy Loading_.
|
**Q. So `FutureProvider` from riverpod or provider not enough?**
|
||||||
|
|
||||||
Remi Rousselet's riverpod is definitely an inspiration for Fl-Query & the `QueryJob` & `MutationJob` API is actually inspired by riverpod & IMO is the best state management solution any library has ever provided but that's still a client state manager just like other client state manager or synchronous data manager
|
Probably yes. Although riverpod@v2 has added a lot of caching related features but still optimistic updates, periodic refetching & disk persistence are missing. Let's not forget about infinite pagination, it's a nightmare😅. In case of provider, same story. It's a great package but it's not ideal for server-state management
|
||||||
Reference in New Issue
Block a user