KivyMD RecycleView 具有低 FPS 和滞后

KivyMD RecycleView has low FPS & lags

我正在使用 Python 3.8.12、Kivy 2.0.0 和 KivyMD-0.104.2 我正在 运行 在 ASUS ROG STRIX GL503VD 上 PyCharm 在 Ubuntu 18.04 LTS 上安装我的应用程序。 我的问题是,每次我使用 for 循环在 KivyMD BottomNavgation 中使用 RecycleView 生成内容时,无论内容是什么(甚至可能是 for i in range(100)),应用程序开始移动得非常慢(手动调整大小时正确调整大小大约需要 10 秒)。此外,我在生成数据的选项卡上的 FPS 低于 50,而在空的选项卡中,我得到 @80 FPS。 当我 运行 在 Kivy 2.0.0 中说 for i in range(100) 时,问题似乎没有发生,但我更愿意坚持使用 KivyMD。

上周我一直在互联网上寻找解决方案,但没有成功,而且有点难以理解关于 RecycleView 的 kivy 文档。

下面是我的代码,如果我做了一些不符合“良好实践”的事情,请纠正我。我刚开始学习 Kivy,我是 Python(@1 年)的初学者。

非常感谢。

编辑:同样,当部署到 Android 时,它在小米 Redmi Note8 Pro 上的运行速度低于 30 FPS。

main.py

from kivy.lang import Builder
from kivymd.app import MDApp as md
from kivymd.uix.list import TwoLineListItem

import json as js
#from kivy.utils import platform
from kivy.core.window import Window

'''
if platform == "android":
    try:
        from android.permissions import request_permissions, Permission
        request_permissions([Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE])
    except:
        pass
'''

class MainApp(md):
    def build(self):
        Window.size = (491, 1064)
        self.theme_cls.primary_palette = 'Red'
        self.theme_cls.primary_hue = '50'
        layouts = Builder.load_file("layouts.kv")
        return layouts
    def on_start(self):
        for key, value in self.read_list().items():
            self.root.ids.container1.add_widget(TwoLineListItem(text=f"{key}", secondary_text="Tests : {}".format(len(value))))
        self.fps_monitor_start()
    def read_list(self):
        with open('tests.json', 'r') as read_test:
            #82 lines in test_list dict
            test_list = js.load(read_test)
        return test_list


if __name__ == '__main__':
    MainApp().run()

layouts.kv

<MainLayout>
#:import get_color_from_hex kivy.utils.get_color_from_hex
MDGridLayout:
    cols: 3
    size_hint: 1, 1
    MDBottomNavigation:
        panel_color: get_color_from_hex("#008080")
        text_color_active: get_color_from_hex("#FFFFFF")
        MDBottomNavigationItem:
            name: 'Item1'
            text: 'item_1'
            icon: 'language-python'
            MDGridLayout:
                cols: 1
                RecycleView:
                    MDList:
                        id: container1

        MDBottomNavigationItem:
            name: 'Item2'
            text: 'item_2'
            icon: 'language-cpp'
            MDBoxLayout:
                RecycleView:
                    MDList:
                        id: container2


        MDBottomNavigationItem:
            name: 'Item3'
            text: 'item_3'
            icon: 'language-javascript'
            MDBoxLayout:
                RecycleView:
                    MDList:
                        id: container3


您实际上并没有使用 RecycleView。要使用 RecycleView,您必须有一个 RecycleLayout 作为其子项,一个 viewclass,以及一个指示 RecycleLayout 中项目的 data 列表。

这是在 App 中使用 RecycleView 的一种方法。首先,修改 kv 以指示 RecycleLayoutviewclass:

MDGridLayout:
    cols: 3
    size_hint: 1, 1
    MDBottomNavigation:
        panel_color: get_color_from_hex("#008080")
        text_color_active: get_color_from_hex("#FFFFFF")
        MDBottomNavigationItem:
            name: 'Item1'
            text: 'item_1'
            icon: 'language-python'
            MDGridLayout:
                cols: 1
                RecycleView:
                    id: container1
                    viewclass: 'TwoLineListItem'
                    RecycleBoxLayout:
                        default_size: None, dp(75)
                        default_size_hint: 1, None
                        size_hint_y: None
                        height: self.minimum_height
                        orientation: 'vertical'

以上将 container1 id 移动到 RecycleView 并添加了允许 RecycleView 运行所需的属性。

然后可以修改on_start()方法来为RecycleView创建data列表:

def on_start(self):
    data = []
    for key, value in self.read_list().items():
        data.append({'text': f"{key}", 'secondary_text': "Tests : {}".format(len(value))})
    self.root.ids.container1.data = data
    self.fps_monitor_start()