使用Provider、Riverpod、flutter_bloc等实现的Flutter状态管理电影应用
项目地址:https://gitcode.com/bizz84/movie_app_state_management_flutter
这个开源项目展示了一个如何在Flutter中使用不同状态管理技术(如Provider、Riverpod和flutter_bloc)构建一款Netflix风格的电影应用。
该项目利用TMDB API获取当前播放的电影列表,功能包括分页和本地存储。
运行项目
在运行前,请参考获取TMDB API密钥的说明。
确保在Flutter beta通道下运行。
应用概述
应用由三个主要页面组成:现在播放、收藏和个人资料。
首次启动时,应用会提示用户创建一个个人资料。
现在播放页面从TMDB API加载电影列表。当滚动到底部时,将自动加载下一页的内容。
每个电影都显示为海报,使用API返回的图片URL。点击❤️图标可以将电影添加为收藏(对应当前选择的个人资料),并且这些偏好会被保存到本地磁盘。
打开收藏页面,可以看到当前所选个人资料的收藏列表。
通过个人资料页面,可以创建额外的个人资料并更新当前所选个人资料,灵感来自Netflix的界面设计。
功能特性
- 当前播放电影(含分页)
- 收藏电影至观看列表
- 多个个人资料(类似Netflix)
- 数据本地持久化(电影、收藏、个人资料)利用Sembast作为NoSQL数据库
结合这些特性,使该应用成为探究Flutter状态管理的一个精彩实例。
应用结构
为了便于比较各种状态管理方法,此应用设计为高度可组合架构。
项目目录如下所示:
/apps
/flutter_bloc
/riverpod
/provider
... 和更多
/packages
/core
/lib
/api
/models
/app_models
/app_state
/tmdb
/persistence
/ui
apps
目录下的每个子目录都是一个实现了相同应用但使用特定状态管理包的Flutter项目。
所有通用功能都位于packages/core
中,包括TMDB API包装器,以及模型类(包括必要的序列化代码)。persistence
目录包含了抽象的DataStore
类和用于本地数据读写的具体SembastDataStore
类。ui
目录包含了所有共享的自定义小部件,它们不持有任何业务逻辑,而是设计用于展示应用UI并提供回调供应用程序插件使用(类似于内置的Flutter小部件)。
所有的业务逻辑都存在于各个应用内部,且拥有相同的文件夹结构:
lib
/app
/app_startup
/create_profile
/favourites
/now_playing
/profile_selection
各应用之间的业务逻辑和屏幕流程完全相同,只是根据使用的状态管理包的不同,语义有所变化,这使得比较不同的解决方案变得简单。
支持的状态管理方案
目前支持以下状态管理解决方案:
- [x] Provider(使用
StateNotifier
) - [x] flutter_bloc(使用
Cubit
) - [x] Riverpod(使用
StateNotifier
) - [x] get_it 和 get_it_mixin
- [x] states_rebuilder
计划未来还会增加更多方案(欢迎PR贡献)!
未来路线图
- 添加更多屏幕
- 界面优化
如果你希望某些功能被实现,欢迎开启问题讨论(虽然预期不高,毕竟我做这些都是免费的😉)。
其他使用的包
应用“核心”部分使用了以下包:
获取TMDB API 密钥
本项目使用TMDB API获取最新电影数据。
在运行应用之前,你需要先在TMDB网站上注册,然后在设置API页面获取API密钥。
之后,在packages/core/
目录下创建.env
文件,并添加你的密钥:
// .env
TMDB_KEY=your-api-key
然后运行代码生成器:
flutter pub run build_runner build --delete-conflicting-outputs
这将在packages/core/lib/api
目录下生成env.g.dart
文件,用于在向TMDB API发出请求时使用。
恭喜,你现在可以开始了。😊
注意:加载HTTP不安全端点的图像
TMDB API返回的数据指向http而非https的图像URL。为正确加载图片,已进行以下更改:
Android
在android/app/src/main/res/xml
创建名为network_security_config.xml
的文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
接着,在AndroidManifest.xml
的应用标签中添加以下内容:
android:networkSecurityConfig="@xml/network_security_config"
iOS
在ios/Runner/info.plist
中添加以下内容:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
更多信息,请参阅:
macOS
由于macOS应用程序默认处于沙盒模式,如果未添加所需权限,我们将收到SocketException
错误。已在macos/Runner/DebugProfile.entitlements
和macos/Runner/Release.entitlements
中添加了以下内容以解决此问题:
<key>com.apple.security.network.client</key>
<true/>
更多信息,请参阅:
致谢
该项目受到Flutter社区的brianegan/flutter_architecture_samples的启发。
LICENSE: MIT
有兴趣深入理解Flutter状态管理,或者想要打造一款功能丰富的电影应用吗?不要错过这个项目,它提供了多种状态管理工具的实际应用示例,且易于理解和扩展。立即加入,开始您的开发之旅吧!
项目地址:https://gitcode.com/bizz84/movie_app_state_management_flutter