Flutter状态可视化插件state_view的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter状态可视化插件state_view的使用

State View 是一个 Dart 包,提供了一组用于在 Flutter 应用中实现状态视图模式的小部件和模式。该模式旨在将应用程序状态与 UI 逻辑分离,使代码组织更加清晰和易于维护。

安装

要使用 State View 包,首先需要将其添加到你的 Flutter 项目中:

dart pub add state_view

安装创建页面脚本

为了使用 State View 包的创建页面脚本,你需要先激活系统上的脚本。打开终端并运行以下命令:

dart pub global activate state_view

确保将 Dart 包可执行文件添加到系统的 PATH 中。在 MacOS / Linux 上,可以通过在 ~/.zshrc 文件中添加以下行来实现(假设 zsh 是默认 shell):

export PATH="$PATH:~/.pub-cache/bin"

在 Windows 上,可以通过将以下内容添加到用户的 PATH 环境变量中来实现:

%LOCALAPPDATA%\Pub\Cache\bin

创建页面

状态视图模式需要一定量的样板代码。为了简化这个过程,包提供了一个脚本,可以自动为新页面创建必要的文件和文件夹。

要创建新页面,请导航到你想要创建它的文件夹(例如 /lib/pages/),然后运行脚本,提供页面名称(以蛇形命名法):

create_page some_new_page

脚本会自动将页面名称转换为帕斯卡命名法用于实际类名。

示例

随着 Flutter 应用的增长,在单个文件中使用 StatefulWidget 来管理业务逻辑、状态和 UI 逻辑可能会变得笨重。State View 包通过提供业务逻辑/状态与 UI 逻辑之间的干净分离来解决这个问题。

状态视图模式主要有三个组件:

  • 页面:将状态和 UI 结合在一起的小部件。
  • StateProvider:保存业务逻辑和状态,并响应 UI 事件。
  • UI:保存 UI 逻辑并发出 UI 事件。

代码示例

让我们看一个如何使用这些组件的示例:

import 'package:flutter/material.dart';
import 'package:state_view/state_view.dart';

class HomePage extends StateView<HomeState> {
  HomePage({Key? key})
    : super(
      key: key,
      stateBuilder: (context) => HomeState(context),
      view: HomeView(),
  );
}

class HomeState extends StateProvider<HomePage, HomeEvent> {
  HomeState(super.context) {
    registerHandler<OnSaveButtonTap>(_handleSave);
  }

  void _handleSave(OnSaveButtonTap event) {
    // 处理保存逻辑
  }
}

abstract class HomeEvent {}

class OnSaveButtonTap extends HomeEvent {}

在这个示例中,HomePage 作为 HomeState(业务逻辑)和 HomeView(UI)之间的粘合剂。HomeState 注册一个或多个处理程序来处理每个事件,这充当了业务逻辑和 UI 之间的接口。UI 小部件通过调用 emit 并发出特定事件与 HomeState 进行交互。这种分离增强了应用扩展时的可读性和可维护性。

事件

为了保持 HomeState.emit 函数的类型安全,建议为每个创建的 StateProvider 定义一个抽象类。每个 UI 事件应表示为扩展此抽象事件类的类。你还可以在这些事件类中包含任何必要的数据。

例如:

abstract class HomeEvent {}

class OnSaveButtonTap extends HomeEvent {}

class OnUserNameChanged extends HomeEvent {
    final String newUsername;
    OnUserNameChanged(this.newUsername);
}

这是 UI 如何使用这些事件的方式:

class HomeView extends StatelessWidget {
  const HomeView({super.key});

  @override
  Widget build(BuildContext context) {
    final state = context.read<HomeState>();
    return Scaffold(
      body: Column(
        children: [
          TextField(
            onChanged: (String value) {
              state.emit(OnUserNameChanged(value));
            },
          ),
          TextButton(
            child: Text('Save'),
            onPressed: () {
              state.emit(OnSaveButtonTap());
            },
          ),
        ],
      ),
    );
  }
}

onEvent

或者,你可以覆盖 onEvent 函数并在状态提供者上调用 onEvent 提供事件。

