Flutter 可管理状态 可以跨导航路由进行通信 插件pylon的使用

Flutter 可管理状态 可以跨导航路由进行通信 插件pylon的使用

设计理念

与其它状态管理包不同,Pylon 的职责在于管理状态。这意味着我们会始终在可靠性上做取舍,而不是追求效率和速度。如果一个包不能保证 100% 的可靠运行,并且需要开发者理解系统的内部机制,那么它就不是一个好的包。Pylon 被设计为简单而可靠的工具,其优先级始终是可靠性。

Pylon 是一个 Provider

  • Pylon 的工作方式与 Provider 类似,但它们的工作方式更加符合预期。
  • Pylon 可以跨导航路由进行通信,通过 Pylon.push 方法实现。
  • 即使 Pylon 是当前访问它的小部件的直接父级,你也可以访问它。

使用方法

Pylon 非常容易使用。你可以将值包装到 widget 树中,并且可以随时访问这些值,无需担心以后无法获取。

基本计数器
import 'package:pylon/pylon.dart';

class Counter extends StatelessWidget {
  Counter({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) => Pylon<int>(
    value: 0, // 初始化值为 0
    builder: (context) => Scaffold(
      body: Center(
        // 访问 Pylon 中的值。由于 Pylon 是构建器,你可以立即使用它
        child: Text("Count: ${context.pylon<int>()}"), // 显示当前计数值
      ),
      floatingActionButton: FloatingActionButton(
        // 使用 modPylon<T>((T) => T) 来修改值,或者直接使用 setPylon(T)
        onPressed: () => context.modPylon<int>((t) => t + 1), // 每次点击按钮时增加计数
        child: Icon(Icons.add),
      ),
    ),
  );
}
桥接 Pylons

在这个例子中,我们有一个包含多个 Dog 对象的列表,每个对象都用一个 DogTile 小部件表示。当用户点击某个 DogTile 时,他们会被导航到 DogScreen,可以在其中修改 Dog 的年龄。当返回列表视图时,被点击的列表项会自动更新为新的年龄。

// 基本的 Dog 类,包含 copyWith 方法
class Dog {
  final String name;
  final int age;

  Dog(this.name, this.age);

  static Dog copyWith(Dog dog, {String? name, int? age}) =>
      Dog(name ?? dog.name, age ?? dog.age);
}

// 狗的列表
List<Dog> dogs = [
  Dog("Fido", 3),
  Dog("Rex", 5),
  Dog("Spot", 2),
];

// 一个方便的扩展,用于访问 Pylon 的值
extension XContext on BuildContext {
  Dog get dog => pylon<Dog>();
  set dog(Dog value) => setPylon(value);
}

// 狗的列表视图
class DogList extends StatelessWidget {
  const DogList({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) => ListView(
    // 将每个狗映射到一个 Pylon<Dog>(value: e, builder: () => DogTile())
    children: dogs.withPylons((context) => DogTile()),
  );
}

// 代表一个狗的列表项
class DogTile extends StatelessWidget {
  const DogTile({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) => ListTile(
    title: Text(context.dog.name),
    trailing: Text("${context.dog.age}y old"),
    // 使用 pylon.push 导航到 DogScreen 并保持 context.dog 可用
    onTap: () => Pylon.push(context, DogScreen()),
  );
}

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

  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(title: Text(context.dog.name)),
    body: Center(
      child: Text("Age: ${context.dog.age}"),
    ),
    floatingActionButton: FloatingActionButton(
      // 增加狗的年龄,这将自动更新此屏幕和父级列表项
      onPressed: () => context.dog = context.dog.copyWith(age: context.dog.age + 1),
      child: Icon(Icons.add),
    ),
  );
}

完整示例 Demo

以下是一个完整的示例代码,展示了如何使用 Pylon 插件来管理状态:

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

// 临时存储 "数据"
List<Note> notes = [];

// 临时函数用于添加笔记
void _addNote(String title, String note) => notes.add(Note(
      id: notes.length,
      name: title,
      description: note,
    ));

// 笔记类表示我们的数据模型
class Note implements PylonCodec<Note> {
  final int id;
  final String name;
  final String description;

  const Note({
    required this.id,
    required this.name,
    required this.description,
  });

  Map<String, dynamic> toMap() => {
        'name': name,
        'id': id,
        'description': description,
      };

  factory Note.fromMap(Map<String, dynamic> map) => Note(
        name: map['name'],
        description: map['description'],
        id: map['id'],
      );

  [@override](/user/override)
  String pylonEncode(Note value) => value.id.toString();

