AWSAmplify DataStore enables the developers to add offline capabilities to their apps with just a few lines of code. It provides an on-device data storage service to read, write and observe data (online & offline mode) and sync it to a cloud database (DynamoDB).
Amplify use GraphQL for the data modeling, and it creates the models in the native language of your framework (JS, Java, Swift, Dart, etc.). This post will use the DataStore to create a Todo App where the user can create, update & delete tasks.
GetX is a micro-framework that combines State Management, Dependency Injection, Route Management, and other valuable utilities (e.g., internationalization, theming, validation, etc.). It is one of the most popular state management packages.
We used the Admin UI to create the backend and enable authentication
Create the Flutter App and run the command below to pull the Amplify backend
amplify pull --appId <Your_appId> --envName staging
Follow the instructions describedhere to add GraphQL API. Once completed, you will get the following in your App.
We will need two models (Users & ToDo), update the file amplify/backend/{api_name}/schema.graphql as below
type Todo @model {
id: ID!
name: String!
createdAt: AWSTimestamp
updatedAt: AWSTimestamp
isDone: Boolean
userId: String
}
type Users @model {
id: ID!
username: String
email: AWSEmail
isVerified: Boolean
createdAt: AWSTimestamp
}
The schema is ready; run the Amplify CLI command below to generate the models.
amplify codegen models
The models will be created as below
We will use three GetxControllers:
AuthController: This will handle the authentication operations by integrating with AuthService, which will use Amplify to authenticate the user. Once the user is signed in, we will create a user datastore record using DataStoreService. here we will also determine what page to display to the user based on the auth status
....
handleAuthChanged(isSignedIn) {
if (!isSignedIn) {
Get.offAllNamed("/signin");
} else {
Get.offAllNamed("/home");
}
}
...
Check my previous post to learn more about Amplify Authentication
Authentication Flow with Flutter & AWS Amplify
Offline Programmer ・ Apr 15 '21
UserController: We will use it to get the user record from the DataStore.
....
Future<void> getCurrUser() async {
AuthUser authUser = await _authService.getCurrentUser();
currentUser.value = await _datastoreService.getUser(authUser.userId);
print(currentUser.value);
}
...
TodoController: This is for creating\deleting\updating the tasks from the DataStore.
....
Future<void> getTodos() async {
AuthUser _authUser = await _authService.getCurrentUser();
List<Todo> _list = await _datastoreService.getTodos(_authUser.userId);
todoList.addAllIf(_list != null, _list);
}
Future<void> addTodo() async {
AuthUser _authUser = await _authService.getCurrentUser();
Todo todo = new Todo(
name: todoTitleController.text.toString(),
isDone: false,
createdAt: TemporalTimestamp.now(),
updatedAt: TemporalTimestamp.now(),
userId: _authUser.userId);
await _datastoreService.saveTodo(todo);
todoList.add(todo);
}
Future<void> removeTodo(Todo todo) async {
await _datastoreService.removeTodo(todo);
todoList.remove(todo);
}
Future<void> setToDoDone(Todo todo, bool newValue) async {
await _datastoreService.setToDoDone(todo, newValue);
todoList[todoList.indexWhere((element) => element.id == todo.id)] =
todo.copyWith(isDone: newValue);
}
...
In the HomePage, the user will be able to create and manage the Todo tasks. Here we will use the power of GetX and its reactive state manager to enable the following features:
Displaying the user email
....
appBar: AppBar(
title: GetX<UserController>(
initState: (_) async {
await Get.find<UserController>().getCurrUser();
},
builder: (_) {
return Text(controller.user?.email ?? '',
style: TextStyle(fontSize: 12));
},
),
...
Displaying the todo tasks
....
Obx(
() => Expanded(
child: ListView.builder(
itemCount: _todocontroller.todoList.length,
itemBuilder: (_, index) {
return TodoCard(todo: _todocontroller.todoList[index]);
},
),
),
),
...
We will use a Get.dialog to add a new Todo task
....
floatingActionButton: FloatingActionButton(
onPressed: () {
Get.dialog(AlertDialog(
title: Text('Add Todo here'),
content: TextFormField(
controller: _todocontroller.todoTitleController,
decoration: InputDecoration(hintText: "Title"),
),
actions: [
TextButton(
child: Text('OK'),
onPressed: () async {
if (_todocontroller.todoTitleController.text != "") {
await _todocontroller.addTodo();
_todocontroller.todoTitleController.clear();
}
Get.back();
},
),
],
));
},
child: Icon(Icons.add),
),
...
We will show a checkbox for each task; the user can tab it to flag it as done. Dismissing the task will delete it from the DataStore.
....
@override
Widget build(BuildContext context) {
TodoController _todocontroller = Get.find();
return _buildContent(_todocontroller);
}
Dismissible _buildContent(TodoController _todocontroller) {
return Dismissible(
direction: DismissDirection.startToEnd,
onDismissed: (DismissDirection direction) {
if (direction == DismissDirection.startToEnd) {
_todocontroller.removeTodo(todo);
}
},
background: Container(
alignment: Alignment.centerLeft,
color: Colors.red,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
key: ValueKey(todo.id),
child: _buildCard(_todocontroller),
);
}
Card _buildCard(TodoController _todocontroller) {
return Card(
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: ListTile(
leading: Checkbox(
value: todo.isDone,
onChanged: (newValue) {
_todocontroller.setToDoDone(todo, newValue);
},
),
title: Text(
todo.name,
style: TextStyle(
color: Colors.black,
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
DateFormat.yMMMMEEEEd().format(
DateTime.fromMillisecondsSinceEpoch(
todo.createdAt.toSeconds() * 1000)),
style: TextStyle(
color: Colors.grey,
fontSize: 10,
),
),
],
),
),
);
}
...
Check the code on github
A Flutter Todo App using AWS Amplify & GetX
A simple To-Do List app created using AWS Amplify and GetX.
With this project you will learn how to:
- Use AWSAmplify Auth.
- Use AWSAmplify DataStore.
- Manage the state of the application using GetXController.
-
- Make the UI reactive efficiently, rebuilding only the necessary widgets.
YouTube video demo here:
Follow me on Twitter for more tips about #coding, #learning, #technology...etc.
Check my Apps on Google Play
Cover image Kelly Sikkema on Unsplash
Top comments (0)