Flutter本地数据存储插件app_preference的使用

Flutter本地数据存储插件app_preference的使用

app_preference 是一个用于管理用户偏好设置的强大工具。它结合了 shared_preferencesflutter_secure_storage 的优点,并且提供了自定义序列化、异步处理和响应式更新等功能。

开始使用

首先,确保在你的项目中添加必要的依赖项:

flutter pub add shared_preferences app_preference_shared_preferences app_preference_secure_storage

依赖项包括:

  • shared_preferences: 用于简单的键值对存储。
  • app_preference_shared_preferences: 适配器,用于与 shared_preferences 集成。
  • app_preference_secure_storage: 适配器,用于与 flutter_secure_storage 集成。

使用 shared_preferences 存储简单数据

以下是一个简单的示例,展示如何使用 shared_preferences 存储和获取字符串数据。

import 'package:app_preference/app_preference.dart';
import 'package:app_preference_shared_preferences/app_preference_shared_preferences.dart';

// 获取 SharedPreferences 实例
final SharedPreferences sharedPreferences = getSharedPreference();
final AppPreferenceAdapter sharedPreferencesAdapter = SharedPreferencesAdapter(sharedPreferences);

// 创建 AppPreference 实例
final userNamePref = AppPreference<String>.direct(
  adapter: sharedPreferencesAdapter,
  key: 'user_name',
  defaultValue: '<unknown>',
);

// 打印初始值
print(userNamePref.value); // 如果是第一次使用,则打印 '<unknown>',否则打印 'my_name'

// 更新值并持久化到 SharedPreferences
userNamePref.value = 'my_name';

// 再次打印值
print(userNamePref.value); // 打印 'my_name'

使用 flutter_secure_storage 存储敏感数据

接下来,我们看看如何使用 flutter_secure_storage 来存储敏感信息,例如用户的访问令牌。

import 'package:app_preference_secure_storage/app_preference_secure_storage.dart';

// 获取 FlutterSecureStorage 实例
final FlutterSecureStorage secureStorage = getSecureStorage();
final AppPreferenceAdapter secureStorageAdapter = SecureStorageAdapter(secureStorage);

// 创建 AppPreference 实例
final userTokenPref = AppPreference<String?>.direct(
  adapter: secureStorageAdapter,
  key: 'user_token',
  defaultValue: null,
);

// 模拟用户认证过程并获取令牌
userTokenPref.value = await authenticateUser(userId, password);

// 调用 API 并传递令牌
await invokeApi(userToken: userTokenPref.value);

处理复杂对象

如果你需要存储更复杂的数据结构(例如 JSON 对象),你可以使用序列化功能。

class UserTokens {
  final String idToken;
  final String accessToken;
  final String refreshToken;

  const UserTokens(this.idToken, this.accessToken, this.refreshToken);

  factory UserTokens.fromJson(Map<String, dynamic> json) => ...;
  Map<String, dynamic> toJson() => ...;

  @override
  bool operator ==(dynamic other) => ...;

  @override
  int get hashCode => ...;

  static const empty = UserTokens("", "", "");
}

// 创建 AppPreference 实例
final userTokenPref = AppPreference<UserTokens>.serialized(
  adapter: secureStorageAdapter,
  key: 'user_tokens',
  defaultValue: UserTokens.empty,
  serializer: (tokens) => tokens.toJson(),
  deserializer: UserTokens.fromJson,
);

异步操作

app_preference 提供了多种方法来处理异步操作。

// 等待直到 `flutter_secure_storage` 返回值
await userTokenPref.ready;

// 打印加载后的值
print(userTokenPref.value); // 值已加载

确保异步读取:

print(await userTokenPref.ensuredRead());

确保异步创建:

final userTokenPref = await AppPreference<String?>.direct(
  adapter: secureStorageAdapter,
  key: 'user_token',
  defaultValue: null,
).ensuredCreation();

响应式更新

你可以利用 valueStream 方法来实现响应式更新。

使用 MobX

