Flutter事件监听插件katana_listenables的使用

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

Flutter事件监听插件katana_listenables的使用

简介

在创建Flutter小部件时,您可能需要管理多个TextEditingControllerValueNotifier以及其他继承自ChangeNotifier的控制器。通常情况下,您需要在State中定义多个ChangeNotifier继承类,或者创建一个继承自ChangeNotifier的类用于状态管理,并为所有监听器添加addListener

为了简化上述实现,katana_listenables插件提供了一种更简单的方式来创建继承自ChangeNotifier的类,并通过传递继承自ChangeNotifier的对象来监控其参数。当被监控的ChangeNotifier发生更改时,更改会传播到其自身对象。

例如,以下代码展示了如何使用katana_listenables

[@listenables](/user/listenables)
class ControllerGroup with _$ControllerGroup, ChangeNotifier {
  factory ControllerGroup({
    required TextEditingController emailTextEditingController,
    required TextEditingController passwordTextEditingController,
    required FocusNode focusNode,
    ValueNotifier<bool> checkTerms,
  }) = _ControllerGroup;
}

当您运行build_runner时,会自动生成一个继承自ChangeNotifier(Listenable)的类。如果您将此加载到riverpod中,例如:

final controllerProvider = ChangeNotifierProvider((_) {
  return ControllerGroup(
    emailTextEditingController: TextEditingController(),
    passwordTextEditingController: TextEditingController(),
    focusNode: FocusNode(),
    checkTerms: ValueNotifier(false),
  );
});

class TestPage extends ConsumerWidget {
  [@override](/user/override)
  Widget build(BuildContext context, WidgetRef ref) {
    final controller = ref.watch(controllerProvider);

    // 当controller中的emailTextEditingController内容更新时,controller也会收到更改通知并更新小部件
    controller.emailTextEditingController.text = "New Text";

    return Scaffold(
      appBar: AppBar(title: Text("Test Page")),
      body: Center(
        child: TextField(
          controller: controller.emailTextEditingController,
        ),
      ),
    );
  }
}

安装

要使用katana_listenables,您需要导入以下包以进行代码生成:

flutter pub add katana_listenables
flutter pub add --dev build_runner
flutter pub add --dev katana_listenables_builder

实现

创建类

创建一个类如下所示:

  1. 添加part '(filename).listenable.dart';
  2. 使用[@listenables](/user/listenables)注解定义的类,并混入_$(定义的类名)ChangeNotifier
  3. factory中创建构造函数,并定义您想要使用的继承自ChangeNotifierListenable的类作为参数。
  4. 在构造函数后写上= _ (定义的类名)

示例代码:

// controller.dart

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

part 'controller.listenable.dart';

[@listenables](/user/listenables)
class ControllerGroup with _$ControllerGroup, ChangeNotifier {
  factory ControllerGroup({
    required TextEditingController emailTextEditingController,
    required TextEditingController passwordTextEditingController,
    required FocusNode focusNode,
    ValueNotifier<bool> checkTerms,
  }) = _ControllerGroup;
}

代码生成

通过输入以下命令进行自动代码生成:

flutter pub run build_runner build --delete-conflicting-outputs

使用方法

由于创建的类继承自ChangeNotifier,因此可以像普通ChangeNotifier一样使用它。

在State中使用
class TestPage extends StatefulWidget {
  [@override](/user/override)
  State<StatefulWidget> createState() => TestPageState();
}

class TestPageState extends State<TestPage> {
  final controller = ControllerGroup(
    emailTextEditingController: TextEditingController(),
    passwordTextEditingController: TextEditingController(),
    focusNode: FocusNode(),
    checkTerms: ValueNotifier(false),
  );

  [@override](/user/override)
  void initState() {
    super.initState();
    controller.addListener(_handledOnUpdate);
  }

  void _handledOnUpdate() {
    setState(() {});
  }

  [@override](/user/override)
  void dispose() {
    super.dispose();
    controller.removeListener(_handledOnUpdate);
    controller.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Test Page")),
      body: Center(
        child: TextField(
          controller: controller.emailTextEditingController,
        ),
      ),
    );
  }
}
在Riverpod中使用
final controllerProvider = ChangeNotifierProvider((_) {
  return ControllerGroup(
    emailTextEditingController: TextEditingController(),
    passwordTextEditingController: TextEditingController(),
    focusNode: FocusNode(),
    checkTerms: ValueNotifier(false),
  );
});

