Flutter状态管理插件data_state_mobx的使用

Flutter状态管理插件data_state_mobx的使用

data_state_mobx 是一个强大的状态机插件,用于 MobX 状态管理。它可以几乎在任何应用程序的状态下使用。它有三种状态:loading(加载中)、success(成功)和 error(错误),非常适合用于无限列表、操作按钮、带有闪烁效果的数据刷新逻辑等。

要求

该包仅适用于 MobX。同时,最低支持的 Dart SDK 版本为 2.16。

开始使用

基本上,你可以在这三种状态下切换以控制你的数据。

  • 在数据加载时,调用:

    dataState.setLoadingState();
    
  • 在成功获取数据时:

    dataState.setSuccessState(data);
    
  • 在发生错误时:

    dataState.setErrorState(error);
    

DataState 会处理其余的事情。

要处理每个状态下的小部件,可以在 Observer 小部件中监听 state 或计算的 getter isLoadingisSuccessisError。例如:

Observer(
  builder: (_) => ElevatedButton(
    child: controller.loginState.isLoading
        ? const CircularProgressIndicator()
        : const Text('Button'),
    onPressed: () {},
  ),
)

或者,你可以使用以下功能。

功能

  • 简单状态
  • 可重载状态
  • 使用 reaction 的状态

简单状态

要处理简单的逻辑,比如显示一个字符串列表。

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](/user/override)
void initState() {
  fetchData();
  //...
  super.initState();
}

[@override](/user/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');
      },
    ),
  ),
}

完整的代码见 这里

可重载状态

当你想在加载小部件回调中使用数据时,可以使用 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');
    },
  ),
);

完整的示例代码见 这里

使用 reaction 的状态

为了在状态改变后仅处理一次,可以使用 handleReactionState 方法。只需在 initState 中设置,并在 dispose 方法中记住清理它。

例如,为了显示一个全屏对话框:

List<ReactionDisposer>? reactionsDisposers;

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

[@override](/user/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();
  }
}

完整的示例代码见 这里

示例代码

import 'package:example/login_sample/login_page.dart';
import 'package:example/reaction_states/reaction_page.dart';
import 'package:example/reloadable_states/reloadable_page.dart';
import 'package:example/simple_states/simple_page.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'DataState Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('DataState'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => const SimpleStatesPage()),
                );
              },
              child: const Text('Simple states'),
            ),
            const SizedBox(height: 8),
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => const ReloadableStatesPage()),
                );
              },
              child: const Text('Reloadable states'),
            ),
            const SizedBox(height: 8),
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => const ReactionPage()),
                );
              },
              child: const Text('States using reaction'),
            ),
            const SizedBox(height: 24),
            const Text('Samples'),
            const SizedBox(height: 8),
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => const LoginPage()),
                );
              },
              child: const Text('Login'),
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter状态管理插件data_state_mobx的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter状态管理插件data_state_mobx的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个使用 data_state_mobx 插件进行 Flutter 状态管理的代码案例。data_state_mobx 并不是 Flutter 官方或广泛使用的状态管理库,但假设它是一个类似于 MobX 的库,这里将展示如何结合 MobX 的概念来实现状态管理。

首先,确保你已经安装了 mobx-dartflutter_mobx 依赖。虽然 data_state_mobx 并不是标准的库,但你可以按照类似的模式来管理状态。

安装依赖

在你的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  mobx: ^2.0.5
  flutter_mobx: ^2.0.3

然后运行 flutter pub get 来安装这些依赖。

创建 Store

接下来,创建一个 store 来管理应用的状态。例如,我们可以创建一个简单的计数器应用。

// counter_store.dart
import 'package:mobx/mobx.dart';

part 'counter_store.g.dart';

class CounterStore = _CounterStore with _$CounterStore;

abstract class _CounterStore with Store {
  @observable
  int count = 0;

  @action
  void increment() {
    count++;
  }

  @action
  void decrement() {
    count--;
  }
}

运行 flutter pub run build_runner build 来生成 MobX 的代码。

使用 Store 在 Flutter 应用中

现在,我们可以使用 CounterStore 在 Flutter 应用中管理状态。

// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'counter_store.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final CounterStore counterStore = CounterStore();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(counterStore: counterStore),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final CounterStore counterStore;

  MyHomePage({required this.counterStore});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Observer(
              builder: (_) => Text(
                'You have pushed the button this many times:',
              ),
            ),
            Observer(
              builder: (_) => Text(
                '${counterStore.count}',
                style: Theme.of(context).textTheme.headline4,
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: counterStore.increment,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}

解释

  1. 创建 Store

    • 使用 @observable 标注可观察的变量。
    • 使用 @action 标注修改这些变量的方法。
  2. 在 Flutter 应用中使用 Store

    • MyApp 中实例化 CounterStore
    • 使用 Observer 组件来监听 Store 的变化并更新 UI。

通过这种方式,你可以使用 data_state_mobx(或类似的 MobX 插件)来管理 Flutter 应用中的状态。希望这个示例对你有所帮助!如果你有任何进一步的问题,请随时询问。

回到顶部