{"id":13551381,"url":"https://github.com/bizz84/movie_app_state_management_flutter","last_synced_at":"2025-04-05T03:10:22.291Z","repository":{"id":38952777,"uuid":"327379619","full_name":"bizz84/movie_app_state_management_flutter","owner":"bizz84","description":"Flutter State Management: Movie App with Provider, Riverpod, flutter_bloc ","archived":false,"fork":false,"pushed_at":"2022-09-15T13:57:50.000Z","size":1193,"stargazers_count":567,"open_issues_count":4,"forks_count":100,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-03-27T18:55:33.776Z","etag":null,"topics":["flutter","flutter-bloc","provider","riverpod","rxdart","sembast","state-management"],"latest_commit_sha":null,"homepage":"https://codewithandrea.com","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bizz84.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"bizz84"}},"created_at":"2021-01-06T17:13:31.000Z","updated_at":"2025-03-21T16:29:01.000Z","dependencies_parsed_at":"2022-07-13T06:50:35.879Z","dependency_job_id":null,"html_url":"https://github.com/bizz84/movie_app_state_management_flutter","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/bizz84%2Fmovie_app_state_management_flutter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bizz84%2Fmovie_app_state_management_flutter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bizz84%2Fmovie_app_state_management_flutter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bizz84%2Fmovie_app_state_management_flutter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bizz84","download_url":"https://codeload.github.com/bizz84/movie_app_state_management_flutter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247280272,"owners_count":20912967,"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":["flutter","flutter-bloc","provider","riverpod","rxdart","sembast","state-management"],"created_at":"2024-08-01T12:01:46.965Z","updated_at":"2025-04-05T03:10:22.268Z","avatar_url":"https://github.com/bizz84.png","language":"Dart","funding_links":["https://github.com/sponsors/bizz84"],"categories":["Dart"],"sub_categories":[],"readme":"# Flutter State Management: Movie App with Provider, Riverpod, flutter_bloc \u0026 more\n\nThis reference project shows how to implement a (Netflix-inspired) movie app with different state management techniques in Flutter:\n\n![Movie app preview](media/app-screenshots.png)\n\nThe project uses the [TMDB API](https://www.themoviedb.org/documentation/api) to fetch a list of movies, and includes features such as pagination and local storage.\n\n### Running the project\n\nBefore running, see instructions on how to [get a TMDB API key](#getting-a-tmdb-api-key).\n\nAlso, make sure to run on **Flutter beta** channel.\n\n## App Overview\n\nThe application is composed by three primary screens: **Now Playing**, **Favourites** and **Profiles**.\n\nOn first launch, the app asks the user to create a profile. \n\nThe **Now Playing** page loads a list of current movies from the TMDB API. Results are paginated and scrolling to the bottom causes the next page to be loaded.\n\nEach movie shows as a poster using the image URL retrieved from the API. You can tap on the ❤️ icon to add a movie as a favourite (for the selected profile), and this preference is persisted to local disk.\n\nOpen the **Favourites** page to see the list of favourites for the currently selected profile.\n\nUse the **Profiles** page to create additional profiles and update the currently selected profile (this is inspired by the Netflix UI).\n\n## Features\n\n- \"Now Playing\" movies (with pagination)\n- Save favourites to watch list\n- Multiple profiles (like Netflix)\n- Local data persistence (movies, favourites, profiles) with Sembast\n\nCombining these features together makes for an interesting case study about state management in Flutter.\n\n## App Structure\n\nThis app was made to compare and contrast multiple state management approaches. A **highly composable** architecture has been designed to enable this.\n\nThe project folders are structured like this:\n\n```\n/apps\n  /flutter_bloc\n  /riverpod\n  /provider\n  ... and more\n/packages\n  /core\n    /lib\n      /api\n      /models\n        /app_models\n        /app_state\n        /tmdb\n      /persistence\n      /ui\n```\n\nEach folder inside `apps` is a Flutter project that implements the same app with a specific state management package.\n\nAll common functionality lives in `packages/core`. This includes a TMDB API wrapper, along with model classes with supporting serialization code where needed.\n\nThe `persistence` folder contains a `DataStore` abstract class that is used by all apps, along with a concrete `SembastDataStore` class to read and write data to local storage (using Sembast as a NoSQL database).\n\nThe `ui` folder contains all the custom widgets that are shared by all apps. These widgets **do not hold any business logic** and are designed to **show the app UI** and **expose callbacks** for the application code to plug into (much like the built-in Flutter widgets).\n\nAll the logic lives inside the apps themselves. All apps have exactly the same folders:\n\n```\nlib\n  /app\n    /app_startup\n    /create_profile\n    /favourites\n    /now_playing\n    /profile_selection\n```\n\nThe business logic and screen flows are identical for each app, but the semantics change depending on which state management package is used. This makes it easy to compare and constrast different solutions.\n\n## Supported state management solutions\n\nThe current state management solutions are currently supported:\n\n- [x] [Provider](https://pub.dev/packages/provider) (using `StateNotifier`)\n- [x] [flutter_bloc](https://pub.dev/packages/flutter_bloc) (using `Cubit`)\n- [x] [Riverpod](https://pub.dev/packages/riverpod) (using `StateNotifier`)\n- [x] [get_it](https://pub.dev/packages/get_it) and [get_it_mixin](https://pub.dev/packages/get_it_mixin)\n- [x] [states_rebuilder](https://pub.dev/packages/states_rebuilder)\n  \nI plan to add more in the future (PRs welcome!).\n\n## Future Roadmap\n\n- Add more screens\n- Polish the UI\n\nFeel free to open issues if you'd like certain features to be implemented (though keep your expectations low, I'm doing this for free after all 😉).\n\n## Other packages in use\n\nThe \"core\" package of the app uses the following packages:\n\n- [Freezed](https://pub.dev/packages/freezed) for app state and [json_annotation](https://pub.dev/packages/json_annotation) for data serialization\n- [Sembast](https://pub.dev/packages/sembast) for local data persistence\n- [dio](https://pub.dev/packages/dio) for the API client\n- [rxdart](https://pub.dev/packages/rxdart) for combining streams\n- [envied](https://pub.dev/packages/envied) for API key security\n  \n## Getting a TMDB API key\n\nThis project uses the TMDB API to get the latest movies data.\n\nBefore running the app you need to [sign up on the TMDB website](https://www.themoviedb.org/signup), then obtain an API key on the [settings API page](https://www.themoviedb.org/settings/api).\n\nOnce you have this, create an `.env` file inside `packages/core/`, and add your key:\n\n```dart\n// .env\nTMDB_KEY=your-api-key\n```\n\nThen, run the code generator:\n\n```\nflutter pub run build_runner build --delete-conflicting-outputs\n```\n\nThis will generate a `env.g.dart` file inside `packages/core/lib/api`, that is used when making requests to the TMDB API.\n\nCongratulations, you're good to go. 😎\n\n## Note: Loading images from insecure HTTP endpoints\n\nThe data returned by the TMBD API points to image URLs using http rather than https. In order for images to load correctly, the following changes have been made:\n\n### Android\n\nCreated a file at `android/app/src/main/res/xml/network_security_config.xml` with these contents:\n\n```\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cnetwork-security-config\u003e\n    \u003cbase-config cleartextTrafficPermitted=\"true\" /\u003e\n\u003c/network-security-config\u003e\n```\n\nAdded this to the application tag in the `AndroidManifest.xml`:\n\n```\nandroid:networkSecurityConfig=\"@xml/network_security_config\"\n```\n\n### iOS\n\nAdd the following to `ios/Runner/info.pList`:\n\n```\n  \u003ckey\u003eNSAppTransportSecurity\u003c/key\u003e\n  \u003cdict\u003e\n      \u003ckey\u003eNSAllowsArbitraryLoads\u003c/key\u003e\n      \u003ctrue/\u003e\n  \u003c/dict\u003e\n```\n\nMore information here:\n\n- [Insecure HTTP connections are disabled by default on iOS and Android.](https://flutter.dev/docs/release/breaking-changes/network-policy-ios-android)\n\n### macOS\n\nSince macOS applications are sandboxed by default, we get a `SocketException` if we haven't added the required entitlements. This has been fixes by adding these lines to `macos/Runner/DebugProfile.entitlements` and `macos/Runner/Release.entitlements`:\n\n```\n\u003ckey\u003ecom.apple.security.network.client\u003c/key\u003e\n\u003ctrue/\u003e\n```\n\nMore info here:\n\n- [How to fix \"SocketException: Connection failed (Operation not permitted)\" with Flutter on macOS](https://codewithandrea.com/tips/socket-exception-connection-failed-macos/)\n\n## Credits\n\nThis project was inspired by [flutter\\_architecture\\_samples](https://github.com/brianegan/flutter_architecture_samples) by the Flutter community.\n\n## [LICENSE: MIT](LICENSE.md)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbizz84%2Fmovie_app_state_management_flutter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbizz84%2Fmovie_app_state_management_flutter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbizz84%2Fmovie_app_state_management_flutter/lists"}