{"id":23140946,"url":"https://github.com/akr-2803/memeappflutter","last_synced_at":"2026-05-10T05:35:27.039Z","repository":{"id":142634606,"uuid":"613735461","full_name":"AKR-2803/MemeAppFlutter","owner":"AKR-2803","description":"Meme app using memes API and Provider.","archived":false,"fork":false,"pushed_at":"2023-03-14T11:48:05.000Z","size":8512,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"akr-branch","last_synced_at":"2025-02-09T21:14:54.694Z","etag":null,"topics":["cross-platform","dart","flutter","flutter-api","flutter-api-implementation","flutter-app","flutter-apps","flutter-demo","flutter-examples","flutter-project","flutter-provider","flutter-ui","flutterappdesign","flutterapplication","flutterdeveloper","mobile","mobile-app","mobile-development","ui"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AKR-2803.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-14T06:59:00.000Z","updated_at":"2024-04-04T12:42:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"28d99d13-4154-4850-9665-073d84b9b8fa","html_url":"https://github.com/AKR-2803/MemeAppFlutter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AKR-2803%2FMemeAppFlutter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AKR-2803%2FMemeAppFlutter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AKR-2803%2FMemeAppFlutter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AKR-2803%2FMemeAppFlutter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AKR-2803","download_url":"https://codeload.github.com/AKR-2803/MemeAppFlutter/tar.gz/refs/heads/akr-branch","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247166171,"owners_count":20894654,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cross-platform","dart","flutter","flutter-api","flutter-api-implementation","flutter-app","flutter-apps","flutter-demo","flutter-examples","flutter-project","flutter-provider","flutter-ui","flutterappdesign","flutterapplication","flutterdeveloper","mobile","mobile-app","mobile-development","ui"],"created_at":"2024-12-17T14:12:03.531Z","updated_at":"2026-05-10T05:35:26.987Z","avatar_url":"https://github.com/AKR-2803.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Meme App using API and Provider\n\n### Splash Screen\n\u003ckbd\u003e\u003cimg src=\"https://user-images.githubusercontent.com/109909231/224924545-2479b895-9be3-4436-8401-10c25291e19a.png\" width=\"250\" height=\"550\"\u003e\u003c/kbd\u003e\n\n### Home Screen\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;Adding Items\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;Cart Screen\n\u003ckbd\u003e\u003cimg src=\"https://user-images.githubusercontent.com/109909231/224924675-ddb5a35f-4b5a-4390-a4e2-316d9d92852e.png\" width=\"250\" height=\"550\"\u003e\u003c/kbd\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003ckbd\u003e\u003cimg src=\"https://user-images.githubusercontent.com/109909231/224924803-b9d3270b-e425-4efb-96dc-ec830d5db4f1.png\" width=\"250\" height=\"550\"\u003e\u003c/kbd\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003ckbd\u003e\u003cimg src=\"https://user-images.githubusercontent.com/109909231/224924817-24c40565-7207-4acf-940d-9eb90619ed0b.png\" width=\"250\" height=\"550\"\u003e\u003c/kbd\u003e\n\n\n### Downloading Image\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;\u0026emsp;Empty Cart\n\u003ckbd\u003e\u003cimg src=\"https://user-images.githubusercontent.com/109909231/224925346-cb5bd3cd-c688-4053-a0c8-a56f549ee9ad.png\" width=\"250\" height=\"550\"\u003e\u003c/kbd\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003ckbd\u003e\u003cimg src=\"https://user-images.githubusercontent.com/109909231/224946487-ecf8b170-bec6-4b91-94ad-96ddbb500327.png\" width=\"250\" height=\"550\"\u003e\u003c/kbd\u003e\n\n### Recording: \n\nhttps://user-images.githubusercontent.com/109909231/224942240-a3389d7f-3005-4151-a6e3-20d6f59483f0.mp4\n\n## Packages used:\n - [http](https://pub.dev/packages/http)\n - [provider](https://pub.dev/packages/provider)\n - [dynamic_height_grid_view](https://pub.dev/packages/dynamic_height_grid_view)\n - [path](https://pub.dev/packages/path)\n - [path_provider](https://pub.dev/packages/path_provider)\n___\n## Detailed description of implementation \n\n### [i]. Fetching data from API and rendering UI\n### [ii]. Provider for state management\n### [iii]. Saving Image to Local Storage  \n___\n  \n### [i]. Fetching data from API and rendering UI\n\n#### Memes API : [MemesAPI](https://api.imgflip.com/get_memes) \n#### _Not sure How to parse JSON data from API?_ Detailed Explanation [here](https://github.com/AKR-2803/FlutterAPI-FlutterProvider#readme)\n\nCode here : [home_page.dart](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/screens/home_page.dart)\n\nParsing the data from memesAPI\n```dart\nFuture\u003cMemesModel\u003e getMemesApi() async {\n  final response =\n      await http.get(Uri.parse(\"https://api.imgflip.com/get_memes\"));\n  var data = jsonDecode(response.body);\n  if (response.statusCode == 200) {\n    return MemesModel.fromJson(data);\n  } else {\n    return MemesModel.fromJson(data);\n  }\n}\n```\n- memes is of type Future\u003cMemesModel\u003e which will contain the fetched data.\n- Note : late keyword is important.\n- call the method in initState()\n```dart\nclass _HomePageState extends State\u003cHomePage\u003e {\n  late Future\u003cMemesModel\u003e memes;\n\n  @override\n  void initState() {\n    super.initState();\n    memes = getMemesApi();\n  }\n```\n\n- use FutureBuilder to render the data on screen\n\n```dart\nbody: FutureBuilder\u003cMemesModel\u003e(\n        future: memes,\n        builder: (context, snapshot) {\n```\n\n- I used DynamicHeightGridView (package [here](https://pub.dev/packages/dynamic_height_grid_view)), you may use any preferred widget/package that suits you.\n- make sure you give itemCount property\n- snapshot will either have data or error (```snapshot.hasData``` , ```snapshot.harError```)\n- if ```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.\n\n```dart\nDynamicHeightGridView(\n                  crossAxisCount: 2,\n                  mainAxisSpacing: 10,\n                  crossAxisSpacing: 25,\n                  itemCount:\n                      //nullcheck operator\n                      snapshot.hasData ? snapshot.data!.data!.memes!.length : 1,\n                  builder: (context, index) {\n                  \n                 //data fetched successfully\n                    if (snapshot.hasData) {\n                      //render UI here\n                    }\n```\n```dart\n//data couldn't be fetched due to some error\nelse if (snapshot.hasError) {\n                      return Center(\n                        child: Text(\"Error Occured : ${snapshot.error}\"),\n                      );\n```\n```dart\n//waiting for data to be fetched (just the way youtube videos show circular progressor while buffering)\nelse {\n                      return const Center(\n                          child: CircularProgressIndicator(\n                        color: Colors.teal,\n                      ));\n                    }\n```\n___\n\n### [ii]. Provider for state management\n\n- We've rendered the UI. Great!\n- But, think about the cart feature, whenever the \"Get This Meme\" button is tapped :\n- how will the we increment the counter value on the top right corner on the cart icon?\n- how will we render the UI accordingly in the cart page?\n#### That's where PROVIDER comes in!\n\nProvider is a state management tool, you can refer more about it here : [ProviderExample](https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple)\n\nNote : It may take sometime to understand provider, my case was no different. (Remember : Nothing comes overnight, good things take time!)\n\n- Once/If you are familiar with provider, lets move ahead.\n\nWe have 2 basic requirements using provider.\n\nCase-1 : Increment/Decreament the counter value on the cart icon on home page(refer images above).\n\nCase-2 : Building the Cart page.\n___\n\nCase-1 : Increment/Decreament Counter\nCode here : [cart_counter_provider.dart](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/providers/cart_counter_provider.dart)\n- define the Provider class\n- make sure to extend ChangeNotifier\n- declare an integer cartCount\n- define the constructor(initalize cartCount value) and getter method\n- define the methods increment() and decreament()\n- notifyListeners()\n\n```dart\nimport 'package:flutter/cupertino.dart';\n\nclass CartCounterProvider extends ChangeNotifier {\n  int cartCount;\n  CartCounterProvider({this.cartCount = 0});\n\n  int get getCartCount =\u003e cartCount;\n\n  void increment() {\n    cartCount += 1;\n    notifyListeners();\n  }\n\n  void decrement() {\n    cartCount -= 1;\n    notifyListeners();\n  }\n}\n```\nNext, when will we need the provider?, when the button is pressed!, hence write the code inside the onPressed() function of button \"Get this Meme\"\n\nCode [here](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/screens/home_page.dart#L162)\n```dart\ncontext.read\u003cCartCounterProvider\u003e().increment();\n```\n\nCode [here](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/screens/home_page.dart#L46)\n```dart\n//just inside the build method this cartCounter will watch the value of the counter \n//button pressed -\u003e increment() method called using provider -\u003e cartCounter watches the value and updates accordingly\nint cartCounter = context.watch\u003cCartCounterProvider\u003e().getCartCount;\n```\nUsing 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.\n___\n\nCase-2 : Building the Cart page.\n\n_Note :_ Always try to define the functionalities prior before implementing.\n\nThe plan for cart page is simple:\n- Displaying a list of memes selected by the user.\n- Also include delete functionality.\n\n\nProvider class for displaying Cart(MemeCartProvider)\n\nCode [meme_cart_provider.dart](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/providers/meme_cart_provider.dart)\n\n```dart\n//read below about CartCardModel first\n\nimport 'package:memeapp/models/cart_card_model.dart';\nimport 'package:flutter/cupertino.dart';\n\nclass MemeCartProvider extends ChangeNotifier {\n  \n  //now it's convenient for us to display the memes, we just need a list of CartCardModel!\n  //each instance of this class will have the respective id, imageURL, and name of the meme.\n  //We just need to traverse and display this list in the cart page, thats it!\n  \n  \n  //_cartList will have the id, imageURL, name of only those memes that are added to cart by user\n  final List\u003cCartCardModel\u003e _cartList = \u003cCartCardModel\u003e[];\n  \n  //memesIdList will only contain the meme ID's which will be used to add/remove memes from the cart\n  //also used to prevent duplicates \n  List\u003cString\u003e? memesIdList = \u003cString\u003e[];\n\n  List\u003cCartCardModel\u003e get getCartList =\u003e _cartList;\n  List\u003cString\u003e? get getMemesIdList =\u003e memesIdList;\n\n  void addItem(CartCardModel addThisItem) {\n    _cartList.add(addThisItem);\n    notifyListeners();\n  }\n\n  void removeItem(String memeId) {\n    _cartList.removeWhere((element) =\u003e element.id == memeId);\n    memesIdList!.remove(memeId);\n    notifyListeners();\n  }\n}\n```\n\n- Wondering what's CartCardModel? (apologies for the confusing name :| )\n- See, we need to show the image and name of the respective memes right.\n- So, to not make things complicated, I defined a class named \"CartCardModel\", which will have id, imageURL, and name of the meme.\n- Why id?, to avoid duplicates!...id will ensure that once added, the same meme won't be added again.\n- ID can be anything that is unique to each item.\n- Thankfully, [MemeAPI](https://api.imgflip.com/get_memes) has IDs for each item already included.\n\nCartCardModel [cart_card_model.dart](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/models/cart_card_model.dart)\n\n```dart\n//each instance of this class (CartCardModel) will have the info of id, imageURL, and name.\n//it will now be easier to display the memes in the cart page\nclass CartCardModel {\n  String id;\n  String? nameCart;\n  String? imageUrlCart;\n  CartCardModel({\n    required this.id,\n    this.nameCart,\n    this.imageUrlCart,\n  });\n}\n```\n\nNow its convenient for us to render memes in the Cart Page.\nWe simply traverse the List\u003cCartCardModel\u003e and display items accordingly.\n\nBut, how will we make sure only those items are rendered which were added by the user?\nProvider it is, again!.\n\n\nCode [cart_page.dart](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/screens/cart_page.dart#L18)\n\n```dart\n  //define an instance of MemeCartProvider class like this inside the build method\n   Widget build(BuildContext context) {\n    var memeCartProvider = Provider.of\u003cMemeCartProvider\u003e(context);\n```\n\nCode [here](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/screens/cart_page.dart#L28)\n```dart\n//wrap the Listview.builder with CONSUMER\u003cMemeCartProvider\u003e\nConsumer\u003cMemeCartProvider\u003e(\n              builder: (context, value, child) {\n                //ListView will traverse CartCardModel list and render memes accordingly\n                return ListView.builder(\n                  //itemCount is simply the length of the list. \n                  itemCount: value.getMemesIdList!.length,\n                  itemBuilder: ((context, index) {\n                    object/instance of CartCardModel class using MemeCartProvider\n                    CartCardModel cartObject = value.getCartList[index];\n```\n\nCode [here](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/screens/cart_page.dart#L51)\n```dart\n //render the image using cartObject\n Image.network(\n                \"${cartObject.imageUrlCart}\",\n                     width: 140,\n              ),\n              \n //render the name using cartObject\n Text(           \n                  //limiting name to 20 characters \n                  cartObject.nameCart!.length \u003e 20\n                   ? \"${cartObject.nameCart!.substring(0, 20)}...\"\n                   : \"${cartObject.nameCart}\",\n```\n\nLast but not the least, we need to implement the delete feature\n\n```dart\n onPressed: () {\n                   //we will remove the item from the list\n                   value.removeItem(cartObject.id);                   \n                   \n                   //why this line? you might've guessed it already, if not, dont worry\n                   //remember we incrementes the counter value when user added items to the cart\n                   //now user is deleting items, hence we need to decreament that counter value too!, right?\n                   context.read\u003cCartCounterProvider\u003e().decrement();\n               },\n\n```\n___\n\n### [iii]. Saving Image to Local Storage  \n\n- The [code](https://github.com/AKR-2803/MemeAppFlutter/blob/akr-branch/lib/screens/preview_download.dart) is easy to understand. \n\n\nAnd...Thats a Wrap!\nI 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.\n\nALL THE BEST🙌\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakr-2803%2Fmemeappflutter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakr-2803%2Fmemeappflutter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakr-2803%2Fmemeappflutter/lists"}