Update Controls from callback method

Can anyone tell me why controls won’t update inside a method even if I call lv_timer_handler().


void RescanButton_Clicked(lv_event_t *e)
	lv_dropdown_set_options(ui_WifiDropdown, "Scanning wifi...";);


	// do a long running process
	// ...

Another Example:

void Button_Clicked(lv_event_t *e)
   lv_label_set_text(ui_myLabel, "Step One");
   lv_label_set_text(ui_myLabel, "Step Two");
   lv_label_set_text(ui_myLabel, "Step Three");

Only “Step Three” shows in the label.

You didn’t write what system (target, compiler etc.) you are using, but I suppose Arduino.
So, see this here: Arduino delay

And also lv_timer_handler

Yes Arduino on as ESP32. I only put those delays there to have time to see the changed label before the next call to change it. But it’s not relevent because the screen is not redrawing in between.

My assumption is/was that calling lv_timer_handler() world perform a screen redraw. Maybe it would if I wasn’t in an lvgl button callback already?

I’m thinking of using RTOS to have actual process handoff delays as my current solution, but wanted to validate my expectations are correct.

As far as the docs explains, the delay is a blocking delay. That means nothing else can happen while the delay is running.
Also within RescanButton_Clicked the comment shows a “do a long running process”. Is it just a comment, or is there really a long running process.
Any long running process within lvgl functions will stop lvgl from doing the work. So you will not see anything happen as long as the long running functions are busy.
That means at least for the Button_Clicked function you are wasting three seconds for nothing.
As far as I know, lv_timer_handler is calling only the timer call back functions, and display redraw is done only in succession by calling lv_task_handler.

My goal was to provide feedback to the user during a long running process. For example a precent complete. My thought was I would force an lvgl redraw periodically with updated widget values. But I guess this is not possible?

It’s the only solution to run the process asychronously and poll it in the loop?

When you are running on a cooperative operating system (like using timers and timer callbacks in lvgl), you would have to split your long runners into short seperate processes, to allow lvgl to do the job of updating the UI.

An alternative approach is to use a preemtive operation system like FreeRTOS.
FreeRTOS is then giving the different tasks the appropriate time for processing (FreeRTOS is doing the ‘splitting’ of your long running process).
In this case, if you have one processing task and one lvgl task, you need a kind of syncronization beetween them.
Either you communicate by message queues, or if you want to call lvgl functions directly you need mutexes/semaphores
to allow exclusive access to the lvgl resources.
That means, when lv_task_handler is called (in the lvgl task), your second task (your long runner) is not allowed to call any lvgl function.
If you do a kind of polling from lvgl, per timer callback function, you may need a kind of exclusive access either. But that depends on what you want to access. A simple 16-bit (or 32-bit value) is ok, as a read is atomic, but reading more complex data may fail,
as lvgl is reading data which is not completly updated by the second (your long runner) task.