图鉴

这项任务相当有趣。和所有项目一样,我首先了解了这款应用的应用范围和状态。

我决定使用干净架构来构建应用。我分阶段构建了应用:UI -> Domain -> Data

对于像这样的一个小项目,我认为使用状态管理库可能有点大材小用,所以我使用了Flutter提供的功能:ChangeNotifiersInheritedWidget

Demo

结构

项目的示例结构如下所示

integration_test/
    |- app_test.dart
    |- custom_finders_matchers.dart
    |- detail_screen_test_cases.dart
    |- home_screen_test_cases.dart
    |
lib/
    |- data
    |  |- entity_mapper.dart
    |  |- models
    |  |- data_sources
    |  |_repository_impl.dart
    |
    |- domain
    |  |- pokemon_entity.dart
    |  |_ repository_base.dart
    |
    |- presentation
    |  |- widgets
    |  |  |_ widget_export.dart
    |  |
    |  |_ data_controllers.dart
    |  |_ data_provider.dart
    |  |_ detail_screen.dart
    |  |_ home_screen.dart
    |
    |- util
    |   |- colors.dart
    |   |- extensions.dart
    |   |- icon_util.dart
    |   |_util_export.dart
    |
    |_ main.dart

展示层包含所有与UI相关的代码,包括UI逻辑。该层依赖于领域层。

领域层是展示层和数据层之间的桥梁。由于展示层只能与该层通信。基础存储库、实体(PokemonEntity)和实体映射器在此定义。PokemonEntity是一个简单的数据类,包含特定的UI相关字段。它对服务器返回的实际数据格式一无所知。映射器类用于将数据模型映射到实体类。

数据层包含所有业务逻辑。它是任何数据相关任务的骨干。它包含解析JSON对象的模型数据类、存储库的实现、数据源和本地数据源。

util文件夹包含应用程序中使用的实用程序,例如颜色、扩展等。

使用的包

使用的依赖项如下所示

  • Google fonts:此包用于应用程序的Noto Sans字体。
  • Shimmer:加载效果由此包处理。
  • Equatable:方便实现不同对象类型的基于值的相等性。
  • Flutter SVG:用于显示网络SVG图像URL。
  • Either Dart:为错误处理提供无缝、高效的方式。
  • GraphQL:用于与pokemon GraphQL API交互。其中还包括一个内部Hive本地存储实现。

    要了解为什么此项目同时包含graphql和dio,请向下滚动并点击此处

  • Path Provider:
  • Dio:用于与pokemon RESTful API交互。

    要了解为什么此项目同时包含graphql和dio,请向下滚动并点击此处

  • Path Provider:由Hive包使用,以在设备上获取本地存储路径。

开发依赖项

  • 集成测试:一个用于在真实设备或模拟器上运行集成测试的包。
  • Mocktail:用于模拟代码的某些部分以进行单元测试。

为什么同时实现GraphQL和RESTful

您可能想知道,为什么同一个应用程序会同时实现DioGraphQL?原因很简单:我注意到pokemon有一个graphql API,它仍处于beta阶段。基于我使用GraphQL的经验及其提供的灵活性,我决定采用它。

一切进展顺利,直到我收到坏消息。几天后,我尝试对我的应用程序进行测试运行,却收到了服务器宕机错误。那时,我回想起“不要使用仍处于beta阶段的资源,至少不要用于生产”的明智建议。尽管面临这一挑战,但曙光就在眼前。

该项目结构灵活。它允许轻松切换数据源。在完成REST API的设置后,我认为保留这两种实现会很酷。

要从REST API切换到GraphQL API,请前往lib/main.dart第15行,并用以下代码替换:

final dataSource = GraphQlDataSource();

现在应用程序使用的是GraphQL API的数据。

要了解更多GraphQL提供的灵活性,这是我写的一篇关于此主题的文章:GraphQL文章

测试

编写测试有时可能很痛苦。对我来说,编写这些测试用例是一种苦乐参半的经历,但它是值得的。不过,我认为测试是软件开发不可或缺的一部分。我致力于编写单元测试小部件测试。此外,集成测试甚至比单元测试和小部件测试更好。

集成测试确保了完整或大部分应用程序的多个组件(小部件、状态持有者、存储库)按预期协同工作,而单元测试和小部件测试则确保单个组件/部分协同工作。

我专注于为应用程序编写集成测试,这就是为什么单元测试用例很少,也没有小部件测试用例。集成测试覆盖了大部分内容。要运行此带覆盖率的集成测试,请使用以下命令。

flutter test integration_test/app_test.dart --coverage

我编写了一些单元测试用例,以确保GraphQlDataSourceRepositoryImpl按预期工作。要运行这些带覆盖率的测试用例,请使用以下命令。

flutter test --coverage

感谢您花时间审阅我的项目。我希望这篇文字能为您在查看代码库时提供所需的见解。

GitHub

查看 Github