I have a global variable that gets changed on a onConnectionSuccessful callback for MQTT. I have an icon in my appBar that i can assign to change color when tapped by checking the variable and then updating. I want to know if there is a way to change the Color of the icon dynamically whenever the global variable changes. I don't know if I'm going about this the wrong way. Essentially, i want the icon to change when my connection to the server changes to let the user know if they are connected or not.
The callback Code:
void onConnected() {
client.subscribe('topic', MqttQos.atMostOnce);
globals.isMqttConnected = true;
print('OnConnected client callback - Client connection was successful');}
The Current Icon Code:
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,
),
),
The OnDisconnected Callback:
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');
}
}
Connected:
Disconnected:
CodePudding user response:
I will try to explain it well, but let's suppose we use Provider, a simple to use as state management, the first thing we have to do is to create our service, in this case is where your onConnected and onDisconnected functions will be found.
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');
}
}
}
Now I made a small demo, which requires you to download the Provider package.
Look, what I did next is simple, I simulated the connection and disconnection by means of buttons (in your case you have it in another way), now, when we need to call some variable or function referring to the service, we have to initiate it globally with a MultiProvider, this will allow that the service is in all the application.
It is for that reason that in my HomePage I initialize it of the following way:
final OnlineService newsService = Provider.of<OnlineService>(context);
With it I can obtain my functions and in the same way the variable isConnected; what you have to do is that instead of occupying buttons, you make the call of those functions when the client connects and you will see the change.
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
),
),
],
);
}
}