【问题标题】:Flutter bloc architecture designFlutter 块架构设计
【发布时间】:2021-10-22 20:26:24
【问题描述】:

这不是关于具体实施,而是更多关于良好实践。

我在一个flutter桌面项目中有如下结构:

  • DataProviders:从两种不同文件格式之一读取数据(本地)
  • 存储库:解析数据并实例化我的模型
  • ProjectCubit:从 FilePicker 获取路径并从上 2 层获取项目

ProjectCubit.dart:

class ProjectCubit extends Cubit<ProjectState> {
  ProjectCubit() : super(ProjectState.Closed);

  Project? loadedProject;

  Project? getProject() {
    // return loaded instance of Project if loaded
    if(loadedProject != null)
      return loadedProject;
  }

  // creates Project instance from csv file
  void importProject(String filePath) async {
    emit(ProjectState.Importing);
    loadedProject = await ProjectRepository().loadData(loadType: ProjectLoadType.IMPORT_FROM_CSV, filePath: filePath);
    emit(ProjectState.Open);
  }

  // open json-Project file 
  void openProject(String filePath) async {
    emit(ProjectState.Opening);
  try {
      loadedProject = await ProjectRepository().loadData(loadType: ProjectLoadType.OPEN_PROJECT_FILE, filePath: filePath);
    } catch (e) {
      emit(ProjectState.Closed);
      Log().l.e("Opening file failed with ${e.toString()}");
    }
    emit(ProjectState.Open);
  }
}

状态在哪里:

enum ProjectState {
  Closed,
  Importing,
  Opening,
  Open
}

ProjectCubit 中的项目实例需要在多个设置(数据表、简单输入等)的多个屏幕上进行访问和更改。例如,Project 有一个 Customer,它有一个 customerName、customerId 等,必须从 Customer-Settings 屏幕进行更改。

我想到了两种方法:

  • 创建一个 ProjectSettingsCubit、CustomerDataCubit、ProjectDataCubit 等,它们将 ProjectCubit 作为参数并从那里修改项目
  • 一直使用 ProjectCubit 并从表示层进行更改

实现这一目标的最佳方法是什么?如果整个结构或 Cubit 不好,为什么?

不胜感激,谢谢

【问题讨论】:

    标签: flutter dart desktop bloc cubit


    【解决方案1】:

    最佳做法取决于您想要完成的任务。 如果您希望您的应用程序在未来扩展,让几个人一起工作,以促进更好的可重用性和更好的可测试性,建议尽可能将业务逻辑和 UI 分开。因此,直接在表示层中有逻辑是没有意义的。当您使用 cubit 时,您会希望在您的程序中保持一致并尽可能地让 UI 和逻辑解耦。

    这当然是有代价的。您需要投入更多时间并使您的代码比以前更复杂。

    至于您的答案,我建议使用ProjectCubit 并根据您的要求实施几个事件,例如CustomerChangeEvent 用于更改客户。

    如果您有任何特殊要求需要在两个页面中以不同方式实现,那么我建议从基类继承或仅使用 mixin 并将该类扩展为不同的 cubits。

    class BaseProjectCubit extends Cubit<ProjectState> {
      void importProject(String filePath) async {
        emit(ProjectState.Importing);
        loadedProject = await ProjectRepository().loadData(loadType: 
      ProjectLoadType.IMPORT_FROM_CSV, filePath: filePath);
        emit(ProjectState.Open);
      }
    ...
    }
    
    class ProjectCubitA extends BaseProjectCubit {
      @override
      void importProject(String filePath) async {
    
        ...
      }
    }
    
    class ProjectCubitB extends BaseProjectCubit {
      importProject(String filePath) async {
        ...
      }
    }
    

    或者对于使用 mixins,它会是这样的:

    mixin ProjectModifier {
      void importProject(String filePath) async {
        emit(ProjectState.Importing);
        loadedProject = await ProjectRepository().loadData(loadType: 
      ProjectLoadType.IMPORT_FROM_CSV, filePath: filePath);
        emit(ProjectState.Open);
      }
    ...
    }
    
    class CustomerTypeOneProjectCubit extends Cubit<ProjectState> with ProjectModifier {
      changeName(String newName) {
        ...
      }
    }
    
    class CustomerTypeTwoProjectCubit extends Cubit<ProjectState> with ProjectModifier {
      changeName(String newName) {
        ...
      }
    }
    

    【讨论】:

    • 非常感谢,但是,如果我使用 mixin 或 Baseclass 子类模型,我将如何让它们共享同一个 Project 实例?现在我基本上调用 openProject() 一次,并且需要为其他肘的所有操作创建的实例。
    • 我刚刚创建了一个 ProjectSettingsCubit,它似乎可以工作。谢谢!
    • 我明白了。如果要共享项目实例,可以将项目用作基类中的静态字段。或者正如您自己所说,分享projectCubit 本身。
    • 我真的很困惑,因为我认为它会按值传递,而不是按引用传递,并且在使用 Project 而不是 ProjectCubit 时我只会编辑一个副本,但它似乎工作,得看看Dart 如何再次传递变量
    猜你喜欢
    • 2010-09-28
    • 1970-01-01
    • 2011-11-18
    • 2012-09-17
    • 2016-06-22
    • 2020-07-24
    • 2012-08-25
    • 2011-05-25
    • 1970-01-01
    相关资源
    最近更新 更多