Just getting ready to ramp up screen building on a big LVGL MP project and trying to understand memory management (already have all basic LVGL running on device and in our simulator).
Right now if I do something naive like this to simulate a user changing screens:
When an LVGL screen is created (a screen is any LVGL object with no parent), it is added to a list of screens managed by the display.
Changing the active screen by calling lv.scr_load does not delete the previous screens.
Furthermore, even when the Python wrapper object goes out of scope and collected by gc, the LVGL screen still exists in that list.
You can see the number of screens currently managed by your display like this: lv.disp_get_default().screen_cnt
So to solve this, you need to make sure that when you no longer need a screen you delete it by calling the scr.delete() function.
For the purpose of measuring memory usage you also need to call gc.collect() to trigger Garbage Collection before calling gc.mem_free(), if you want to see the true size of available memory.
So here is your example, with added code to delete the screen on each iteration.
When running it - free memory remains constant between iterations. You can also run this on the Online Simulator
counter = 0
scr = None
for i in range(0,10):
gc.collect()
print('Available Mem: {}'.format(gc.mem_free()))
if scr:
scr.delete()
scr = lv.obj()
btn = lv.btn(scr)
btn.align(lv.ALIGN.CENTER, 0, 0)
label = lv.label(btn)
label.set_text("Button {}".format(counter))
lv.scr_load(scr)
counter += 1
Thanks amirgon. That helped a lot! With my actual code I was also allocating and setting a keyboard input group like so:
group = lv.group_create()
group.add_obj(ta1)
group.add_obj(ta2)
common.keypad_indev.set_group(group)
I had to add code to keep track of the active group and call active_group._del() on each screen change, otherwise I was leaking 96 bytes each screen change.