Flutter数据监听插件value_listenables的使用

Flutter数据监听插件value_listenables的使用

本文将介绍如何使用 value_listenables 插件来管理状态并监听数据变化。通过结合 ControllerValueListenable,我们可以轻松实现数据驱动的 UI 更新。


插件说明

value_listenables 是一个用于管理状态的插件,它通过 ControllerValueListenable 提供了强大的数据监听功能。以下是它的主要特点:

  • 声明式编程:通过定义 ValueListenable,可以自动监听数据的变化。
  • 可组合性:支持复杂的依赖关系和数据绑定。
  • 生命周期管理:自动处理 dispose,避免内存泄漏。

示例代码解析

以下是一个完整的示例代码,展示如何使用 value_listenables 插件来管理状态并更新 UI。

示例代码

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:value_listenables/value_listenables.dart';

// 定义一个控制器类,继承自 ControllerBase
class TextController extends ControllerBase<TextController> {
  // 定义一个 ValueNotifier,并通过 view() 方法获取 ValueListenable
  final rawA = ValueNotifier(1);
  ValueListenable<String> get aString => rawA.view().map((e) => e.toString());

  // 定义另一个 ValueNotifier,并通过 view() 方法获取 ValueListenable
  final b = TextEditingController(text: 'b');
  ValueListenable<String> get bString => b.view().map((e) => e.text);

  // 定义第三个 ValueNotifier,并通过 view() 方法获取 ValueListenable
  final rawC = ValueNotifier(2.0);
  ValueListenable<String> get cString => rawC.view().map((e) => e.toString());
  ValueListenable<Text> get cText => cString.map(Text.new);

  // 定义一个 Slider 的 ValueListenable
  ValueListenable<Slider> get cSlider => rawC.view().map(
        (e) => Slider(
          value: e,
          min: 0,
          max: 3,
          onChanged: (v) => rawC.value = v,
        ),
      );

  // 定义一个复杂的 ValueListenable,包含多个依赖
  ValueListenable<String> get text =>
      aString.view().bind((a) => bString.view().bind((b) => c.view().map((c) => '$a, $b, $c')));

  ValueListenable<Text> get textWidget => text.map(Text.new);

  // 增加 A 的值
  void incrementA() => rawA.value = rawA.value + 1;

  // 减少 A 的值
  void decrementA() => rawA.value = rawA.value - 1;

  // 初始化方法
  void init() {
    print("init");
    super.init();
  }

  // 销毁方法
  void dispose() {
    print("dispose");
    b.dispose();
    rawC.dispose();
    super.dispose();
  }
}

// 主页面
void main() => runApp(MaterialApp(
      home: Home(),
    ));

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Example'),
      ),
      body: ControllerInjectorBuilder<TextController>(
        // 使用 ControllerInjectorBuilder 注入控制器
        factory: (context) => ControllerBase.create(() => TextController()),
        builder: (context, controller) => Body(
          controller: controller,
        ),
      ),
    );
  }
}

// 页面主体
class Body extends ControllerWidget<TextController> {
  const Body({
    Key? key,
    required ControllerHandle<TextController> controller,
  }) : super(key: key, controller: controller);

  @override
  Widget build(ControllerContext<TextController> context) {
    return Column(
      children: [
        SizedBox(height: 24),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: controller.textWidget.build(), // 使用 build() 方法生成 Text 小部件
        ),
        SizedBox(height: 16),
        TextField(
          controller: controller.b, // 绑定 TextField 控制器
        ),
        SizedBox(height: 16),
        Expanded(
          child: ListView(
            padding: EdgeInsets.symmetric(horizontal: 16),
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  TextButton(
                    onPressed: controller.incrementA, // 按钮绑定 incrementA 方法
                    child: Text('+'),
                  ),
                  controller.aText.build(), // 使用 build() 方法生成 Text 小部件
                  TextButton(
                    onPressed: controller.decrementA, // 按钮绑定 decrementA 方法
                    child: Text('-'),
                  ),
                ],
              ),
              Text('C:'),
              controller.cText.build(), // 使用 build() 方法生成 Text 小部件
              controller.cSlider.build(), // 使用 build() 方法生成 Slider 小部件
            ],
          ),
        ),
        SizedBox(height: 24),
      ],
    );
  }
}

代码详解

1. 定义控制器类

TextController 中,我们定义了多个 ValueNotifier,并通过 view() 方法获取 ValueListenable。这些 ValueListenable 可以直接用于构建 UI 或与其他小部件绑定。

关键方法:

  • incrementA()decrementA():用于更新 rawA 的值。
  • init()dispose():分别用于初始化和销毁资源。

2. 使用 ControllerInjectorBuilder

ControllerInjectorBuilder 用于注入 TextController,并在上下文中提供对控制器的访问。

ControllerInjectorBuilder<TextController>(
  factory: (context) => ControllerBase.create(() => TextController()),
  builder: (context, controller) => Body(controller: controller),
)

3. 构建 UI

Body 类中,我们通过 controller 访问 TextController 的各种 ValueListenable,并使用 build() 方法动态生成小部件。

Padding(
  padding: const EdgeInsets.all(8.0),
  child: controller.textWidget.build(),
)

4. 动态绑定数据

通过 bind() 方法,我们可以将多个 ValueListenable 组合在一起,形成更复杂的依赖关系。例如:

ValueListenable<String> get text =>
    aString.view().bind((a) => bString.view().bind((b) => c.view().map((c) => '$a, $b, $c')));

更多关于Flutter数据监听插件value_listenables的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据监听插件value_listenables的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,ValueListenable 是一个用于监听数据变化的接口,通常与 ValueNotifier 一起使用。ValueListenable 允许你在数据发生变化时自动更新UI,而不需要手动调用 setState

1. 使用 ValueNotifierValueListenableBuilder

ValueNotifier 是一个简单的类,它持有一个值,并在值发生变化时通知监听器。ValueListenableBuilder 是一个小部件,它监听 ValueListenable 并在值发生变化时重建其子部件。

示例代码:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('ValueListenable Example')),
        body: CounterWidget(),
      ),
    );
  }
}

class CounterWidget extends StatefulWidget {
  [@override](/user/override)
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  // 创建一个 ValueNotifier,初始值为 0
  final ValueNotifier<int> _counter = ValueNotifier<int>(0);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // 使用 ValueListenableBuilder 监听 _counter 的变化
          ValueListenableBuilder<int>(
            valueListenable: _counter,
            builder: (context, value, child) {
              return Text(
                'Counter: $value',
                style: Theme.of(context).textTheme.headline4,
              );
            },
          ),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              // 增加计数器的值
              _counter.value++;
            },
            child: Text('Increment'),
          ),
        ],
      ),
    );
  }

  [@override](/user/override)
  void dispose() {
    // 释放资源
    _counter.dispose();
    super.dispose();
  }
}
回到顶部