这不是关于具体的实现,而是关于良好的实践。
我在一个flutter桌面项目中有以下结构:
- DataProviders:从两种不同的文件格式之一(本地)读取数据
- Repository:解析数据并实例化我的模型
- projectcube:从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
}
projectcube中的Project实例需要在多个设置(DataTable,简单输入等)中的多个屏幕中进行访问和更改。例如,项目有一个客户,它有一个customerName, customerId等,必须从客户设置屏幕更改。
我想到了两种方法:
- 创建ProjectSettingsCubit, CustomerDataCubit, ProjectDataCubit等,将ProjectCubit作为参数并从那里修改项目
- 一直使用projectcube,并从表示层进行更改
实现这一目标的最佳方法是什么?如果整个结构或Cubit不好,为什么?
感谢任何帮助,谢谢
最佳实践取决于您想要完成什么。如果你想让你的应用在未来扩展,让几个人一起工作,促进更好的可重用性和更好的可测试性,建议将业务逻辑分开。尽可能多地使用UI。因此,直接在表示层中使用逻辑是没有意义的。当您使用cubit时,您会希望在程序中保持一致。尽量让UI和逻辑解耦。
当然,这是有代价的。你需要投入更多的时间。让你的代码比以前更复杂。
关于你的答案,我建议使用ProjectCubit
并根据你的要求实施几个事件,如CustomerChangeEvent
用于改变客户。
如果你有任何特殊的需求,需要在两个页面中以不同的方式实现,那么我建议从一个基类继承,或者只是使用mixin并在不同的腕尺中扩展那个类。
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) {
...
}
}