Flutter上下文管理插件xcontext的使用

Flutter上下文管理插件xcontext的使用

xcontext 是一个简单的包,它为 widgetsmaterialcupertino 库中的 BuildContext 对象添加了静态扩展方法和获取器。

xcontext 可以让你轻松地向 Flutter 的 BuildContext 添加静态扩展方法和获取器。你可以完全控制要添加到上下文的方法和获取器,同时保持类型安全,并且代码简洁清晰。

Continuous Integration xcontext Published by dartside.dev GitHub Stars Count

重要链接

关于这个包

这个包是一个实验,旨在消除代码库中的 SomeClass.of(context).someMethod 调用。该包还简化了需要传递 context 的其他函数调用。

使用该包将使你的代码更易于键入、阅读和理解。

我编写这个包的方式使得你可以轻松定制以满足你的需求,并有选择性地添加或隐藏扩展。

如果你喜欢 .of 静态方法,请继续使用它们!

使用

// 向BuildContext添加所有方法和获取器
import 'package:xcontext/xcontext.dart';

BuildContext context;
// 然后...
context.navigator.pushNamed('/other');
context.scaffold;
context.mediaQuery.platformBrightness;
context.theme;
context.dividerTheme;
context.cupertinoLocalizations;
context.cupertinoTheme;
context.showCupertinoDialog(builder: b, useRootNavigator: true); // 不要忘记定义builder。
context.showTimePicker(initialTime: TimeOfDay.now());

如果你希望代码更加简洁,可以使用“tiny”版本:

// tiny_xcontext 使用较短的名称,并不添加所有获取器
import 'package:xcontext/tiny_xcontext.dart';

BuildContext context;
// 然后...
context.nav.pushNamed('/other');
context.scaf;
context.mq.platformBrightness;
context.theme; // 并非所有获取器都被缩短。Theme已经足够短
// context.dividerTheme; // 在“tiny”模式下,并非所有获取器都可用
context.cupL10n;
context.cuptheme;
context.showCupDialog(builder: builder, useRootNavigator: true); // 不要忘记定义builder。
context.showTP(initialTime: TimeOfDay.now());

这个包的库

// 向BuildContext添加所有方法和获取器
import 'package:xcontext/xcontext.dart';

// 或者,如果你只想从某些库中扩展:
import 'package:xcontext/cupertino.dart';
import 'package:xcontext/material.dart';
import 'package:xcontext/widgets.dart';

// 向BuildContext添加一些方法和获取器,有些被缩短
import 'package:xcontext/tiny_xcontext.dart';

// 或者,如果你只想从某些库中扩展,使用简短版本
import 'package:xcontext/tiny_cupertino.dart';
import 'package:xcontext/tiny_material.dart';
import 'package:xcontext/tiny_widgets.dart';

查看所有库:xcontextcupertinomaterialwidgetstiny_xcontexttiny_cupertinotiny_materialtiny_widgets

Navigator.of(context)context.navigator

xcontext 包允许你直接在 context 上访问 Something.of(context).someMethod,形式为 context.something.someMethod。它将官方 widgetsmaterialcupertino 库的返回值的 .of 静态方法作为获取器添加。

因此,在导入 'package:xcontext/xcontext.dart' 之后,你可以写:

import 'package:xcontext/xcontext.dart';

class Example extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    // 代替 Theme.of(context),只需写:
    final theme = context.theme;
    // ...然后像平常一样使用主题:
    print('当前亮度是 ${theme.brightness}');
    return ElevatedButton(
      onPressed: () {
        // 代替 Navigator.of(context),使用 context.navigator
        context.navigator.pushNamed('/other');
      },
      child: Text('导航器推送'),
    );
  }
}

如果 .of 静态方法接受额外参数,这些值会暴露在不同的获取器中,例如:

// Navigator.of(context, rootNavigator: true)
context.rootNavigator;
// Theme.of(this, shadowThemeOnly: true);
context.shadowTheme;

显示这个,显示那个!

所有 showXYZ 方法(日期和时间选择器、模态底部表单、关于对话框)也被添加,所以现在你可以写:

import 'package:xcontext/xcontext.dart';

context.showAboutDialog(
  applicationName: 'xcontext 示例应用',
  applicationIcon: FlutterLogo(),
  applicationLegalese: '版权所有 2020',
  applicationVersion: '1.2.3',
  children: [
    Text('感谢使用此包!'),
    Text('❤️'),
  ],
);

hide/show

虽然扩展可能提高了可发现性,但在 IDE 中每次输入 context. 时看到几十个额外的方法可能会令人烦恼。出于这个原因,每个获取器和方法都是作为一个单独的扩展添加的,因此你可以根据需要 hideshow 它们。

/*** hide ***/
// 如果某个或多个扩展让你感到困扰,隐藏它们。
import 'package:xcontext/material.dart' hide XContextNavigationRailTheme;

/*** show ***/
// 如果你只需要某些扩展,显示它们,并隐藏所有其他扩展。
// 只显示 context.navigator 和 context.rootNavigator
import 'package:xcontext/widgets.dart' show XContextNavigator, XContextRootNavigator;

