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

为provider_counter示例集成shared_preferences时遇类型赋值错误

解决SharedPreferences与Provider结合时的Future类型不匹配问题

问题原因

SharedPreferences.getInstance()是异步操作,返回的是Future<SharedPreferences>对象,但你的Counter构造函数要求传入的是SharedPreferences实例,这就导致了类型不匹配错误。


解决方案一:异步初始化main函数(推荐)

通过将main函数改为异步,等待SharedPreferences初始化完成后再启动App,确保传入Counter的是已经解析完成的实例:

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

void main() async {
  // 必须先初始化Flutter绑定,否则异步操作会抛出异常
  WidgetsFlutterBinding.ensureInitialized();
  // 等待SharedPreferences实例初始化完成
  final prefs = await SharedPreferences.getInstance();
  runApp(
    ChangeNotifierProvider(
      create: (context) => Counter(prefs: prefs),
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Counter Demo')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text('You have pushed the button this many times:'),
              Consumer<Counter>(
                builder: (context, counter, child) => Text(
                  '${counter.value}',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () => context.read<Counter>().increment(),
          tooltip: 'Increment',
          child: const Icon(Icons.add),
        ),
      ),
    );
  }
}

class Counter with ChangeNotifier {
  int value = 0;
  final SharedPreferences prefs;

  // 现在传入的是已初始化的SharedPreferences实例
  Counter({required this.prefs}) {
    value = prefs.getInt('counter') ?? 0;
  }

  void _setPrefItems() {
    prefs.setInt('counter', value);
  }

  void increment() {
    value += 1;
    _setPrefItems();
    notifyListeners();
  }
}

关键说明:

  • WidgetsFlutterBinding.ensureInitialized():在异步main函数中必须调用,确保Flutter的核心绑定已初始化,否则无法执行SharedPreferences.getInstance()这类平台相关操作。
  • await关键字:等待Future完成,拿到真正的SharedPreferences实例后再传递给Counter。

解决方案二:在Counter内部处理异步初始化

如果不想阻塞App启动(比如希望先显示默认值,再加载保存的数据),可以在Counter内部处理SharedPreferences的异步初始化:

class Counter with ChangeNotifier {
  int value = 0;
  late final SharedPreferences _prefs;

  Counter() {
    _initPrefs();
  }

  Future<void> _initPrefs() async {
    _prefs = await SharedPreferences.getInstance();
    // 加载保存的计数器值
    value = _prefs.getInt('counter') ?? 0;
    // 通知UI更新初始值
    notifyListeners();
  }

  void _setPrefItems() {
    _prefs.setInt('counter', value);
  }

  void increment() {
    value += 1;
    _setPrefItems();
    notifyListeners();
  }
}

关键说明:

  • 使用late关键字延迟初始化_prefs,避免在构造函数中处理异步逻辑。
  • 初始化完成后调用notifyListeners(),确保UI能接收到初始值的更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:22:45