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

如何使用Provider替代setState修改按钮颜色,避免地图组件不必要重绘

实现方案

1. 安装provider依赖

在项目pubspec.yaml中添加依赖:

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.1.1 # 可替换为当前最新稳定版

执行flutter pub get完成安装。

2. 新建状态管理类

创建独立的DriverStatusProvider类管理按钮相关状态:

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

class DriverStatusProvider extends ChangeNotifier {
  // 初始状态默认离线
  bool _isDriverAvailable = false;
  Color _driverStatusColor = Colors.black;
  String _driverStatusText = "您当前处于离线状态";

  // 对外暴露只读的状态
  bool get isDriverAvailable => _isDriverAvailable;
  Color get driverStatusColor => _driverStatusColor;
  String get driverStatusText => _driverStatusText;

  // 切换上下线状态的方法
  void toggleDriverStatus({
    required Function onOnline, // 上线时需要执行的业务逻辑
    required Function onOffline, // 下线时需要执行的业务逻辑
  }) {
    if (!_isDriverAvailable) {
      // 执行上线逻辑
      onOnline();
      // 更新状态
      _isDriverAvailable = true;
      _driverStatusColor = Colors.green;
      _driverStatusText = "您当前处于在线状态";
    } else {
      // 执行下线逻辑
      onOffline();
      // 更新状态
      _isDriverAvailable = false;
      _driverStatusColor = Colors.black;
      _driverStatusText = "您当前处于离线状态";
    }
    // 通知监听者更新
    notifyListeners();
  }
}

3. 注册Provider

在当前页面的父层注册Provider,示例如下:

// 你原有页面的父组件处修改
ChangeNotifierProvider(
  create: (context) => DriverStatusProvider(),
  child: YourOriginalPage(), // 替换为你的原有页面类名
)

4. 修改原有页面代码

删除原有页面State中定义的driverStatusColor、driverStatusText、isDriverAvailable三个变量,修改build方法如下:

@override
Widget build(BuildContext context) {
  super.build(context);
  return Stack(
    children: [
      // CustomMap不在Provider监听范围内,永远不会被强制重建
      const CustomMap(),
      Positioned(
        top: 60.0,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              // 用Selector仅监听需要的状态,仅更新按钮部分
              child: Selector<DriverStatusProvider, (Color, String)>(
                selector: (context, provider) => (provider.driverStatusColor, provider.driverStatusText),
                builder: (context, status, child) {
                  return RaisedButton(
                    color: status.$1,
                    child: Text(status.$2),
                    onPressed: () {
                      final provider = Provider.of<DriverStatusProvider>(context, listen: false);
                      provider.toggleDriverStatus(
                        onOnline: () {
                          makeDriverOnlineNow();
                          getLocationLiveUpdates();
                          displayToastMessage("You are Online now", context);
                        },
                        onOffline: () {
                          driverOffline();
                          displayToastMessage("You are Offline now", context);
                        },
                      );
                    },
                  );
                },
              ),
            )
          ],
        ),
      )
    ],
  );
}

实现原理

Selector只会监听你指定的driverStatusColor和driverStatusText两个状态,状态变化时仅会重建Selector包裹的按钮组件,位于监听范围外的CustomMap完全不会触发重建,也就不会出现地图重载的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 20:24:01