feat(travel): Optimize arrival data updates and enhance UI responsiveness

This commit is contained in:
GW_MC
2026-02-03 21:45:23 +08:00
parent 1d32c7674e
commit a93b7fe029
4 changed files with 71 additions and 17 deletions

View File

@@ -160,8 +160,10 @@ void MainUI::update_arrivals(const std::vector<RouteArrivalData>& arrival_data)
return;
}
// Hide message label
// Hide message label only if it's currently visible
if (!lv_obj_has_flag(msg_label_, LV_OBJ_FLAG_HIDDEN)) {
lv_obj_add_flag(msg_label_, LV_OBJ_FLAG_HIDDEN);
}
// Update each route display
for (int i = 0; i < MAX_DISPLAY_ROUTES; i++) {
@@ -186,17 +188,21 @@ void MainUI::update_route_display_(RouteDisplay& display, const RouteArrivalData
display.cached_visible = true;
}
// Update header with line color
// Update header text (station -> direction)
std::string header_text = data.route.station_name + " -> " + data.route.direction_name;
if (header_text != display.cached_header_text) {
lv_label_set_text(display.header, header_text.c_str());
display.cached_header_text = header_text;
}
// Update line color only if changed
if (data.route.line_color != display.cached_line_color) {
if (!data.route.line_color.empty()) {
lv_color_t line_color = hex_to_lv_color_(data.route.line_color);
lv_obj_set_style_text_color(display.header, line_color, 0);
}
display.cached_line_color = data.route.line_color;
}
// Update arrival labels - only if text changed
for (int i = 0; i < MAX_ARRIVALS_PER_ROUTE; i++) {
@@ -217,23 +223,28 @@ void MainUI::update_route_display_(RouteDisplay& display, const RouteArrivalData
display.cached_arrival_texts[i] = arrival_text;
}
// Handle visibility
// Handle visibility only if changed
if (should_show != display.cached_arrival_visible[i]) {
if (should_show) {
if (lv_obj_has_flag(display.arrival_labels[i], LV_OBJ_FLAG_HIDDEN)) {
lv_obj_clear_flag(display.arrival_labels[i], LV_OBJ_FLAG_HIDDEN);
}
} else {
if (!lv_obj_has_flag(display.arrival_labels[i], LV_OBJ_FLAG_HIDDEN)) {
lv_obj_add_flag(display.arrival_labels[i], LV_OBJ_FLAG_HIDDEN);
}
display.cached_arrival_visible[i] = should_show;
}
}
// Show error if any
if (!data.is_valid && !data.error_message.empty()) {
std::string error_text = " 錯誤: " + data.error_message;
if (error_text != display.cached_arrival_texts[0]) {
lv_label_set_text(display.arrival_labels[0], error_text.c_str());
display.cached_arrival_texts[0] = error_text;
}
if (!display.cached_arrival_visible[0]) {
lv_obj_clear_flag(display.arrival_labels[0], LV_OBJ_FLAG_HIDDEN);
display.cached_arrival_visible[0] = true;
}
}
}
@@ -244,7 +255,10 @@ void MainUI::update_last_refresh_time(const std::string& time_str) {
}
std::string full_text = "更新: " + time_str;
if (full_text != cached_refresh_time_text) {
lv_label_set_text(refresh_time_label_, full_text.c_str());
cached_refresh_time_text = full_text;
}
lvgl_port_unlock();
}

View File

@@ -37,6 +37,7 @@ private:
lv_obj_t* settings_btn_ = nullptr;
lv_obj_t* refresh_time_label_ = nullptr;
lv_obj_t* msg_label_ = nullptr;
std::string cached_refresh_time_text;
// Route display containers (up to MAX_ROUTES)
struct RouteDisplay {
@@ -46,7 +47,9 @@ private:
// Cached values for change detection
std::string cached_header_text;
std::string cached_line_color;
std::string cached_arrival_texts[3];
bool cached_arrival_visible[3] = {false, false, false};
bool cached_visible = false;
};
RouteDisplay route_displays_[5];

View File

@@ -238,8 +238,11 @@ void MainUIHandler::fetch_and_update_arrivals_() {
arrival_data.push_back(data);
}
// Update UI
// Update UI only if data changed
if (has_arrival_data_changed_(arrival_data)) {
main_ui_->update_arrivals(arrival_data);
cached_arrival_data_ = arrival_data;
}
main_ui_->update_last_refresh_time(get_current_time_string_());
}
@@ -296,6 +299,37 @@ std::string MainUIHandler::get_current_time_string_() {
return std::string(buffer);
}
bool MainUIHandler::has_arrival_data_changed_(const std::vector<RouteArrivalData>& new_data) {
if (new_data.size() != cached_arrival_data_.size()) {
return true;
}
for (size_t i = 0; i < new_data.size(); i++) {
const auto& new_route = new_data[i];
const auto& cached_route = cached_arrival_data_[i];
if (new_route.route.station_code != cached_route.route.station_code ||
new_route.route.direction != cached_route.route.direction ||
new_route.is_valid != cached_route.is_valid ||
new_route.error_message != cached_route.error_message) {
return true;
}
if (new_route.arrivals.size() != cached_route.arrivals.size()) {
return true;
}
for (size_t j = 0; j < new_route.arrivals.size(); j++) {
if (new_route.arrivals[j].arrival_time != cached_route.arrivals[j].arrival_time ||
new_route.arrivals[j].arrival_time_full != cached_route.arrivals[j].arrival_time_full) {
return true;
}
}
}
return false;
}
void MainUIHandler::on_settings_button_clicked_static_(lv_event_t* e) {
MainUIHandler* handler = static_cast<MainUIHandler*>(lv_event_get_user_data(e));
if (handler) {

View File

@@ -47,6 +47,7 @@ private:
void on_settings_button_clicked_();
void fetch_and_update_arrivals_();
bool has_arrival_data_changed_(const std::vector<RouteArrivalData>& new_data);
std::string format_arrival_time_(const std::string& api_time);
std::string format_arrival_time_full_(const std::string& api_time);
std::string get_current_time_string_();
@@ -65,6 +66,8 @@ private:
SettingsButtonCallback on_settings_callback_ = nullptr;
void* settings_callback_user_data_ = nullptr;
std::vector<RouteArrivalData> cached_arrival_data_;
static constexpr uint32_t LVGL_LOCK_TIMEOUT_MS = 4000;
};