class TestPage extends ConsumerWidget {
  [@override](/user/override)
  Widget build(BuildContext context, WidgetRef ref) {
    final controller = ref.watch(controllerProvider);

    // 当controller中的emailTextEditingController内容更新时,controller也会收到更改通知并更新小部件
    controller.emailTextEditingController.text = "New Text";

    return Scaffold(
      appBar: AppBar(title: Text("Test Page")),
      body: Center(
        child: TextField(
          controller: controller.emailTextEditingController,
        ),
      ),
    );
  }
}

额外用法

添加方法

要添加方法,使用以下写作风格:

// controller.dart

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

part 'controller.listenable.dart';

[@listenables](/user/listenables)
class ControllerGroup with _$ControllerGroup, ChangeNotifier {
  factory ControllerGroup({
    required TextEditingController emailTextEditingController,
    required TextEditingController passwordTextEditingController,
    required FocusNode focusNode,
    ValueNotifier<bool> checkTerms,
  }) = _ControllerGroup;
  ControllerGroup._(); // 额外要求

  bool get checked => checkTerms?.value ?? false;

  void someMethod() {
    // 方法实现
  }
}

完整示例Demo

以下是一个完整的示例,展示了如何使用katana_listenables插件:

// Dart imports:
import 'dart:math';

// Flutter imports:
import 'package:flutter/material.dart';

// Package imports:
import 'package:katana_listenables/katana_listenables.dart';

part 'main.listenable.dart';

[@listenables](/user/listenables)
class ListenableValue with _$ListenableValue, ChangeNotifier {
  factory ListenableValue({
    required TextEditingController controller,
    ValueNotifier<String> value,
  }) = _ListenableValue;
  ListenableValue._();

  void get() {}
}

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

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

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

class ListenablePage extends StatefulWidget {
  const ListenablePage({super.key});

  [@override](/user/override)
  State<StatefulWidget> createState() => ListenablePageState();
}

class ListenablePageState extends State<ListenablePage> {
  final listenable = ListenableValue(
    controller: TextEditingController(text: "before click"),
    value: ValueNotifier("0"),
  );

  [@override](/user/override)
  void initState() {
    super.initState();
    listenable.addListener(() {
      setState(() {});
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Flutter Demo")),
      body: ListView(
        children: [
          ListTile(
            title: Text(listenable.controller.text),
            onTap: () {
              listenable.controller.text = "after click";
            },
          ),
          ListTile(
            title: Text(listenable.value?.value ?? ""),
            onTap: () {
              listenable.value?.value = Random().nextInt(100).toString();
            },
          )
        ],
      ),
    );
  }
}

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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用katana_listenables插件进行事件监听的示例代码。katana_listenables是一个允许在Flutter应用中轻松创建和监听全局事件的插件。

首先,你需要在你的pubspec.yaml文件中添加katana_listenables依赖:

dependencies:
  flutter:
    sdk: flutter
  katana_listenables: ^最新版本号  # 请替换为实际的最新版本号

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

接下来,我们来看一个具体的代码示例。

1. 创建一个事件类

首先,我们需要定义一个事件类。这个类可以包含任何你想传递的数据。

// event.dart
class MyCustomEvent {
  final String message;

  MyCustomEvent({required this.message});
}

2. 设置事件监听器

在你的主应用文件(通常是main.dart)中,设置事件监听器。

import 'package:flutter/material.dart';
import 'package:katana_listenables/katana_listenables.dart';
import 'event.dart';

void main() {
  // 初始化KatanaListenables
  KatanaListenables.init();

  // 监听自定义事件
  KatanaListenables.listen<MyCustomEvent>((event) {
    print('Received event: ${event.message}');
  });

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('KatanaListenables Example'),
        ),
        body: Center(
          child: MyEventButton(),
        ),
      ),
    );
  }
}

class MyEventButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        // 触发自定义事件
        KatanaListenables.notify(MyCustomEvent(message: 'Hello, World!'));
      },
      child: Text('Trigger Event'),
    );
  }
}

3. 运行应用

现在你可以运行你的Flutter应用。当你点击按钮时,你应该会在控制台看到打印出的消息:

Received event: Hello, World!

这个示例展示了如何使用katana_listenables插件来创建和监听全局事件。你可以根据需要在你的应用中扩展和修改这个示例。

回到顶部