Code here : home_page.dart
Parsing the data from memesAPI
Future<MemesModel> getMemesApi() async {
final response =
await http.get(Uri.parse("https://api.imgflip.com/get_memes"));
var data = jsonDecode(response.body);
if (response.statusCode == 200) {
return MemesModel.fromJson(data);
} else {
return MemesModel.fromJson(data);
}
}
memes is of type Future which will contain the fetched data.
Note : late keyword is important.
call the method in initState() ```dart class _HomePageState extends State { late Future memes;
@override void initState() { super.initState(); memes = getMemesApi(); }
- use FutureBuilder to render the data on screen
```dart
body: FutureBuilder<MemesModel>(
future: memes,
builder: (context, snapshot) {
snapshot.hasData
, snapshot.harError
)snapshot.hasData
render the UI, else if snapshot.hasError
display the error, else render a CircularProgressIndicator, i.e while waiting for data to be fetched.DynamicHeightGridView(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 25,
itemCount:
//nullcheck operator
snapshot.hasData ? snapshot.data!.data!.memes!.length : 1,
builder: (context, index) {
//data fetched successfully
if (snapshot.hasData) {
//render UI here
}
//data couldn't be fetched due to some error
else if (snapshot.hasError) {
return Center(
child: Text("Error Occured : ${snapshot.error}"),
);
//waiting for data to be fetched (just the way youtube videos show circular progressor while buffering)
else {
return const Center(
child: CircularProgressIndicator(
color: Colors.teal,
));
}
Provider is a state management tool, you can refer more about it here : ProviderExample
Note : It may take sometime to understand provider, my case was no different. (Remember : Nothing comes overnight, good things take time!)
We have 2 basic requirements using provider.
Case-1 : Increment/Decreament the counter value on the cart icon on home page(refer images above).
Case-2 : Building the Cart page.
Case-1 : Increment/Decreament Counter Code here : cart_counter_provider.dart
import 'package:flutter/cupertino.dart';
class CartCounterProvider extends ChangeNotifier {
int cartCount;
CartCounterProvider({this.cartCount = 0});
int get getCartCount => cartCount;
void increment() {
cartCount += 1;
notifyListeners();
}
void decrement() {
cartCount -= 1;
notifyListeners();
}
}
Next, when will we need the provider?, when the button is pressed!, hence write the code inside the onPressed() function of button "Get this Meme"
Code here
context.read<CartCounterProvider>().increment();
Code here
//just inside the build method this cartCounter will watch the value of the counter
//button pressed -> increment() method called using provider -> cartCounter watches the value and updates accordingly
int cartCounter = context.watch<CartCounterProvider>().getCartCount;
Using read and watch is one way to do it. Another one is using the instance of the Provider class you made, lets discuss this approach for Case-2.
Case-2 : Building the Cart page.
Note : Always try to define the functionalities prior before implementing.
The plan for cart page is simple:
Provider class for displaying Cart(MemeCartProvider)
//read below about CartCardModel first
import 'package:memeapp/models/cart_card_model.dart';
import 'package:flutter/cupertino.dart';
class MemeCartProvider extends ChangeNotifier {
//now it's convenient for us to display the memes, we just need a list of CartCardModel!
//each instance of this class will have the respective id, imageURL, and name of the meme.
//We just need to traverse and display this list in the cart page, thats it!
//_cartList will have the id, imageURL, name of only those memes that are added to cart by user
final List<CartCardModel> _cartList = <CartCardModel>[];
//memesIdList will only contain the meme ID's which will be used to add/remove memes from the cart
//also used to prevent duplicates
List<String>? memesIdList = <String>[];
List<CartCardModel> get getCartList => _cartList;
List<String>? get getMemesIdList => memesIdList;
void addItem(CartCardModel addThisItem) {
_cartList.add(addThisItem);
notifyListeners();
}
void removeItem(String memeId) {
_cartList.removeWhere((element) => element.id == memeId);
memesIdList!.remove(memeId);
notifyListeners();
}
}
CartCardModel cart_card_model.dart
//each instance of this class (CartCardModel) will have the info of id, imageURL, and name.
//it will now be easier to display the memes in the cart page
class CartCardModel {
String id;
String? nameCart;
String? imageUrlCart;
CartCardModel({
required this.id,
this.nameCart,
this.imageUrlCart,
});
}
Now its convenient for us to render memes in the Cart Page. We simply traverse the List and display items accordingly.
But, how will we make sure only those items are rendered which were added by the user? Provider it is, again!.
Code cart_page.dart
//define an instance of MemeCartProvider class like this inside the build method
Widget build(BuildContext context) {
var memeCartProvider = Provider.of<MemeCartProvider>(context);
Code here
//wrap the Listview.builder with CONSUMER<MemeCartProvider>
Consumer<MemeCartProvider>(
builder: (context, value, child) {
//ListView will traverse CartCardModel list and render memes accordingly
return ListView.builder(
//itemCount is simply the length of the list.
itemCount: value.getMemesIdList!.length,
itemBuilder: ((context, index) {
object/instance of CartCardModel class using MemeCartProvider
CartCardModel cartObject = value.getCartList[index];
Code here
//render the image using cartObject
Image.network(
"${cartObject.imageUrlCart}",
width: 140,
),
//render the name using cartObject
Text(
//limiting name to 20 characters
cartObject.nameCart!.length > 20
? "${cartObject.nameCart!.substring(0, 20)}..."
: "${cartObject.nameCart}",
Last but not the least, we need to implement the delete feature
onPressed: () {
//we will remove the item from the list
value.removeItem(cartObject.id);
//why this line? you might've guessed it already, if not, dont worry
//remember we incrementes the counter value when user added items to the cart
//now user is deleting items, hence we need to decreament that counter value too!, right?
context.read<CartCounterProvider>().decrement();
},
And...Thats a Wrap! I hope this helped you and you learnt something new. If you desire, consider giving this repo a ⭐. In case you have any queries, you can surely reach me out through my socials.
ALL THE BEST🙌
Author: Nareshmalviyaspacestem
Source: https://github.com/Nareshmalviyaspacestem/MemeAppFlutter-akr-branch