Flutter查找功能插件findx的使用

Flutter查找功能插件FindX的使用

FindX 是一个受 GetX 中控制器和 GetBuilder 启发的 Flutter 状态管理器。

为什么我制作了这个包

  1. 因为我想尝试制作一个包,哈哈。
  2. 我真的很喜欢 GetX 作为状态管理器。我喜欢 GetControllers 的工作方式,我喜欢 Obx、GetBuilder 和 GetView。但是有时候 GetX 会以奇怪的方式运行,比如删除不应该被删除的控制器,或者不删除应该被删除的控制器。
  3. 我想尝试制作一个包,使得背后发生的事情更容易理解。

如何使用它

要使用 FindX,首先需要在小部件树中创建 FindXStore 小部件,该小部件将存储所有的控制器。

class MyApp extends StatelessWidget {
  // 这个小部件是你的应用的根节点。
  [@override](/user/override)
  Widget build(BuildContext context) {
    return FindXStore(
      child: MaterialApp(
        title: 'Flutter Demo',
        home: Test(),
      ),
    );
  }
}

现在我们需要我们的控制器:

class Controller extends FindXController {
  String sampleData = "example";

  void changeRandomData() {
    sampleData = _generateRandomString(10);
    this.update();
  }

  String _generateRandomString(int len) {
    var r = Random();
    const _chars =
        'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
    return List.generate(len, (index) => _chars[r.nextInt(_chars.length)]).join();
  }
}

如果你想要全局控制器,可以在 FindXStore 上使用 globalControllers 选项:

return FindXStore(
  globalControllers: [
    GlobalController()
  ],
  child: MaterialApp(
    title: 'Flutter Demo',
    home: Test(),
  ),
);

现在我们可以从不同的方式注入控制器:

FindXStore.of(context)!.store.put<Controller>(Controller());

然后可以在树的下层使用它:

FindXStore.of(context)!.store.find<Controller>();

别忘了在不再使用时移除控制器:

Find.of(context)!.store.remove<Controller>();

但是,有更好的方法来完成所有这些操作,那就是使用…

FindXBuilder

它类似于 GetX 中的 GetBuilder:

FindXBuilder<Controller>(
  builder: (Controller _) {
    return TextButton(
        onPressed: () {
          _.changeRandomData();
        },
        child: Text(_.sampleData));
  });

FindXBuilder 会找到我们想要的控制器,并将其传递给构建函数。当页面被销毁时,如果没有任何其他 FindXBuilder 使用该控制器,FindXStore 将会移除该控制器。

如果你没有注入你想要使用的控制器,有一个 put: 选项可以做到这一点:

FindXBuilder<Controller>(
  put: Controller(),
  builder: (Controller _) {
    return TextButton(
        onPressed: () {
          _.changeRandomData();
        },
        child: Text(_.sampleData));
  });

如果你使用此选项,FindXBuilder 会调用 FindXStore.of(context)!.store.put

如果你有另一个带有 put: Controller()FindXBuilder,它将尝试将对象放入存储(但不会成功),并使用该对象。

为了使这一切具有响应性,你可以调用控制器上的 update() 方法,这将更新所有依赖于该控制器的 FindXBuilder

如果你想仅更新少数几个 FindXBuilder,你可以指定一个 id,然后使用 update(['fxbuilder1','fxbuilder2']) 来更新。

完整示例代码

以下是完整的示例代码:

import 'package:findx/findx_builder.dart';
import 'package:findx/findx_store.dart';
import 'package:flutter/material.dart';
import 'package:test_findx/controllers.dart';

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

class MyApp extends StatelessWidget {
  // 这个小部件是你的应用的根节点。
  [@override](/user/override)
  Widget build(BuildContext context) {
    return FindXStore(
      globalControllers: [
        GlobalController()
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        home: Test(),
      ),
    );
  }
}

