This tutorial focuses on practical performance engineering for Flutter applications connected to smart glasses, NVIDIA Jetson, ROS 2, and Physical AI systems.
Start by deciding which data needs real-time treatment and which data can be delayed. A useful mobile target is roughly 16 ms per frame for a 60 Hz display. High-frequency robot telemetry should not automatically trigger a full widget-tree rebuild.
Use separate budgets for:
A scalable design is:
Smart Glasses / Robot
|
v
Native Android / Jetson / ROS 2
|
v
Transport Layer
(WebSocket / MQTT / gRPC / REST)
|
v
Flutter Repository
|
v
State Controller
|
v
Lightweight Widgets
Keep transport, state, and presentation separate.
class RobotTelemetry {
final double battery;
final double cpu;
final double temperature;
const RobotTelemetry({
required this.battery,
required this.cpu,
required this.temperature,
});
}
The UI should consume application-level models instead of raw ROS 2 or wearable messages.
Avoid putting all telemetry into one large setState().
Prefer independently updating sections:
Column(
children: [
BatteryCard(),
CpuCard(),
TemperatureCard(),
CameraPreview(),
RobotLogPanel(),
],
)
Use granular state subscriptions so a battery change does not rebuild the camera preview.
If ROS 2 or a wearable SDK produces 100 messages per second, the UI normally does not need 100 complete rebuilds per second.
Keep the newest value and publish it to the UI at a controlled interval:
Timer? _uiTimer;
RobotTelemetry? _latest;
void onTelemetry(RobotTelemetry value) {
_latest = value;
}
void startUiUpdates() {
_uiTimer = Timer.periodic(
const Duration(milliseconds: 100),
(_) {
final value = _latest;
if (value != null) {
updateVisibleTelemetry(value);
}
},
);
}
This separates high-frequency acquisition from UI refresh.
For smart-glasses cameras and robot vision, an old frame can be less useful than the newest frame.
Prefer a bounded pipeline:
Frame -> processing
|
newer frame replaces waiting frame
rather than allowing an unlimited queue to grow.
Large JSON decoding, image transformations, filtering, and other CPU-heavy Dart work can cause frame drops.
For suitable CPU-bound work:
final result = await compute(processPayload, payload);
For hardware-specific or very expensive processing, move the work to native Android, Jetson, ROS 2, or another dedicated service.
Do not send every raw camera frame through a Flutter platform channel.
Prefer:
Camera
-> Native processing
-> filtering/compression
-> selected result
-> Flutter
For many operator applications, detections, metadata, status, or a preview frame are more useful than raw sensor data.
A strong robotics architecture is:
ROS 2 Sensors
|
v
ROS 2 / Isaac ROS Processing
|
v
Jetson AI / Control
|
v
WebSocket / MQTT / gRPC
|
v
Flutter
Flutter can receive compact state such as:
{
"robot_id": "r01",
"battery": 82.5,
"speed": 1.2,
"obstacles": 3,
"ai_state": "tracking"
}
instead of every low-level sensor sample.
Combine related values into snapshots instead of sending many tiny messages:
{
"timestamp": 1720000000,
"battery": 82.5,
"cpu": 61.2,
"temperature": 57.0,
"pose": {
"x": 1.2,
"y": 3.4,
"yaw": 0.8
}
}
Batching reduces message overhead and makes Flutter state updates simpler.
Do not render every raw point-cloud or sensor message directly in Flutter.
Use the robotics side to:
Then render the simplified result in Flutter.
AI models can generate frequent inference results. Flutter usually needs only useful, current results.
Filter by confidence:
final visible = detections
.where((d) => d.confidence >= 0.60)
.toList();
Also consider duplicate suppression, latest-result caching, and rate limiting before updating the UI.
For camera and AI screens:
A 720p preview may be more appropriate than transferring a 4K frame when the UI displays only a small preview.
For long detection, diagnostic, or telemetry lists:
ListView.builder(
itemCount: detections.length,
itemBuilder: (context, index) {
return DetectionTile(
detection: detections[index],
);
},
)
Avoid constructing every list item when only a small portion is visible.
Do not judge production performance only from debug mode.
Measure:
Trace the complete path:
Sensor
-> processing
-> transport
-> Flutter state
-> widget build
-> rendered frame
A small diagnostics model can expose performance problems:
class PerformanceStats {
int messagesReceived = 0;
int uiUpdates = 0;
int framesDropped = 0;
int commandsSent = 0;
}
If a stream receives 200 messages/sec but the screen needs only 10 updates/sec, the difference becomes visible immediately.
Performance optimization must never compromise safety.
Commands should use:
Example:
Flutter
|
| command + sequence ID
v
Jetson
|
| acknowledgement
v
Flutter
The robot must have its own safe-state behavior if Flutter or the network disappears.
For Meta or Google smart-glasses companion apps, filter wearable events before forwarding them to Flutter:
Wearable event
|
v
Native SDK
|
+--> filtering
+--> throttling
+--> aggregation
|
v
Flutter
For camera and audio workloads, native APIs should handle device-specific processing where practical.
For remote robots, use:
Separate traffic into:
HIGH: commands, emergency state, safety
MEDIUM: telemetry, AI detections
LOW: logs, debug metrics
Low-priority logging should never block control messages.
class TelemetryController {
RobotTelemetry? _latest;
Timer? _timer;
void receive(RobotTelemetry data) {
_latest = data;
}
void start(void Function(RobotTelemetry) publish) {
_timer = Timer.periodic(
const Duration(milliseconds: 100),
(_) {
final value = _latest;
if (value != null) publish(value);
},
);
}
void dispose() {
_timer?.cancel();
}
}
This is useful when acquisition is much faster than the desired UI update rate.
Smart Glasses
|
Native Android SDK
|
v
ROS 2 <------> Jetson / AI <------> NVIDIA Models
| |
| v
+------------> Gateway
|
WebSocket/MQTT/gRPC
|
v
Flutter Repository
|
Telemetry Controller
|
+-----------+-----------+
| | |
Status Camera AI UI
| | |
+-----------+-----------+
|
Operator UI
Flutter should focus on interaction, visualization, navigation, and operator controls. Jetson/ROS 2 should handle sensor processing, AI inference, and real-time robotics. Native wearable SDKs should handle platform-specific device access.
The largest performance gains in Flutter robotics and smart-glasses applications usually come from controlling the data pipeline rather than micro-optimizing individual widgets.
Use this sequence:
Acquire
↓
Process
↓
Filter
↓
Throttle
↓
Transport
↓
State
↓
Render
Do expensive work close to the hardware, send only useful information to Flutter, and render at a rate meaningful to the operator.
Website: www.v-modal.com
SDK Flutter: https://github.com/v-modal/vmodal_sdk_flutter
SDK Android: https://github.com/v-modal/vmodal_sdk_android
Discord: https://discord.gg/K72z28KUx