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

Flutter Riverpod环境下选择国家后phoneCode无法界面更新问题

问题修复:Flutter Riverpod 选中国家后界面不更新

核心问题分析

  1. 未同步更新全局状态:LoginPage的pickCountry方法里仅修改了局部变量currentCountry,没有通过Riverpod的notifier更新countryProvider的全局状态,导致界面感知不到变化。
  2. 错误的状态监听逻辑:CountryCodeAndTextField中监听countryProvider.notifier并取其state,这种方式不会触发Widget重建,应该直接监听countryProvider本身。
  3. 异步代码执行顺序错误:debugPrint放在showCountryPicker外部,会在用户选择国家前执行,打印的是旧值而非选中后的最新值。

修复后的代码

1. 修正 login_page.dart

class LoginPage extends ConsumerWidget {
  const LoginPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    void pickCountry() {
      showCountryPicker(
        context: context,
        onSelect: (Country selectedCountry) {
          // 关键:通过notifier更新provider的全局状态
          ref.read(countryProvider.notifier).state = selectedCountry;
          // 在回调内打印才能获取选中后的最新值
          debugPrint('selected phone code: ${selectedCountry.phoneCode}');
        },
      );
    }

    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text(
          'Enter your phone number',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          const Text(
            'Chattor will need to verify your phone number',
            style: TextStyle(color: Colors.grey),
          ),
          TextButton(
            onPressed: pickCountry,
            child: const Text(
              'Pick Country',
              style: TextStyle(color: Colors.amber),
            ),
          ),
          const CountryCodeAndTextField(),
          SizedBox(height: ScreenSize.getHeight(context) * 0.63),
          SizedBox(
            width: ScreenSize.getWidth(context) * 0.30,
            height: ScreenSize.getHeight(context) * 0.07,
            child: const NextButtonWidget(),
          ),
        ],
      ),
    );
  }
}

2. 修正 country_code_and_text_field.dart

class CountryCodeAndTextField extends ConsumerWidget {
  const CountryCodeAndTextField({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 直接监听countryProvider,状态变化时自动触发Widget重建
    final Country? country = ref.watch(countryProvider);
    // TextEditingController用read而非watch,避免不必要的重建
    final phoneController = ref.read(phoneControllerProvider);

    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        if (country != null)
          Text(
            '+${country.phoneCode}',
            style: const TextStyle(color: Colors.white),
          )
        else
          const Text(
            '00',
            style: TextStyle(color: Colors.white),
          ),
        SizedBox(
          width: ScreenSize.getWidth(context) * 0.6,
          child: TextField(
            controller: phoneController,
            decoration: const InputDecoration(
              hintText: 'Enter your phone number',
              hintStyle: TextStyle(color: Colors.grey),
            ),
          ),
        ),
      ],
    );
  }
}

额外优化建议

phoneControllerProvider无需用StateProvider包裹,因为TextEditingController本身是可变对象,改用Provider并添加销毁逻辑更合理:

final phoneControllerProvider = Provider<TextEditingController>((ref) {
  final controller = TextEditingController();
  // 页面销毁时释放控制器,避免内存泄漏
  ref.onDispose(() => controller.dispose());
  return controller;
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:32:07