当某些全局变量发生变化时,有没有办法在 Flutter 中动态更新图标的颜色?

Is there a way to dynamically update the Color of an Icon in Flutter when some global variable changes?

我有一个全局变量,它在 MQTT 的 onConnectionSuccessful 回调中发生变化。我的 appBar 中有一个图标,我可以通过检查变量然后更新来分配它以更改颜色。我想知道是否有办法在全局变量更改时动态更改图标的颜色。我不知道我是否以错误的方式解决这个问题。本质上,我希望当我与服务器的连接发生变化时图标也会发生变化,以让用户知道他们是否已连接。

回调代码:

void onConnected() {
 client.subscribe('topic', MqttQos.atMostOnce);
 globals.isMqttConnected = true;
 print('OnConnected client callback - Client connection was successful');}

当前图标代码:

            child: GestureDetector(
             onTap: () {
               setState(() {});
             },
             child: (globals.isMqttConnected == true)
                 ? const Icon(
                     Icons.bar_chart_rounded,
                     size: 26.0,
                     color: Colors.white,
                   )
                 : const Icon(
                     Icons.bar_chart_rounded,
                     size: 26.0,
                     color: Colors.grey,
                   ),
           ),

OnDisconnected 回调:

void onDisconnected() {
 globals.isMqttConnected = false;
 print('EXAMPLE::OnDisconnected client callback - Client disconnection');
 if (client.connectionStatus!.disconnectionOrigin ==
     MqttDisconnectionOrigin.solicited) {
   print('EXAMPLE::OnDisconnected callback is solicited, this is correct');
 } else {
   print(
       'EXAMPLE::OnDisconnected callback is unsolicited or none, this is incorrect - exiting');
   // exit(-1);
 }
 if (pongCount == 3) {
   print('EXAMPLE:: Pong count is correct');
 } else {
   print('EXAMPLE:: Pong count is incorrect, expected 3. actual $pongCount');
 }

}

已连接:

断开连接:

我会尽量解释清楚,但假设我们使用 Provider,一个简单的用作状态管理,我们要做的第一件事就是创建我们的服务,在本例中是您的 onConnected 和 onDisconnected 函数所在的位置。

class OnlineService with ChangeNotifier { // to notify the listeners

   bool _isConnected = false; // varible that gonna change

   bool get isConnected => _isConnected; // getter

   void onConnected() {
     client.subscribe('topic', MqttQos.atMostOnce);
     globals.isMqttConnected = true;
     print('OnConnected client callback - Client connection was successful');

     _isConnected = true; // now connected
     notifyListeners(); // this is important to change the UI
   }

   void onDisconnected() {
     globals.isMqttConnected = false;
     print('EXAMPLE::OnDisconnected client callback - Client disconnection');

     _isConnected = false; // now disconnected
     notifyListeners(); // this is important to change the UI
       
     if (client.connectionStatus!.disconnectionOrigin ==    MqttDisconnectionOrigin.solicited) {
         print('EXAMPLE::OnDisconnected callback is solicited, this is correct');
     } else {
         print('EXAMPLE::OnDisconnected callback is unsolicited or none, this is incorrect - exiting');  // exit(-1);
     }
     if (pongCount == 3) {
         print('EXAMPLE:: Pong count is correct');
     } else {
       print('EXAMPLE:: Pong count is incorrect, expected 3. actual $pongCount');
      }
   }

}

现在我做了一个小demo,需要你下载Provider包。

你看,我接下来做的很简单,我通过按钮模拟连接和断开连接(你的情况是另一种方式),现在,当我们需要调用一些变量或函数时,引用服务,我们必须使用 MultiProvider 全局启动它,这将允许该服务在所有应用程序中。

正是出于这个原因,在我的 HomePage 中,我按以下方式对其进行了初始化:

final OnlineService newsService = Provider.of<OnlineService>(context);

有了它,我可以获得我的功能,并以同样的方式获得变量 isConnected;你要做的是,不要占用按钮,而是在客户端连接时调用这些函数,你就会看到变化。

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => OnlineService()), // set the service in all the app
      ],
      child: MaterialApp(
        title: 'Material App',
        theme: myTheme,
        debugShowCheckedModeBanner: false,
        home: const HomePage(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final OnlineService newsService = Provider.of<OnlineService>(context); // instance of the service

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        MaterialButton(
          onPressed: () {
            newsService.onConnected(); // connected
          },
          child: const Text("Connected"),
        ),
        MaterialButton(
          onPressed: () {
            newsService.onDisconnected(); // disconnected
          },
          child: const Text("Disconnected"),
        ),
        Center(
          child: Icon(
            Icons.bar_chart_rounded,
            size: 26.0,
            color: newsService.isConnected ? Colors.white : Colors.grey, // like this you change the color
          ),
        ),
      ],
    );
  }
}