Flutter偏好设置管理插件easy_prefs_gen的使用

Flutter偏好设置管理插件easy_prefs_gen的使用

Flutter代码生成器,用于生成易于使用的shared_preferences

Pub Package

Setup

在依赖项中添加easy_prefsshared_preferences,并在开发依赖项中添加easy_prefs_genbuild_runner。 注意:如果将[providerExtensionMethods]设置为true,则还需要添加provider

dependencies:
  easy_prefs: [version]
  shared_preferences: ^2.0.11

dev_dependencies:
  build_runner: [version]
  easy_prefs_gen: [version]

在你的main.dart文件中:

// 导入这两个包
import 'package:easy_prefs/easy_prefs.dart';
import 'package:shared_preferences/shared_preferences.dart';

Future<void> main() async {
  // 添加这两行
  WidgetsFlutterBinding.ensureInitialized(); 
  await EasyPrefs.initialize(await SharedPreferences.getInstance());

  // ...
  runApp(const MyApp());
}

运行代码生成器

一旦你在代码中添加了注解,就需要运行代码生成器来生成缺失的.g.dart生成的Dart文件。

dart run build_runner build

// 或者监听模式
dart run build_runner watch

示例

假设有一个名为example.dart的Dart文件,其中包含一个带有[PrefsAnnotation]注解的Settings类:

import 'package:easy_prefs/easy_prefs.dart';
import 'package:flutter/material.dart'; // 如果设置了[changeProvider]为true,则需要导入
import 'package:provider/provider.dart'; // 如果设置了[providerExtensionMethods]为true,则需要导入

part 'example.g.dart';

@PrefsAnnotation(
{  
	"username": "",
	"notification": true,
	"notificationSound": true,
	"exchangeRate": 1.1,
	"language": LanguageCodes.kmr,
	"likeCount": 0,
	"favs": PrefsStringList(["asf", "afsaf"]),
	"favs2": ["asf", "afsaf"],
},
changeNotifier: true,
onlyModifier: true,
providerExtensionMethods: true,
toggleMethodForBoolValues: true,
)
class Settings extends _$Settings {}

构建后会创建相应的部分文件example.g.dart

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'example.dart';

// **************************************************************************
// PrefsGenerator
// **************************************************************************

class _Keys {
  static const String username = 'username';
  static const String notification = 'notification';
  static const String notificationSound = 'notificationSound';
  static const String exchangeRate = 'exchangeRate';
  static const String language = 'language';
  static const String likeCount = 'likeCount';
  static const String favs = 'favs';
  static const String favs2 = 'favs2';
}

class _$Settings extends IEasyPrefs with ChangeNotifier {
  final _helper = SharedPreferencesHelper();
  final _Keys = const _Keys();

  /// 如果[silent]为true,则值更改不会通知。
  _$Settings({bool silent = false}) {
    if (silent) return;
    _helper.onNotify = onValueChanged;
  }

  [@override](/user/override)
  void onValueChanged(String key) {
    notifyListeners();
  }

  String? _$username;
  String get username => _$username ?? _helper.getString(_Keys.username, '');
  set username(String val) => _helper.setString(_Keys.username, val, (_) => _$username = val);

  bool? _$notification;
  bool get notification => _$notification ?? _helper.getBool(_Keys.notification, true);
  set notification(bool val) => _helper.setBool(_Keys.notification, val, (_) => _$notification = val);
  bool toggleNotification() => _helper.toggleBool(_Keys.notification, true, (val) => _$notification = val);

  bool? _$notificationSound;
  bool get notificationSound => _$notificationSound ?? _helper.getBool(_Keys.notificationSound, true);
  set notificationSound(bool val) => _helper.setBool(_Keys.notificationSound, val, (_) => _$notificationSound = val);
  bool toggleNotificationSound() => _helper.toggleBool(_Keys.notificationSound, true, (val) => _$notificationSound = val);

