Flutter持久化上下文管理插件persistent_context的使用

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

Flutter持久化上下文管理插件persistent_context的使用

PersistentContext

PersistentContext 是一个 Flutter 小部件,它提供了简单的同步接口来存储持久变量,并在底层依赖于共享偏好设置。

基本用法

要在一个小部件中开始使用持久变量,只需将其包装在 PersistentContext 小部件内。你可以通过 PersistentContext.of(context) 从任何后代小部件访问 PersistentContext 实例及其方法。

简单调用 set(key, value) 方法来设置名为 key 的持久变量并带有值 value,而 get(key) 方法用于访问该值。请注意,由于共享偏好设置的限制,value 只能有以下类型:

  • int
  • double
  • bool
  • String

每次设置值时,它将立即反映在 UI 上,并异步地在后台进行持久化。

然而,当你的应用程序第一次启动时,数据会从本地存储异步加载,因此如果在 PersistentContext 初始化之前调用 get 方法,则可能会返回 null(或者指定的默认值)。

你可以检查 ready 未来来等待初始化完成,以避免任何不便。

下面的示例展示了如何使用 PersistentContext 构建一个简单的计数器应用,该应用保持计数的持久性。注意,不需要状态小部件,因为 PersistentContext 也充当简单的状态管理器。

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

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

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

class CounterWidget extends StatelessWidget {
  void _increment(BuildContext context) {
    final currentCount = PersistentContext.of(context).get('counter') ?? 0;
    PersistentContext.of(context).set(
      'counter',
      currentCount + 1,
    );
  }

  void _reset(BuildContext context) {
    PersistentContext.of(context).set('counter', 0);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          'This counter will persist after restarting the app:',
        ),
        Text(
          '${PersistentContext.of(context).get('counter') ?? 0}',
          style: Theme.of(context).textTheme.headline4,
        ),
        ButtonBar(
          alignment: MainAxisAlignment.center,
          children: [
            ElevatedButton.icon(
              onPressed: () => _increment(context),
              icon: Icon(Icons.add),
              label: Text('Increment'),
            ),
            ElevatedButton.icon(
              onPressed: () => _reset(context),
              icon: Icon(Icons.refresh),
              label: Text('Reset'),
            ),
          ],
        ),
      ],
    );
  }
}

高级功能

PersistentContext 构造函数包含以下可选参数,这些参数可能在高级用例中很有用:

  • defaultValues: 一个键值映射,定义持久记录的默认值。注意,如果定义了默认值,则变量只能设置为相同类型的值。
  • prefix: 一个字符串前缀,将添加到所有共享偏好设置的键上。如果有多个 PersistentContext 实例,应使用它来避免冲突。
  • sharedPreferencesInstance: 一个可以直接使用的 SharedPreferences 实例。如果没有提供,则构造函数将异步创建一个新的 SharedPreferences 对象,这会导致一个小延迟。

以下代码片段说明了如何在前面的示例中使用这些参数:

PersistentContext(
    child: CounterWidget(),
    prefix: 'counterContext',
    defaultValues: {
        'counter': 0,
    },
    sharedPreferencesInstance: sharedPrefs,
)

扩展

为了保持代码尽可能干净和健壮,建议不要直接使用 PersistentContext,而是扩展它以创建一个自定义类,该类通过专用的 getter 和 setter 为每个持久变量调用 getset 方法,并且还静态地定义了默认值。

例如,考虑以下实现的计数器应用程序示例:

class CustomPersistentContext extends PersistentContext {
  // 默认值
  static final _counterDefault = 0;

  // 构造函数
  CustomPersistentContext({
    Key? key,
    required Widget child,
  }) : super(
          key: key,
          child: child,
          defaultValues: {
            'counter': _counterDefault,
          },
        );

  // Getter 和 Setter
  int get counter => get('counter') ?? _counterDefault;

  set counter(int value) {
    set('counter', value);
  }

  // 这是为了让 `of` 方法工作
  static CustomPersistentContext of(BuildContext context) {
    return context
        .dependOnInheritedWidgetOfExactType<CustomPersistentContext>()!;
  }
}

CounterWidget 中的 _increment_reset 方法可以简化如下:

void _increment(BuildContext context) {
  CustomPersistentContext.of(context).counter++;
}

