一个强大的状态机,用于 MobX 管理,几乎可以用于任何应用程序状态。

它有3种状态——加载中、成功、错误——非常适合用于无限列表、操作按钮、闪光效果、刷新逻辑等。

特点

要求

此包仅与 MobX 配合使用。最低 Dart SDK 版本为 2.16。

用法

简单状态

用于处理简单的逻辑,例如显示字符串列表。

mobx控制器文件中创建DataState

final dataState = DataState<List<String>>();

Future<void> fetchData() async {
  dataState.setLoadingState();

  try {
    final data = await Future.delayed(const Duration(seconds: 3))
        .then((_) => ['String 1', 'String 2', 'String 3']);
    dataState.setSuccessState(data);
  } catch (e) {
    dataState.setErrorState(e);
  }
}

然后,在视图中添加Observer来展示列表

final controller = ControllerInstance();

@override
void initState() {
  fetchData();
  //...
  super.initState();
}

@override
Widget build(context) {
  //...
  Observer(
    builder: (context) => controller.dataState.handleState(
      loading: () {
        return const CircularProgressIndicator();
      },
      success: (data) {
        return ListView.builder(
          shrinkWrap: true,
          itemCount: data.length,
          itemBuilder: (context, index) => Text(
            data[index],
            textAlign: TextAlign.center,
          ),
        );
      },
      error: (error) {
        return const Text('Error');
      },
    ),
  ),
}

在此处查看完整的代码 here

可重载状态

当您想在加载小部件回调中使用数据时,请使用handleStateLoadableWithData方法。例如,在无限列表或刷新逻辑中。

Observer(
  builder: (context) => controller.dataState.handleStateLoadableWithData(
    loading: (data) {
      return Stack(
        children: [
          if (data != null) list(data),
          Positioned.fill(
            child: Container(
              color: Colors.black45,
              alignment: Alignment.center,
              child: const CircularProgressIndicator()),
          ),
        ],
      );
    },
    success: (data) => list(data),
    error: (error) {
      return const Text('Error');
    },
  ),
);

在此处查看完整的示例代码 here

使用reaction的状态

要仅在状态更改后处理一次状态,handleReactionState是解决方案。只需在initState中设置,并记住在dispose方法中处理它。

例如,显示一个完整的对话框

List<ReactionDisposer>? reactionsDisposers;

@override
void initState() {
  reactionsDisposers = [
    controller.dataState.handleReactionState(
      loading: loadingDialog,
    )
  ];
  super.initState();
}

@override
void dispose() {
  reactionsDisposers?.forEach((dispose) {
    dispose();
  });
  super.dispose();
}

void loadingDialog(bool show) {
  if (show) {
    showDialog(
      barrierDismissible: false,
      context: context,
      builder: (BuildContext context) {
        return Dialog(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: const [
                CircularProgressIndicator(),
                SizedBox(width: 32),
                Text("Loading"),
              ],
            ),
          ),
        );
      },
    );
  } else {
    Navigator.of(context).pop();
  }
}

在此处查看完整的示例代码 here

GitHub

查看 Github