You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter:如何在Provider中无StatefulWidget使用shared_preferences

在Flutter中无StatefulWidget/setState使用shared_preferences的方案

一、处理异步特性(Futures)

不用StatefulWidget时,FutureBuilder是最直接的解决方案,它能自动监听Future的状态(等待、完成、错误),并根据状态渲染对应UI,完全不需要依赖setState。如果需要实时监听数据变化,也可以结合ValueNotifier来维护状态,但FutureBuilder更适合单次异步加载的场景。

二、数据序列化问题

shared_preferences仅支持存储基础数据类型:String、int、bool、double、List<String>。如果要存储自定义对象,必须手动将其序列化为JSON字符串(用jsonEncode),读取时再反序列化为对象(用jsonDecode)——该包本身没有内置复杂对象的序列化功能。

完整示例

下面是一个无状态Widget的示例,实现保存/读取用户偏好的用户名:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';

// 自定义用户偏好模型(示例)
class UserPrefs {
  final String username;

  UserPrefs({required this.username});

  // 序列化为JSON字符串
  String toJson() => jsonEncode({'username': username});

  // 从JSON字符串反序列化
  static UserPrefs? fromJson(String jsonString) {
    try {
      final map = jsonDecode(jsonString) as Map<String, dynamic>;
      return UserPrefs(username: map['username'] ?? '');
    } catch (e) {
      return null;
    }
  }
}

class PrefsDemo extends StatelessWidget {
  final TextEditingController _usernameController = TextEditingController();

  // 保存用户名到shared_preferences
  Future<void> _saveUsername(String username) async {
    final prefs = await SharedPreferences.getInstance();
    final userPrefs = UserPrefs(username: username);
    await prefs.setString('user_prefs', userPrefs.toJson());
  }

  // 从shared_preferences读取用户名
  Future<UserPrefs?> _loadUsername() async {
    final prefs = await SharedPreferences.getInstance();
    final jsonString = prefs.getString('user_prefs');
    if (jsonString != null) {
      return UserPrefs.fromJson(jsonString);
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('SharedPrefs无状态示例')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _usernameController,
              decoration: const InputDecoration(labelText: '输入用户名'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: () => _saveUsername(_usernameController.text),
              child: const Text('保存'),
            ),
            const SizedBox(height: 24),
            // 用FutureBuilder处理异步加载
            FutureBuilder<UserPrefs?>(
              future: _loadUsername(),
              initialData: null,
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.waiting) {
                  return const CircularProgressIndicator();
                } else if (snapshot.hasError) {
                  return const Text('加载数据出错');
                } else {
                  final username = snapshot.data?.username ?? '未设置用户名';
                  return Text('当前保存的用户名:$username');
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

补充说明

  • 如果需要实时监听跨页面的shared_preferences数据变化,可以用ValueNotifier结合Consumer(来自provider包),或者Riverpod的FutureProvider,但这些需要引入额外状态管理包,上面的示例是纯Flutter基础实现。
  • 存储简单独立的基础类型(比如单个字符串、数字)时,不需要序列化,直接调用prefs.setString、prefs.getInt等方法即可。

内容的提问来源于stack exchange,提问作者Jad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 02:34:52