Flutter媒体中介插件flutter_mediator_simple的使用

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

Flutter媒体中介插件flutter_mediator_simple的使用

Flutter Media Mediator Simple是一个用于Flutter的状态管理包。简单、高效且易于使用。

目录

开始使用

运行以下命令:

$ flutter pub add flutter_mediator_simple

这将在你的pubspec.yaml文件中添加如下依赖(并隐式地运行flutter pub get):

dependencies:
  flutter_mediator_simple: "^1.2.1"

或者,你的编辑器可能支持flutter pub get。查阅你的编辑器文档以了解更多信息。

导入它

在你的Dart代码中,你可以使用以下导入语句:

import 'package:flutter_mediator_simple/flutter_mediator_simple.dart';

有关如何开始使用Flutter的更多帮助,请参阅在线文档。

用法

  1. 声明需要管理的变量,并添加.rx后缀,使其成为中介变量。
  2. 创建Subscriber小部件。任何在Subscriber小部件内部使用的中介变量都会在更新时自动重建该小部件。

用例1:类型为Int的中介变量

步骤1:声明中介变量_int1

var.dart文件中声明中介变量_int1

/// Mediator Variable: int1
final _int1 = 0.rx; // or `final _int1 = Rx(0);`
int get int1 => _int1.value;
set int1(value) => _int1.value = value;
// optional
get int1Subscribe => _int1.subscribe;
String get int1Notify => _int1.notify;

步骤2:创建使用_int1Subscriber小部件

Subscriber(
  () {
    return Text(
      'int1: $int1', // 使用中介变量`_int1`
      style: Theme.of(subscriberContext).textTheme.headlineMedium,
    );
  },
),

更新int1将自动重建相应的Subscriber小部件。

@override
Widget build(BuildContext context) {
  return DefaultTabController(
    initialIndex: 0,
    length: myTabs.length,
    child: Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          switch (_tabController.index) {
            case 0:
              int1++;
              break;
            case 1:
              int2++;
              break;
            case 2:
              int3++;
              break;
            case 3:
              updateListItem();
              break;
            case 4:
              int1++;
              break;
            default:
          }
        },
        child: const Icon(Icons.add),
      ),
    ),
  );
}

用例2:类型为List的中介变量

步骤1:声明中介变量_data

var.dart文件中声明中介变量_data

/// Mediator Variable: data
final _data = <ListItem>[].rx; //or `RxList(<ListItem>[]);`
List<ListItem> get data => _data.value;
set data(List<ListItem> value) => _data.value = value;
SubscriberFn get dataSubscribe => _data.subscribe;
List<ListItem> get dataNotify => _data.notify;

步骤2:创建使用_dataSubscriber小部件

return Scaffold(
  appBar: AppBar(title: const Text('List Demo')),
  body: Subscriber(
    () => GridView.builder(
      itemCount: data.length, // 使用中介变量`_data`
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: (MediaQuery.of(subscriberContext).orientation == Orientation.portrait) ? 5 : 10,
      ),
      itemBuilder: (context, index) {
        final item = data[index];
        final widget = Padding(
          padding: const EdgeInsets.all(7.0),
          child: Card(
            color: item.color,
            child: Padding(
              padding: const EdgeInsets.all(3.0),
              child: GridTile(
                footer: Text("${item.units}"),
                child: Text(item.item),
              ),
            ),
          ).animate().fade(duration: 125.ms).scale(delay: 125.ms),
        );
        return widget;
      },
    ),
  ),
);

步骤3:实现更新函数

void updateListItem() {
  final units = Random().nextInt(maxUnits) + 1;
  final itemIdx = Random().nextInt(itemNames.length);
  final itemName = itemNames[itemIdx];
  final color = itemColors[Random().nextInt(itemColors.length)];
  if (data.length >= maxItems) data.clear();

  // 更新集合类型的中介变量
  // data.add(ListItem(itemName, units, color));
  _data.notify.add(ListItem(itemName, units, color)); // 通知小部件重建
}

使用notify来通知订阅小部件重建当中介变量的类型为类并且通过方法添加项目时。

用例3:中介变量的间接使用和持久化

间接使用意味着订阅小部件不使用中介变量的值,而是依赖于它。

步骤1:安装i18n包flutter_i18n并按照说明进行设置。

步骤1-1:在main.dart中设置locale delegates。