class Test extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    FindXStore.of(context)!.store.put(Controller()..sampleData = "okokoko");

    return Scaffold(
      body: Center(
        child: FindXBuilder<Controller>(
          put: Controller(),
          builder: (_) => Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              TextButton(
                  onPressed: () {
                    _.changeRandomData();
                  },
                  child: Text(_.sampleData)),
              AnotherFindXBuilder(),
              LastFindXBuilder(),
              TextButton(
                child: Text("To another page"),
                onPressed: (){
                  Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => SecondRoute()));
                },
              )
            ],
          ),
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(FindXStore.of(context)!.store.find<GlobalController>().data),
      ),
      body: Column(
        children: [
          FindXBuilder<GlobalController>(
            builder:(_) => TextButton(
              child: Text("Change data global controller - ${_.data}"),
              onPressed: (){
                _.changeRandomData();
              },
            ),
          ),
          TextButton(
            child: Text("Remove global controller"),
            onPressed: (){
              FindXStore.of(context)!.store.forceRemove<GlobalController>();
            },
          ),
          TextButton(
            child: Text("Go back to first"),
            onPressed: () {
              FindXStore.of(context)!.store.remove<Controller>();
            },
          ),
        ],
      ),
    );
  }
}

class FirstFindXBuilder extends StatelessWidget {

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FindXBuilder<Controller>(builder: (controller) {
      return TextButton(
          onPressed: () {
            controller.changeRandomData();
          },
          child: Text("First builder" + controller.sampleData));
    });
  }
}

class AnotherFindXBuilder extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return FindXBuilder<Controller>(builder: (controller) {
      return TextButton(
          onPressed: () {
            controller.changeRandomData();
          },
          child: Text("Second builder" + controller.sampleData));
    });
  }
}

class LastFindXBuilder extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return FindXBuilder<Controller>(
        //put: Controller(),
        builder: (_) {
          return Column(
            children: [
              TextButton(
                  onPressed: () {
                    _.changeRandomData();
                  },
                  child: Text("Last builder" + _.sampleData)),
              CommFindXBuilder()
            ],
          );
        });
  }
}

class CommFindXBuilder extends StatelessWidget {

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FindXBuilder<CommunicationWithOthers>(
        put: CommunicationWithOthers(),
        allowCommunicationWithOthers: true,
        builder: (_) {
      return TextButton(
          onPressed: () {
            _.testCommunication();
          },
          child: Text("Communicate with other controller"));
    });
  }
}

更多关于Flutter查找功能插件findx的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter查找功能插件findx的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


findx 是一个 Flutter 插件,用于简化在 Flutter 应用程序中查找和管理小部件的任务。它提供了一种更简洁的方式来查找小部件、验证它们的存在、以及执行交互操作。findx 插件通常用于测试和调试场景,但它也可以用于常规的开发中。

安装 findx 插件

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

dependencies:
  flutter:
    sdk: flutter
  findx: ^1.0.0  # 使用最新版本

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

使用 findx 插件

findx 插件的主要功能是通过 Find 类来查找小部件。以下是一些常见的用法:

1. 查找小部件

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('FindX Example'),
        ),
        body: Center(
          child: Text('Hello, FindX!', key: Key('hello_text')),
        ),
      ),
    );
  }
}

void findWidget() {
  final find = Find();
  final textWidget = find.text('Hello, FindX!');
  print(textWidget.key); // 输出: Key(hello_text)
}

在上面的例子中,我们使用 find.text('Hello, FindX!') 来查找包含特定文本的小部件。

2. 验证小部件的存在

void checkWidgetExistence() {
  final find = Find();
  final exists = find.text('Hello, FindX!').exists;
  print(exists); // 输出: true
}

exists 属性可以用来检查小部件是否存在。

3. 执行交互操作

void tapWidget() {
  final find = Find();
  find.text('Hello, FindX!').tap();
}

tap() 方法可以模拟用户点击小部件。

4. 查找嵌套小部件

void findNestedWidget() {
  final find = Find();
  final nestedWidget = find.byType(Scaffold).findText('Hello, FindX!');
  print(nestedWidget.key); // 输出: Key(hello_text)
}
回到顶部