  double? _$exchangeRate;
  double get exchangeRate => _$exchangeRate ?? _helper.getDouble(_Keys.exchangeRate, 1.1);
  set exchangeRate(double val) => _helper.setDouble(_Keys.exchangeRate, val, (_) => _$exchangeRate = val);

  LanguageCodes? _$language;
  LanguageCodes get language => _$language ?? _helper.getEnum(_Keys.language, LanguageCodes.values, LanguageCodes.kmr);
  set language(LanguageCodes val) => _helper.setInt(_Keys.language, val.index, (_) => _$language = val);

  int? _$likeCount;
  int get likeCount => _$likeCount ?? _helper.getInt(_Keys.likeCount, 0);
  set likeCount(int val) => _helper.setInt(_Keys.likeCount, val, (_) => _$likeCount = val);

  NotifiableStringList? _$favs;
  NotifiableStringList get favs => _$favs ?? _helper.getStringList(_Keys.favs, ['asf', 'afsaf']);
  set favs(NotifiableStringList val) => _helper.setStringList(_Keys.favs, val, (_) => _$favs = val);

  NotifiableStringList? _$favs2;
  NotifiableStringList get favs2 => _$favs2 ?? _helper.getStringList(_Keys.favs2, ['asf', 'afsaf']);
  set favs2(NotifiableStringList val) => _helper.setStringList(_Keys.favs2, val, (_) => _$favs2 = val);

  [@override](/user/override)
  void initializeAll() {
    final tmp = _helper.onNotify;
    _helper.onNotify = null;

    username = username;
    notification = notification;
    notificationSound = notificationSound;
    exchangeRate = exchangeRate;
    language = language;
    likeCount = likeCount;
    favs = favs;
    favs2 = favs2;

    _helper.onNotify = tmp;
    _helper.onNotify?.call("");
  }

  [@override](/user/override)
  bool isTouched() {
    return _helper.hasKey(_Keys.username) ||
        _helper.hasKey(_Keys.notification) ||
        _helper.hasKey(_Keys.notificationSound) ||
        _helper.hasKey(_Keys.exchangeRate) ||
        _helper.hasKey(_Keys.language) ||
        _helper.hasKey(_Keys.likeCount) ||
        _helper.hasKey(_Keys.favs) ||
        _helper.hasKey(_Keys.favs2);
  }

  [@override](/user/override)
  String toString() {
    return '''
{
  "username" : "$username",
  "notification" : $notification,
  "notificationSound" : $notificationSound,
  "exchangeRate" : $exchangeRate,
  "language" : $language,
  "likeCount" : $likeCount,
  "favs" : [
      ${favs.map((e) => '"$e"').join(",\n      ")}
    ],
  "favs2" : [
      ${favs2.map((e) => '"$e"').join(",\n      ")}
    ]
}
''';
  }
}

extension SettingsProviderExtensionMethodsOnBuildContext on BuildContext {
  Settings readSettings() => read<Settings>();
  Settings watchSettings() => watch<Settings>();
  R selectSettings<R>(R Function(Settings s) selector) => select(selector);
}

