Вот приложение Hello World как с двумя кнопками. Большой заполняет список из 50 элементов, а маленький очищает его. Проверка использования памяти выполняется следующим образом:
$ mprof run --include-children python leak.py
...
$ mprof plot --output out.png
Кроме kivy
, требуется программное обеспечение kivymd
, matplotlib
и memory-profiler
. Всякий раз, когда вы запускаете тест, создавая и затем очищая список несколько раз, нажимая кнопки, вы получаете график, похожий на непрерывно восходящую лестницу. Я абсолютно не знаю, что мне следует сделать, чтобы отправить удаленные виджеты сборщику мусора.
kivymd
Не могу обойтись.
leak.py
:
from functools import partial
import kivy
kivy.require("1.11.1")
from kivy.utils import platform
print(f"platform: {platform}")
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivymd.app import MDApp
from kivymd.uix.tab import MDTabsBase
from kivymd.uix.list import TwoLineAvatarIconListItem
import gc
ACTION_ICON = "eye"
class PowerListItem(TwoLineAvatarIconListItem):
"""The engaged power supply item."""
class TabList(FloatLayout, MDTabsBase):
"""The engaged power supplies tab."""
def surfacing(self, tab_text):
pass
def discover(self, cnt):
ids = MDApp.get_running_app().root.ids
for i in range(cnt):
item = PowerListItem(
text="List Item" + f" {i + 1:>2}", secondary_text="none"
)
ids.ps_list.add_widget(item)
class Contero(MDApp):
def build(self):
return Builder.load_file("leak.kv")
def on_start(self):
self.theme_cls.primary_palette = "Gray"
def discovery_clean(self):
for item in self.root.ids.ps_list.children:
print(f"item: {item.text}")
self.root.ids.ps_list.clear_widgets()
gc.collect()
def discovery_request(self, item_count=50):
self.discovery_clean()
tab_list = self.root.ids.ps_tab_list
tab_list.discover(item_count)
def on_tab_switch(self, instance_tabs, instance_tab, instance_tab_label, tab_text):
"""Called when switching tabs.
:type instance_tabs: <kivymd.uix.tab.MDTabs object>;
:param instance_tab: <__main__.Tab object>;
:param instance_tab_label: <kivymd.uix.tab.MDTabsLabel object>;
:param tab_text: text or name icon of tab;
"""
instance_tab.surfacing(tab_text)
if __name__ == "__main__":
Contero().run()
leak.kv
:
#:kivy 1.11.1
#:import ACTION_ICON __main__.ACTION_ICON
BoxLayout:
orientation: "vertical"
MDTabs:
id: ps_tabs
on_tab_switch: app.on_tab_switch(*args)
TabList:
id: ps_tab_list
text: "flash"
ScrollView:
bar_margin: 5
bar_width: 15
bar_color: .0, .8, .0, 1
bar_inactive_color: .5, .5, .5, 1
effect_cls: "ScrollEffect"
scroll_type: ["bars", "content"]
scroll_distance: 5
scroll_timeout: 50
MDList:
id: ps_list
MDBottomAppBar:
MDToolbar:
id: ps_toolbar
title: "Destroy a list"
icon: ACTION_ICON
type: "bottom"
on_action_button: app.discovery_request()
right_action_items: [ ['minus-box-outline', lambda x: app.discovery_clean()], ]
<PowerListItem>:
IconLeftWidget:
id: item_left
icon: "earth"