ExotikArch – Flutter setState 性能增强⚡

ExotikArch for Flutter。使用Flutter快速交付生产应用。

  • 全局状态管理
  • 导航服务
  • 辅助小部件,例如加载器和处理器。
  • 无缝异常处理,无需重复代码
  • 支持Isolates以卸载API调用。

*注意

目前,ExotikArch以这个应用项目的形式存在。如果这个项目能获得足够的关注,我将把它打包并发布到pubdev上。

运行它

flutter run

模块

状态管理

ExotikArch使用内置的setState函数来处理全局状态管理。它设计用于与MVC模式良好配合。我们创建控制器来处理业务逻辑。要构建一个简单的控制器,只需将其扩展为ExoController

import 'package:exotik_todos_app/exotik_arch/exotik_arch.dart';

class TodosController extends ExoController<TodosRetainer> {

  void Function(void Function() fn)? setState;
  TodosRetainer? retainer;

  TodosController(
    this.setState,
    {
      TodosRetainer?initRetainer
    }
  ) : super(
    setState,
    initRetainer: initRetainer ?? TodosRetainer()
  );

  void dispose() async {
    super.dispose();
  }

}

ExoController接受一个泛型类型,该类型将作为控制器数据的模型。例如,在TodosController的情况下,这个TodosRetainers引用定义为,

class TodosRetainer {

  late List<Todo> todosList;

  TodosRetainer(){
    todosList = [];
  }

}

按照约定,将retainer引用保存在与控制器相同的文件中。要从UI调用控制器,请使用此语法,

  late TodosController todosController;

  @override
  void initState() {

    todosController = TodosController(
      this.setState,
      initRetainer: anaGlobalRetainers.todosRetainer
    );

    super.initState();
  }

请注意,将一个initRetainer传递给了TodosContoller构造函数。这就是全局状态支持的方式。所有全局retainer都放在一个AnaGlobalRetinaters引用中,并在需要时传递给控制器。如果传递了initRetainer,则控制器将使用现有状态进行初始化,从而产生全局状态效果。

导航服务

随时随地导航。只需使用,

import 'package:exotik_todos_app/exotik_arch/exotik_arch.dart';

ExoNavService.push(
    MainPage()
);

辅助小部件

ExotikArch附带2个主要辅助小部件。它们基于一个非常简单的想法构建。几乎90%的应用只做两件事。它们加载并显示数据。或者它们将数据提交给服务器并等待响应。ExotikArch分别将它们视为数据加载和过程处理。要加载数据,有一个名为ExoDataLoader的辅助小部件。它接受ExoControler的引用。并且每当控制器处于加载状态时,它都会自动渲染一个加载指示器,并在数据渲染完成后停止。

我们将逻辑暴露在控制器中,UI会自动更新。

Future<void> getTodos({
    bool reload = true
}) async {

    try {

      if(!reload){
        if(retainer!.todosList.isNotEmpty){
          return;
        }
      }

      List<Todo> _todosList;

      exoDataLoaderHelper.startLoading(); // Start Data Loader

      _todosList = await apiInterface.getTodos();

      exoDataLoaderHelper.stopLoading(); // Stop Data Loader

      if(_todosList != null){
        retainer!.todosList = _todosList;
      }

    } on ExoException catch (e, s){

      exoDataLoaderHelper.showError(e); // Handle Error Messages

      return null;

    }

    return;

}

进程也是如此。有一个ExoProcessHandler,它将显示一个叠加的加载指示器,并在进程完成后停止它。

Future<bool> login(
    String email,
    String password,
    {
      bool rememberMe: true
    }
) async {

    try{

      AppUser? _appUser;

      exoProcessHandlerHelper.startLoading(); // Start Process Loader

      _appUser = await apiInterface.logIn(
        email,
        password,
      );

      exoProcessHandlerHelper.stopLoading(); // Stop Process Loader

      appUser = _appUser;

      if(appUser != null){
        if(rememberMe){
          appUser?.cache();
        }
        return true;
      } else {
        return false;
      }

    } on ExoException catch (e, s){

      exoProcessHandlerHelper.showError(e); // Handle Error Messages

      return false;

    }

}

ExoDataLoaderExoProcessHandler的调用方式与常规小部件一样,

@override
  Widget build(BuildContext context) {
    return ExoProcessHandler(
      exoProcessHandlerHelper: todosController.exoProcessHandlerHelper,
      child: Container(),
    );
  }

@override
  Widget build(BuildContext context) {
    return ExoProcessHandler(
      exoProcessHandlerHelper: authController.exoProcessHandlerHelper,
      child: Container()
    );
}

异常处理

ExotikArch有一个内置机制来在内部处理所有异常。这通过控制器和小部件工作。所有异常都被解析到一个单一类ExoException中,该类有一个friendlyErrorMessage字段。当ExoProcessHandlerExoDataLoader小部件出现问题时,此消息会自动显示。闪信会构造并提示给用户。

工作卸载 – 支持Isolates

Isolates支持目前非常基础。我们为此使用内置的compute()函数。它将生成Isolates,在其中发出网络请求,然后将其注销。实现可以在api_interface.dart文件中找到。

      ComputeRequest computeRequest = ComputeRequest(
        requestURL,
        RequestType.POST,
        body: body,
      );

      CDioResponse<Map<String, dynamic>> response = await compute<ComputeRequest, CDioResponse<Map<String, dynamic>>>(
        cRequest,
        computeRequest
      ); // Execute the network request With Isolate

      CDioResponse<Map<String, dynamic>> response = await cRequest(
        computeRequest
      ); // Execute the Network Request WithOut Isolate

贡献

欢迎 Pull requests。对于重大更改,请先打开一个 issue 来讨论您想进行的更改。

许可证

MIT

GitHub

查看 Github