class UserNameWidget extends StatelessWidget {
  final AppPreference<String> userNamePref;

  const UserNameWidget({super.key, required this.userNamePref});

  @override
  Widget build(BuildContext context) => Observer(
    builder: (_) => Text(
      '${userNamePref.value}',
    ),
  );
}

不使用 MobX

class UserNameWidget extends StatelessWidget {
  final AppPreference<String> userNamePref;

  const UserNameWidget({super.key, required this.userNamePref});

  @override
  Widget build(BuildContext context) => StreamBuilder(
    stream: userNamePref.valueStream(),
    builder: (_, snapshot) => Text(
      '${snapshot.data}',
    ),
  );
}

监听变化

你还可以监听偏好设置的变化。

late final AppPreference<UserSessions> _userSessionPref;

@override
void initState() {
  super.initState();

  _userSessionPref = getUserSessionPref();

  _userSessionPref.subscribeChanges((session) {
    // 会话改变时触发
    if(session == UserSessions.empty) {
      // 会话变为空;
      Navigator.restorablePushReplacementNamed(context, '/unauthorized');
    }
  });
}

日志记录和错误处理

app_preference 使用 logging 库进行日志记录和错误报告。

如果应用已经使用了 logging 库,那么集成已经自动完成。

你也可以通过 AppPreference.logger 进行更细粒度的配置。

自定义日志记录

AppPreference.onLog((log) {
  print('${log.time} [${log.loggerName}](${log.level}): ${log.message}');
  if(log.error != null) print('Error: ${log.error}');
  if(log.stackTrace != null) print('StackTrace: ${log.stackTrace}');
});

仅关注错误

AppPreference.onError((message, error, stackTrace) {
  Crashlytics.instance.recordError(error, stackTrace, reason: message);
});

更多关于Flutter本地数据存储插件app_preference的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter本地数据存储插件app_preference的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中使用app_preferences插件进行本地数据存储的示例代码。app_preferences是一个简单的键值存储插件,可以用于在Flutter应用中持久化存储数据。

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

dependencies:
  flutter:
    sdk: flutter
  app_preferences: ^0.9.3  # 请注意版本号,使用最新版本

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

接下来,在你的Dart文件中使用app_preferences进行数据存储和读取。以下是一个完整的示例:

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  late AppPreferences preferences;
  String? storedValue;
  final String key = 'my_key';

  @override
  void initState() {
    super.initState();
    initPreferences();
  }

  Future<void> initPreferences() async {
    preferences = await AppPreferences.getInstance();
    storedValue = await preferences.getString(key, defaultValue: null);
    setState(() {});
  }

  Future<void> saveValue(String value) async {
    await preferences.setString(key, value);
    setState(() {
      storedValue = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('App Preferences Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Stored Value: $storedValue',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(height: 20),
            TextField(
              decoration: InputDecoration(
                labelText: 'Enter new value',
              ),
              onChanged: (value) {
                // You can add validation or processing here if needed
              },
              onEditingComplete: () async {
                // When the user finishes editing, save the value
                String newValue = (context as _MyHomePageState).textController.text;
                await saveValue(newValue);
              },
              // To directly use the TextField value, you can use a TextEditingController
              // but for simplicity, we'll use onEditingComplete here.
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                String newValue = 'Default Value';
                await saveValue(newValue);
              },
              child: Text('Set Default Value'),
            ),
          ],
        ),
      ),
    );
  }
}

注意

  1. 上面的示例代码中,TextFieldonEditingComplete方法用于在用户完成编辑时保存值。在实际应用中,你可能需要更复杂的逻辑来处理用户输入,例如使用TextEditingController来实时获取输入框的值。
  2. AppPreferences.getInstance()是一个异步方法,用于获取AppPreferences实例。
  3. 使用preferences.getString(key, defaultValue: null)读取存储的值,如果键不存在,则返回null
  4. 使用preferences.setString(key, value)保存值。

这个示例展示了如何使用app_preferences插件在Flutter应用中进行简单的本地数据存储和读取。希望这对你有所帮助!

回到顶部