Add flutter_data
and dependencies to your pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
flutter_data: ^1.1.0
# Highly RECOMMENDED (but not required) packages
path_provider: ^2.0.7
json_annotation: ^4.4.0
flutter_riverpod: ^1.0.0
dev_dependencies:
build_runner: ^2.0.4 # REQUIRED!
# Highly RECOMMENDED (but not required) packages
json_serializable: ^6.1.4
Flutter Data doesn’t require any library besides build_runner
for code generation.
However, json_serializable
and path_provider
are highly convenient so they are recommended.
flutter_data
should be 1.1.0
. Please check for all packages latest stable versions before copy-pasting dependencies.Annotate your models with @DataRepository()
and mix DataModel<T>
in.
Example:
import 'package:flutter_data/flutter_data.dart';
import 'package:json_annotation/json_annotation.dart';
part 'task.g.dart';
@JsonSerializable()
@DataRepository([])
class Task with DataModel<Task> {
@override
final int? id;
final String title;
final bool completed;
Task({this.id, required this.title, this.completed = false});
}
The annotation takes a list of adapters.
Adapters are mixins used to customize the framework’s behavior, ranging from the very basic to the extremely powerful. They are applied on Flutter Data’s RemoteAdapter<T>
base class.
Let’s start by the most common configuration: the base URL.
mixin ApplicationAdapter<T extends DataModel<T>> on RemoteAdapter<T> {
@override
String get baseUrl => 'https://my-json-server.typicode.com/flutterdata/demo/';
}
Next, we’ll pass it to the annotation:
@JsonSerializable()
@DataRepository([ApplicationAdapter])
class Task with DataModel<Task> {
final int? id;
final String title;
final bool completed;
Task({this.id, required this.title, this.completed = false});
}
Flutter Data ships with a built-in serializer/deserializer for classic JSON.
It means that the default serialized form of a Task
instance looks like:
{
"id": 1,
"title": "delectus aut autem",
"completed": false
}
Notice two things about our model above:
int?
to represent the actual type of the id
identifier field (null
when new)fromJson
and toJson()
haven’t been included as they are not required (Flutter Data will automatically use _$TaskFromJson
and _$TaskToJson
functions generated by json_serializable
– but they can both be overridden)We are now ready to run a build:
flutter pub run build_runner build
Flutter Data auto-generated a Repository
class for Task
.
It also generated a Dart library at main.data.dart
which makes Flutter Data initialization effortless. It’s out-of-the-box compatible with Riverpod.
Next step is to configure local storage and initialize the framework:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_data/flutter_data.dart';
import 'package:tutorial/main.data.dart';
void main() {
runApp(
ProviderScope(
child: TasksApp(),
overrides: [configureRepositoryLocalStorage()],
),
);
}
class TasksApp extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
home: Scaffold(
body: Center(
child: ref.watch(repositoryInitializerProvider()).when(
error: (error, _) => Text(error.toString()),
loading: () => const CircularProgressIndicator(),
data: (_) => 'Hello from Flutter Data ${ref.tasks}!',
),
),
),
debugShowCheckedModeBanner: false,
);
}
}
Once the data
callback is invoked, Flutter Data is ready!
The configureRepositoryLocalStorage
setup function has several optional arguments.
You will have to supply baseDirFn
(a function that returns a base directory for local storage) if you do not have path_provider
as a dependency.
For more information see initialization.
âž¡ Continue with the tutorial for a Tasks app or learn more about Repositories