return MaterialApp(
  // ...
  localizationsDelegates: [
    FlutterI18nDelegate(
      translationLoader: FileTranslationLoader(
        forcedLocale: Locale(locale),
        // useCountryCode: true,
        fallbackFile: 'en',
        basePath: 'assets/flutter_i18n',
        decodeStrategies: [JsonDecodeStrategy()],
      ),
      missingTranslationHandler: (key, locale) {
        // ignore: avoid_print
        print('--- Missing Key: $key, languageCode: ${locale!.languageCode}');
      },
    ),
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
  ],
);

步骤1-2:在pubspec.yaml中添加资源并在指定文件夹中准备locale文件。

# pubspec.yaml
flutter:
  assets:
    - assets/flutter_i18n/

步骤2:安装持久化包shared_preferences

步骤3:在var.dart中声明中介变量_locale和SharedPreferences。

/// Locale page
late SharedPreferences prefs; // for persistence
// Mediator Variable: locale
late Rx<String> _locale;
String get locale => _locale.value;
// set locale(String value) =&gt; _locale.value = value; // comment out
get localeSubscribe => _locale.subscribe;
String get localeNotify => _locale.notify;

步骤4:实现初始化持久化的函数。

initPersistence() async {
  WidgetsFlutterBinding.ensureInitialized(); // for shared_Preferences
  prefs = await SharedPreferences.getInstance();
  final loc = prefs.getString("locale") ?? 'en'; // 默认locale为'en'
  _locale = loc.rx; // 将_locale设为类型为`Rx<String>`的中介变量
}

步骤5:实现设置locale的方法。

set locale(String value) {
  _locale.value = value;
  prefs.setString("locale", value);
}

步骤6:实现更改locale的方法。

/// 更改locale,通过`String`[countryCode]
Future<void> changeLocale(BuildContext context, String countryCode) async {
  if (countryCode != locale) {
    final loc = Locale(countryCode);
    await FlutterI18n.refresh(context, loc);

    locale = countryCode; // 重建关联的订阅小部件
  }
}

步骤7:在main.dart中初始化持久化。

void main() async {
  await initPersistence();
  runApp(const MyApp());
}

步骤8(可选):在var.dart中为String实现扩展,以帮助构建locale的订阅小部件。

extension StringI18n on String {
  /// String extension for i18n.
  String i18n(BuildContext context) {
    return FlutterI18n.translate(context, this);
  }

  /// String extension for i18n
  /// use `_locale.subscribe` to create Subscriber widget of locale.
  Widget sub18n(BuildContext context, {TextStyle? style}) {
    return _locale.subscribe(
      () => Text(FlutterI18n.translate(context, this), style: style),
    );
  }
}

步骤9:在main.dart中创建locale的订阅小部件。

Widget localeTxt(BuildContext context, String name) {
  return SizedBox(
    width: 250,
    child: Row(
      children: [
        // * Step: Create a Subscriber widget
        localeSubscribe(() => Text('${'app.hello'.i18n(context)} ')),
        Text('$name, '),
        // * Or use the string extension `sub18n`(in var.dart)
        'app.thanks'.sub18n(context),
      ],
    ),
  );
}

步骤10:在类_RadioGroupState中处理radio状态以更改locale。

Future<void> _handleRadioValueChange1(Object? value) async {
  await changeLocale(context, value!.toString());
  setState(() {});
}

用例4:计算型中介变量

步骤1:在var.dart中声明计算型中介变量_sum

/// Computed Mediator Variable: sum
final _sum = Rx(() => int1 + int2 + int3 as dynamic);
get sum => _sum.value;
set sum(value) => _sum.value = value;

步骤2:创建使用sumSubscriber小部件。

Subscriber(
  () {
    return Text(
      'sum(computed): $sum',
      style: Theme.of(subscriberContext).textTheme.headlineLarge,
    );
  },
),

步骤2a(可选):根据需要更改计算函数。

floatingActionButton: FloatingActionButton(
  onPressed: () {
    if (sum is int && sum >= 10) {
      sum = () => "excess upper bound($sum)";
    }
    // ...
  }
),

或者,将更改合并到计算函数中。

final _sum = Rx(() {
  final res = int1 + int2 + int3;
  if (res <= 10) {
    return res;
  }
  return "excess upper bound($res)";
});

订阅

