Building a social media app with AWS Amplify and Flutter(PART 3)

I love creating and writing about the creation of software.
Search for a command to run...

I love creating and writing about the creation of software.
No comments yet. Be the first to comment.
This series outlines the steps involved in build an MVP for a social Medial Application using the Amplify Framework and flutter
Welcome to the 4th and final post in this series. PART 1 PART 2 PART 3 In the last 3 posts, we setup Amplify to Work with Flutter, Created a Login/Registration Screen Sign In With Google Created an update profile screen Create and Display Posts ...
Watch the complete Video on Youtube https://www.youtube.com/watch?v=kKX-8L_R2XM Prerequisites Before proceeding make sure you have these dependencies Docker Python 3.11 and above AWS CLI Full access to a foundation model. For this workshop, we'll...

Introduction In a previous workshop, Building event-driven applications with AWS sam and python we built an e-commerce ordering service using AWS SAM, API Gateway, Lambda and Python. Here's the solutions architecture. In that workshop, whenever a ne...

Github Repository https://github.com/EducloudHQ/introduction_to_gen_ai Skill up with serverless on Educloud https://www.educloud.academy/content/da99ad07-7efa-41e7-ba50-b18e6b89e10d This post is an introductory lesson to building AI-enhanced serverle...

Introduction Serverless computing is a cloud-based approach to application development that eliminates the need for provisioning and managing servers. Instead, developers focus on writing code that is triggered by events such as HTTP requests or data...

https://github.com/trey-rosius/sam_stepfunctions Hey!!! How you doing? In this post, we’ll look at how to build a workflow, using SAM as IaC, Appsync, and python. Prerequisites Install AWS Cli (https://docs.aws.amazon.com/cli/latest/userguide/cli-c...

In PART 1 and PART 2 of this series, we covered how to configure Amplify with Flutter, create login/registration screens and update profile screen.
In this post, we'll look at how to let a user add and display all posts in the database in real time.
The next major component in our system after user login is creating and displaying a Post.
A post consist of a postText, postStatus, postImage, and the user who made the post.
For the postText, we'll use a TextFormField to grab user input, and then, we'll use this image_picker: ^0.8.2 library we already added to the pubspec.yaml file.
createPost function
Future<bool> createPost(String userId) async{
loading = true;
/**
* first retrieve user model
*/
try {
List<User> user = await Amplify.DataStore.query(
User.classType, where: User.ID.eq(userId));
print("user details" + user[0].toString());
Post post = Post(content: postTextController.text.trim(),
type: PostType.TEXT_IMAGE,
status: PostStatus.CREATED,
userID: userId,
postImageUrl: postImageUrl,
user: user[0],
//user model
createdOn: TemporalDateTime.now(),
updatedOn: TemporalDateTime.now());
await Amplify.DataStore.save(post);
loading = false;
return true;
}catch(ex){
print(ex.toString());
loading = false;
return false;
}
}
What the code above does is, firstly, it gets the details of the user(UserModel) who's about to make the post. Then, create a new post Object and adds all the corresponding Post fields.
Remember that there's a one-to-many relationship between a User and a Post.
So when saving a post item, we have to satisfy that relationship.
We do that by adding the userId and user[0] object to the Post object.
We call await Amplify.DataStore.save(post); to save the Post Object to the datastore, which would later synchronize this local data with our remote database. You don't have to worry about that.
Strings: eq | ne | le | lt | ge | gt | contains | notContains | beginsWith | between
Numbers: eq | ne | le | lt | ge | gt | between
Lists: contains | notContains
So We'll be using predicates to filter and grab the data we need
getAllPosts
Future<List<Post>>queryAllPosts() async{
List<Post> posts = await Amplify.DataStore.query(Post.classType,sortBy: [Post.CREATEDON.descending()]);
return posts;
}
We want to retrieve the latest posts first. So we sortBy [Post.CREATEDON.descending()]
Pagination is also a piece of cake. Here's a function to paginate through the posts
paginatePosts
Future<List<Post>>paginatePosts(int page) async{
List<Post> posts = await Amplify.DataStore.query(Post.classType,sortBy: [Post.CREATEDON.descending()],
pagination: QueryPagination(page:page, limit:100));
return posts;
}
getSinglePost
Future<List<Post>>getSinglePost(String postID) async{
List<Post> posts = await Amplify.DataStore.query(Post.classType,where: Post.ID.eq(postID));
return posts;
}
updatePost
Future<void> updatePost(String postId) async{
Post oldPost = (await Amplify.DataStore.query(Post.classType,
where: Post.ID.eq(postId)))[0];
Post newPost = oldPost.copyWith(id: oldPost.id,
createdOn: TemporalDateTime.now(),
updatedOn: TemporalDateTime.now());
await Amplify.DataStore.save(newPost);
}
You can also get all posts for a particular user
queryAllUserPosts
Future<List<Post>>queryAllUserPosts(String userId) async{
List<Post> posts = await Amplify.DataStore.query(Post.classType,
where: Post.USERID.eq(userId),
sortBy: [Post.CREATEDON.descending()]);
return posts;
}
Now, how do we display a list of posts on our home page?
Like so
postRepo.queryAllPosts().then((value) {
postRepo.posts = value;
print("something posts "+value.toString());
});
Firstly, we'll query all the posts and save them in a List, then we loop through the list and display each individual post.
ListView.builder(
itemBuilder: (context,index){
return PostItem(userId!,postRepo.posts[index]);
},itemCount: postRepo.posts.length,)
How cool is that ?

So how do we accomplish this ?
late StreamSubscription postStream;
postStream = Amplify.DataStore.observe(Post.classType).listen((event) {
if(event.eventType != EventType.create){
return;
}
if(postRepo.posts[0].id != event.item.id){
postRepo.posts.insert(0, event.item);
print('Received event of type ' + event.eventType.toString());
print('Received post ' + event.item.toString());
}
});
From the above code, we define a StreamSubscription and listen to all events happening in the POST model.
You can use event.eventType to know if the event was an onCreate, onUpdate or onDelete.
At this stage, we want to get updates for create events only.
I noticed that subscriptions get fired multiple times, which wasn't what I wanted. It added duplicates to my listview.
So I added this if statement if(postRepo.posts[0].id != event.item.id) to make sure not to add duplicates to the listview.
Please get the complete code here Friends_GitHUB and it out.
Here's also a video illustration.
14 October, 2021 - Create/List Post - Watch Video
In the next post, we'll be going through creating and getting a list of comments for a post in real-time.
So stay tuned 😉
Thanks for checking this out.
I'll love to know what you think about this series or how you feel about the Amplify Framework.
Happy Coding ✌🏾