  [@override](/user/override)
  Future<Note> pylonDecode(String value) async => notes[int.parse(value)];
}

void main() {
  // 添加一些 "笔记"
  for (int i = 0; i < 100; i++) {
    _addNote("Hello Note ${notes.length}", "This is the content of note ${notes.length}");
  }

  registerPylonCodec(const Note(id: -1, name: "", description: ""));

  // 注册编码器
  runApp(MainS());
}

extension _XContextPylonNotes on BuildContext {
  Note get note => pylon<Note>();
}

class MainS extends StatelessWidget {
  Map<String, WidgetBuilder> routes = {
    "/": (context) => const HomeScreen(),
    "/note": (context) => const NoteScreen()
  };

  MainS({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) => MaterialApp(
        theme: ThemeData.dark(),
        debugShowCheckedModeBanner: false,
        onGenerateRoute: (RouteSettings settings) {
          if (settings.name?.isNotEmpty ?? false) {
            String route = Uri.parse(settings.name!).path;

            if (routes.containsKey(route)) {
              return MaterialPageRoute(
                  builder: routes[route]!, settings: settings);
            }
          }
        },
        routes: routes,
        initialRoute: "/",
      );
}

// 展示笔记列表的界面
class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: Conduit<int>(builder: (context, v) => Text("$v")),
        ),
        body: ListView.builder(
          // 为每个笔记构建一个 Pylon 包装的笔记项
          itemBuilder: (context, i) => Pylon<Note>(
            value: notes[i],
            builder: (context) => NoteTile(),
          ),
          itemCount: notes.length,
        ),
      );
}

// 一个显示笔记的列表项
class NoteTile extends StatelessWidget {
  const NoteTile({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) => ListTile(
        title: Text(context.note.name),
        subtitle: Text(context.note.description),
        onTap: () {
          Pylon.push(context, NoteScreen(),
              settings: RouteSettings(
                name: "/note",
              ));
          Conduit.modOr<int>((i) => (i ?? 0) + 1);
        },
      );
}

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

  [@override](/user/override)
  Widget build(BuildContext context) => PylonPort<Note>(
        tag: "note",
        loading: const Scaffold(body: Center(child: CircularProgressIndicator())),
        error: const Scaffold(body: Center(child: Text("Something went wrong"))),
        builder: (context) => Scaffold(
          appBar: AppBar(
            title: Text(context.note.name),
          ),
          body: Text(context.note.description),
          floatingActionButton: FloatingActionButton(
              onPressed: () {
                Pylon.push(
                    context,
                    Pylon<Note>(
                      value: notes[(context.note.id + 1) % notes.length],
                      builder: (context) => NoteScreen(),
                    ));
              },
              child: Icon(Icons.next_plan)),
        ),
      );
}

更多关于Flutter 可管理状态 可以跨导航路由进行通信 插件pylon的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter 可管理状态 可以跨导航路由进行通信 插件pylon的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,使用第三方插件通常涉及添加依赖项、导入包以及调用插件提供的API。尽管pylon插件的具体功能未知(由于描述为“undefined”),但我可以提供一个通用的模板代码示例,展示如何在Flutter项目中集成和使用一个假设的第三方插件。

步骤 1: 添加依赖项

首先,你需要在pubspec.yaml文件中添加pylon插件的依赖项。请注意,由于这是一个假设的插件,实际的依赖项名称和版本号可能会有所不同。你需要替换为实际的插件名称和版本号。

dependencies:
  flutter:
    sdk: flutter
  pylon: ^x.y.z  # 替换为实际的版本号

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

步骤 2: 导入包

在你的Dart文件中,你需要导入pylon包。

import 'package:pylon/pylon.dart';

步骤 3: 使用插件功能

由于pylon的具体功能未知,我将提供一个假设的示例代码,展示如何调用一个假设的插件方法。假设pylon插件有一个名为performUnknownFunction的方法。

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  String result = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Pylon Plugin Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Result: $result',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                try {
                  // 调用假设的 performUnknownFunction 方法
                  var response = await Pylon.performUnknownFunction();
                  setState(() {
                    result = 'Response: $response';
                  });
                } catch (e) {
                  setState(() {
                    result = 'Error: ${e.toString()}';
                  });
                }
              },
              child: Text('Perform Unknown Function'),
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个按钮,当用户点击按钮时,会调用Pylon.performUnknownFunction()方法(这是一个假设的方法名)。结果会显示在屏幕上。

注意事项

  1. 实际方法名与参数:由于pylon插件的具体功能未知,你需要查阅插件的官方文档以了解实际的方法名、参数以及返回值。
  2. 错误处理:在实际应用中,添加适当的错误处理是非常重要的,以便在插件调用失败时能够给用户一个友好的提示。
  3. 插件版本:确保你使用的是与你的Flutter SDK版本兼容的插件版本。

希望这个示例代码能帮助你开始使用pylon插件,尽管其具体功能未知。一旦你有了更多关于插件的信息,你可以相应地调整代码。

回到顶部