消费该类(main.dart

import 'package:easy_prefs/easy_prefs.dart';
import 'package:easy_prefs_example/settings.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();  // 重要
  await EasyPrefs.initialize(await SharedPreferences.getInstance());  // 重要
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'EasyPrefs Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ChangeNotifierProvider(
        create: (_) => Settings(),
        builder: (_, __) {
          return const MyHomePage();
        },
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    final settings = context.watchSettings();
    final lastValInFavList = int.parse(settings.favs.isNotEmpty ? settings.favs.last : "0");
    return Scaffold(
      appBar: AppBar(
        title: const Text("EasyPrefs Demo"),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              CheckboxListTile(
                value: settings.notification,
                title: const Text("Enable notification"),
                onChanged: (t) => settings.notification = t!,
              ),
              CheckboxListTile(
                value: settings.notificationSound,
                title: const Text("Enable notification sound"),
                onChanged: (t) => settings.notificationSound = t!,
              ),
              const Divider(height: 1),
              ListTile(
                title: const Text("Language"),
                trailing: DropdownButton(
                  value: settings.language,
                  items: LanguageCodes.values
                      .map((e) => DropdownMenuItem(
                            child: Text(e.name, textScaler: TextScaler.linear(1.2)),
                            value: e,
                          ))
                      .toList(),
                  onChanged: (LanguageCodes? lang) {
                    if (lang != null) {
                      settings.language = lang;
                    }
                  },
                ),
              ),
              const Divider(height: 1),
              Row(
                children: [
                  const Padding(
                    padding: EdgeInsets.all(16.0),
                    child: Text("View Count: ", textScaler: TextScaler.linear(1.2)),
                  ),
                  const Spacer(),
                  IconButton(onPressed: () => settings.likeCount--, icon: const Icon(Icons.remove)),
                  Text(settings.likeCount.toString(), textScaler: TextScaler.linear(1.2)),
                  IconButton(onPressed: () => settings.likeCount++, icon: const Icon(Icons.add)),
                ],
              ),
              const Divider(height: 1),
              Row(
                children: [
                  const Padding(
                    padding: EdgeInsets.all(16.0),
                    child: Text("Fav Items: ", textScaler: TextScaler.linear(1.2)),
                  ),
                  const Spacer(),
                  ElevatedButton(onPressed: () => settings.favs.removeLast(), child: const Icon(Icons.remove)),
                  const SizedBox(width: 5),
                  ElevatedButton(onPressed: () => settings.favs.add("${lastValInFavList + 1}"), child: const Icon(Icons.add)),
                ],
              ),
              const Divider(height: 20),
              const Padding(
                padding: EdgeInsets.fromLTRB(20, 10, 20, 0),
                child: Text("settings.toString() :", textScaler: TextScaler.linear(1.1)),
              ),
              Padding(
                padding: const EdgeInsets.fromLTRB(20, 5, 20, 10),
                child: Text(settings.toString()),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

更多关于Flutter偏好设置管理插件easy_prefs_gen的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter偏好设置管理插件easy_prefs_gen的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


easy_prefs_gen 是一个用于 Flutter 应用的插件,它基于 shared_preferences 包,帮助开发者更方便地管理和生成偏好设置(Preferences)的代码。通过代码生成,easy_prefs_gen 可以自动生成用于读取和写入偏好设置的代码,减少手动编写重复代码的工作量。

安装 easy_prefs_gen

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

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.0.6  # 或者最新版本
  easy_prefs_gen: ^0.1.0  # 或者最新版本

dev_dependencies:
  build_runner: ^2.1.0  # 或者最新版本

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

使用 easy_prefs_gen

1. 创建偏好设置类

首先,你需要创建一个 Dart 类,并使用 @Prefs 注解来标记这个类。在这个类中,你可以定义需要存储的偏好设置字段。

import 'package:easy_prefs_gen/easy_prefs_gen.dart';

part 'prefs.g.dart';  // 自动生成的代码将会放在这个文件中

@Prefs()
class MyPrefs {
  @PrefsField(defaultValue: 'Guest')
  String username;

  @PrefsField(defaultValue: 0)
  int score;

  @PrefsField(defaultValue: false)
  bool isLoggedIn;
}

2. 生成代码

接下来,你需要运行 build_runner 来生成代码。在终端中运行以下命令:

flutter pub run build_runner build

运行完成后,easy_prefs_gen 会自动生成一个名为 prefs.g.dart 的文件,其中包含了读取和写入偏好设置的代码。

3. 使用生成的代码

生成的代码中包含了一个 MyPrefs 类的单例实例,你可以直接使用它来读取和写入偏好设置。

import 'package:flutter/material.dart';
import 'prefs.dart';  // 导入生成的代码

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 初始化偏好设置
  await MyPrefs.init();

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Easy Prefs Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('Username: ${MyPrefs.instance.username}'),
              ElevatedButton(
                onPressed: () {
                  // 更新偏好设置
                  MyPrefs.instance.username = 'JohnDoe';
                },
                child: Text('Update Username'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
回到顶部