导出你需要的内容

你可能会认为,虽然使用包中的某些扩展很棒,但其他扩展并不那么好,所以你只希望看到子集的扩展。

只需创建一个新的文件 your_favorite_extensions.dart,导出你喜欢的扩展,然后在其余代码库中导入该文件以保持一致性。

// your_favorite_extensions.dart
export 'package:xcontext/xcontext.dart'
    show XContextShowGeneralDialog,  // context.showGeneralDialog
         XContextNavigator, // context.navigator
         XContextRootNavigator, // context.rootNavigator
         XContextScaffold,  // context.scaffold
         XContextMediaQuery; // context.mediaQuery

// 你甚至可以在这里编写自己的上下文扩展。
// 其他文件...
import 'package:your_awesome_app/your_favorite_extensions.dart';

简短的变体

这个包还有一个“tiny”变体的扩展。如果你偏好简洁,“tiny”版本不会包含所有可能的获取器和方法,并且一些获取器被重命名,以便你在保持代码清晰的同时减少编码量:

import 'package:xcontext/tiny_xcontext.dart';

// 然后...
context.nav.pop();
final isLight = context.mq.platformBrightness == Brightness.light;

完整示例代码

以下是一个完整的示例代码,展示了如何使用 xcontext 包:

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

void main() => runApp(MyApp());

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

class Example extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    final TextDirection textDirection = context.textDirection;
    print('文本方向: $textDirection}');
    return Wrap(
      children: [
        for (final button in [
          ElevatedButton(
            onPressed: () {
              context.showDatePicker(
                initialDate: DateTime.now(),
                firstDate: DateTime.now(),
                lastDate: DateTime.now().add(Duration(days: 7)),
              );
            },
            child: Text('日期选择器'),
          ),
          ElevatedButton(
            onPressed: () {
              context.navigator
                  .push(MaterialPageRoute(builder: (_) => ExampleRoute()));
            },
            child: Text('导航器推送'),
          ),
          ElevatedButton(
            onPressed: () {
              context.showModalBottomSheet(
                builder: (_) => BottomSheet(
                  builder: (_) => Padding(
                    padding: const EdgeInsets.all(28.0),
                    child: Popper(),
                  ),
                  onClosing: () {},
                ),
              );
            },
            child: Text('显示模态底部表单'),
          ),
          ElevatedButton(
            onPressed: () {
              final time = context.showTimePicker(initialTime: TimeOfDay.now());
              print('选择的时间是 $time');
            },
            child: Text('显示时间选择器'),
          ),
          ElevatedButton(
            onPressed: () {
              context.showAboutDialog(
                applicationName: 'xcontext 示例应用',
                applicationIcon: FlutterLogo(),
                applicationLegalese: '版权所有 2020',
                applicationVersion: '1.2.3',
                children: [
                  Text('感谢使用此包!'),
                  Text('❤️'),
                ],
              );
            },
            child: Text('显示关于对话框'),
          ),
        ])
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
            child: button,
          )
      ],
    );
  }
}

class ExampleRoute extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Popper(),
      ),
    );
  }
}

class Popper extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        context.navigator.pop();
      },
      child: Text('弹出!'),
    );
  }
}

更多关于Flutter上下文管理插件xcontext的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter上下文管理插件xcontext的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


xcontext 是一个用于 Flutter 的上下文管理插件,旨在简化在 Flutter 应用中获取和管理 BuildContext 的过程。它提供了一些便捷的方法来访问上下文,并在某些情况下可以避免手动传递 BuildContext

以下是如何使用 xcontext 插件的基本步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 xcontext 依赖:

dependencies:
  flutter:
    sdk: flutter
  xcontext: ^1.0.0  # 请根据最新版本号进行替换

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

2. 基本用法

获取 BuildContext

xcontext 提供了 XContext.of(context) 方法来获取当前的 BuildContext。这在你需要在某些地方访问 BuildContext 时非常有用。

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

class MyHomePage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('XContext Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            var currentContext = XContext.of(context);
            print('Current context: $currentContext');
          },
          child: Text('Get Context'),
        ),
      ),
    );
  }
}

导航和对话框

xcontext 还提供了一些便捷的方法来简化导航和显示对话框的操作。

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

class MyHomePage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('XContext Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () {
                XContext.push(context, MaterialPageRoute(
                  builder: (context) => SecondPage(),
                ));
              },
              child: Text('Navigate to Second Page'),
            ),
            ElevatedButton(
              onPressed: () {
                XContext.showDialog(
                  context: context,
                  builder: (context) {
                    return AlertDialog(
                      title: Text('Dialog'),
                      content: Text('This is a dialog.'),
                      actions: <Widget>[
                        TextButton(
                          onPressed: () {
                            Navigator.of(context).pop();
                          },
                          child: Text('OK'),
                        ),
                      ],
                    );
                  },
                );
              },
              child: Text('Show Dialog'),
            ),
          ],
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Page'),
      ),
      body: Center(
        child: Text('This is the second page.'),
      ),
    );
  }
}
回到顶部