要为中介变量的间接使用创建订阅小部件。

间接使用意味着订阅小部件不使用中介变量的值,而是依赖于它。

例如,locale用例。

通知

通知以重建与中介变量相关的方面。

当中介变量的类型为Class且通过方法添加项目时使用。

信号

中介变量可以通过Signal注解和类型别名初始化。

例如,

final _int1 = 0.signal;
final _int2 = Signal(0); 
final _int3 = Signal(0); 
// 计算型中介变量
final _sum = Signal(() => int1 + int2 + int3);

订阅者上下文

可以通过getter subscriberContext获取订阅者的上下文。

例如:

Subscriber(
  () {
    return Text(
      'int1: $int1',
      style: Theme.of(subscriberContext).textTheme.headlineMedium,
    );
  },
),

VS Code代码片段

使用VS Code代码片段来帮助键入样板代码。

例如,snippet_Flutter_Mediator__statelessful.code-snippets

  • getset - 获取/设置中介变量
  • cgetset - 获取/设置计算型中介变量
  • sub1 - 创建箭头函数的订阅小部件
  • subs - 创建多行的订阅小部件

带动画的状态管理

通过使用flutter_animate库,可以轻松地将动画添加到中介变量。如果每次中介变量变化都需要动画,则只需向animate添加一个ValueKey

例如,在main.dart中:

Subscriber(
  () {
    return Text(
      'int1: $int1', // 使用中介变量`_int1`
      style: Theme.of(subscriberContext).textTheme.headlineMedium,
    )
    .animate(key: ValueKey(int1))
    .fade(duration: 125.ms)
    .scale(delay: 125.ms);
  },
);

更多关于Flutter媒体中介插件flutter_mediator_simple的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter媒体中介插件flutter_mediator_simple的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用 flutter_mediator_simple 插件的示例代码。这个插件主要用于在 Flutter 应用中管理媒体播放,例如音频或视频。请注意,具体的插件功能和API可能会随着版本更新而变化,所以请确保你查阅了最新的官方文档。

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

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

然后运行 flutter pub get 来获取依赖项。

接下来,我们编写一个简单的 Flutter 应用来演示如何使用 flutter_mediator_simple

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

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

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

class MediaPlayerScreen extends StatefulWidget {
  @override
  _MediaPlayerScreenState createState() => _MediaPlayerScreenState();
}

class _MediaPlayerScreenState extends State<MediaPlayerScreen> {
  late MediaPlayerController _mediaPlayerController;

  @override
  void initState() {
    super.initState();
    // 初始化 MediaPlayerController
    _mediaPlayerController = MediaPlayerController(
      // 这里替换为你的媒体文件URL
      mediaUrl: 'https://www.example.com/path/to/your/media/file.mp4',
      autoPlay: false, // 是否自动播放
      looping: false, // 是否循环播放
    );

    // 监听播放状态变化
    _mediaPlayerController.addListener(() {
      setState(() {}); // 更新UI
    });
  }

  @override
  void dispose() {
    // 释放资源
    _mediaPlayerController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Media Player'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SizedBox(
              height: 200,
              child: VideoPlayerWidget(
                controller: _mediaPlayerController,
              ),
            ),
            SizedBox(height: 20),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                ElevatedButton(
                  onPressed: () {
                    setState(() {
                      _mediaPlayerController.play();
                    });
                  },
                  child: Text('Play'),
                ),
                SizedBox(width: 20),
                ElevatedButton(
                  onPressed: () {
                    setState(() {
                      _mediaPlayerController.pause();
                    });
                  },
                  child: Text('Pause'),
                ),
                SizedBox(width: 20),
                ElevatedButton(
                  onPressed: () {
                    setState(() {
                      _mediaPlayerController.stop();
                    });
                  },
                  child: Text('Stop'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的媒体播放器应用,它包含播放、暂停和停止按钮。我们使用 MediaPlayerController 来管理媒体播放,并将 VideoPlayerWidget 嵌入到我们的布局中显示视频。

请确保你已经正确配置了 flutter_mediator_simple 插件,并且媒体文件的URL是有效的。如果你使用的是音频文件,你可以替换 VideoPlayerWidgetAudioPlayerWidget

请注意,flutter_mediator_simple 插件的具体实现和API可能会随着版本更新而变化,所以务必参考最新的官方文档和示例代码。

回到顶部