void _reset(BuildContext context) {
  CustomPersistentContext.of(context).counter = 0;
}

完整示例

以下是完整的示例代码,包括 MyAppCounterWidget 类:

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

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

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

class CounterWidget extends StatelessWidget {
  void _increment(BuildContext context) {
    CustomPersistentContext.of(context).counter++;
  }

  void _reset(BuildContext context) {
    CustomPersistentContext.of(context).counter = 0;
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          'This counter will persist after restarting the app:',
        ),
        Text(
          '${CustomPersistentContext.of(context).counter}',
          style: Theme.of(context).textTheme.headline4,
        ),
        ButtonBar(
          alignment: MainAxisAlignment.center,
          children: [
            ElevatedButton.icon(
              onPressed: () => _increment(context),
              icon: Icon(Icons.add),
              label: Text('Increment'),
            ),
            ElevatedButton.icon(
              onPressed: () => _reset(context),
              icon: Icon(Icons.refresh),
              label: Text('Reset'),
            ),
          ],
        ),
      ],
    );
  }
}

class CustomPersistentContext extends PersistentContext {
  // 默认值
  static final _counterDefault = 0;

  // 构造函数
  CustomPersistentContext({
    Key? key,
    required Widget child,
  }) : super(
          key: key,
          child: child,
          defaultValues: {
            'counter': _counterDefault,
          },
        );

  // Getter 和 Setter
  int get counter => get('counter') ?? _counterDefault;

  set counter(int value) {
    set('counter', value);
  }

  // 这是为了让 `of` 方法工作
  static CustomPersistentContext of(BuildContext context) {
    return context
        .dependOnInheritedWidgetOfExactType<CustomPersistentContext>()!;
  }
}

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

1 回复

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


当然,下面是一个关于如何在Flutter应用中使用persistent_context插件进行持久化上下文管理的代码示例。persistent_context插件允许你在Flutter应用中轻松地进行状态持久化,特别是在需要跨页面或应用重启后保持数据的情况下。

首先,确保你已经在pubspec.yaml文件中添加了persistent_context依赖:

dependencies:
  flutter:
    sdk: flutter
  persistent_context: ^x.y.z  # 请替换为最新版本号

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

接下来,让我们看看如何在Flutter应用中使用persistent_context

1. 初始化PersistentContext

在你的应用入口(通常是main.dart)中初始化PersistentContext

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

void main() {
  // 初始化PersistentContext
  PersistentContext.init(
    storage: Storage.sharedPreferences,  // 使用SharedPreferences作为存储后端
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

2. 保存和读取数据

现在,你可以在任何需要的地方保存和读取数据。以下是一个简单的示例,展示如何在两个屏幕之间持久化数据。

HomeScreen.dart

import 'package:flutter/material.dart';
import 'package:persistent_context/persistent_context.dart';
import 'second_screen.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Persistent Context Demo'),
            ElevatedButton(
              onPressed: () async {
                // 保存数据到PersistentContext
                await PersistentContext.of(context).save('key', 'Hello, Persistent Context!');
                Navigator.push(context, MaterialPageRoute(builder: (context) => SecondScreen()));
              },
              child: Text('Save and Go to Second Screen'),
            ),
          ],
        ),
      ),
    );
  }
}

SecondScreen.dart

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

class SecondScreen extends StatefulWidget {
  @override
  _SecondScreenState createState() => _SecondScreenState();
}

class _SecondScreenState extends State<SecondScreen> {
  String? _value;

  @override
  void initState() {
    super.initState();
    // 在initState中读取数据
    _readValue();
  }

  Future<void> _readValue() async {
    String? value = await PersistentContext.of(context).read<String>('key');
    setState(() {
      _value = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Persistent Context Demo - Second Screen'),
            if (_value != null)
              Text(
                'Retrieved Value: $_value',
                style: TextStyle(fontSize: 20),
              ),
          ],
        ),
      ),
    );
  }
}

总结

以上代码示例展示了如何在Flutter应用中使用persistent_context插件进行持久化上下文管理。通过在main.dart中初始化PersistentContext,你可以在任何需要的地方使用PersistentContext.of(context).savePersistentContext.of(context).read方法来保存和读取数据。这非常适合于需要跨页面或应用重启后保持数据的场景。

回到顶部