例如:

class HomeState extends StateProvider<HomePage, HomeEvent> {
  HomeState(super.context);

  @override
  void onEvent(HomeEvent event) {
    if (event is OnSaveButtonTap) {
      _handleSave(event);
    }
  }

  void _handleSave(OnSaveButtonTap event) {
    // 处理保存逻辑
  }
}

然后从 UI 调用:

context.read<HomeState>().onEvent(OnSaveButtonTap());

这是一种较旧的方法来发出事件,不推荐使用,因为通常会在 onEvent 函数中添加额外的逻辑,而不仅仅是分配处理程序。但这在功能上与 registerHandler / emit 模式相同。

MultiProvider

StateProvider 小部件不能直接在 MultiProvider 中使用。但是,你可以使用 ViewlessStateProvider,它几乎相同,但可以在 MultiProvider 中使用。

完整示例 Demo

以下是一个完整的示例 demo,展示了如何使用 state_view 包:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:state_view/state_view.dart';

void main() => runApp(
  MaterialApp(
    home: HomePage(initialUsername: 'test_username'),
  ),
);

class HomePage extends StateView<HomeState> {
  final String initialUsername;
  HomePage({
    Key? key,
    required this.initialUsername,
  }) : super(
    key: key,
    stateBuilder: (context) => HomeState(context),
    view: const HomeView(),
  );
}

class HomeState extends StateProvider<HomePage, HomeEvent> {
  HomeState(BuildContext context) : super(context) {
    _username = widget.initialUsername;
  }

  late String _username;
  String get username => _username;

  @override
  void onEvent(HomeEvent event) {
    if (event is OnUserNameChanged) {
      _username = event.newUsername;
      notifyListeners();
    }
  }
}

abstract class HomeEvent {}

class OnUserNameChanged extends HomeEvent {
  final String newUsername;
  OnUserNameChanged(this.newUsername);
}

class HomeView extends StatelessWidget {
  const HomeView({super.key});

  @override
  Widget build(BuildContext context) {
    final state = context.watch<HomeState>();
    return Scaffold(
      appBar: AppBar(title: Text('Home Page')),
      body: Column(
        children: [
          Text('Current username: ${state.username}'),
          TextField(
            onChanged: (String value) {
              state.onEvent(OnUserNameChanged(value));
            },
          ),
        ],
      ),
    );
  }
}

以上代码展示了如何结合使用 state_view 包中的不同组件来构建一个简单的 Flutter 应用。希望这对你的开发有所帮助!


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

1 回复

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


当然,以下是一个关于如何在Flutter应用中使用state_view插件进行状态可视化的代码示例。state_view插件允许开发者在开发过程中直观地查看Widget的状态,这对于调试和理解应用状态流非常有帮助。

首先,确保你已经在pubspec.yaml文件中添加了state_view依赖:

dependencies:
  flutter:
    sdk: flutter
  state_view: ^latest_version  # 请替换为最新的版本号

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

接下来,我们来看一个具体的代码示例,展示如何使用StateView来可视化Widget的状态。

import 'package:flutter/material.dart';
import 'package:state_view/state_view.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter StateView Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter StateView Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            StateView(  // 使用StateView包裹状态相关的Widget
              title: 'Counter State',
              data: _counter,
              child: ElevatedButton(
                onPressed: _incrementCounter,
                child: Text('Increment'),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // 这个按钮没有使用StateView,只是为了展示另一种交互方式
    );
  }
}

在这个示例中,我们创建了一个简单的计数器应用,并在其中一个按钮上使用了StateViewStateView有三个主要参数:

  1. title: 用于显示状态视图的标题。
  2. data: 要显示的状态数据。这里我们传递的是计数器的值_counter
  3. child: 要包裹的Widget,这里是一个ElevatedButton

当你运行这个应用并点击按钮时,StateView会在屏幕上显示当前计数器的值,从而帮助你可视化Widget的状态。

请注意,state_view插件主要用于开发调试阶段,不建议在生产环境中使用,因为它会在UI中引入额外的调试信息。

回到顶部