You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Many people state that kivy is slow. While this may be true it is mostly due to that python is slow to run on android devices.Thus it is in the programmer's hands to properly optimize their code so as to create a performant application.
Most of the lag on android devices runing kivy apps arise due to widget creation. Widget creation remains the slowest step in a kivy app.
Here are some of the methods that I follow to optimize my apps and ensure I can hit 60fps even on old devices
One very simple method to improve performance of your app is to load all the heavy widgets or even all your apps widgets at the start of your application. However this does have the draw back of causing longer load times for your app.
The way to cover up these long load times would be too create an interesting app splash screen with some animations. Buildozer supports lottie animations(https://github.com/tshirtman/p4a_lottie_demo Courtesy of tshirtman).
Loading all your widgets at start means that you can simply add your widgets to screens through out your code and the performance impact would become negligable.
If you do need to create your widgets during program run time you can use animations to hide the lag. Properly placed animations that animate opacity can be used to hide the time required to load widgets. The user would perceive this just as a transition and not as lag.
First create your widget and give it an opacity of zero
Add the widget to the layout that it needs to be in
Add an animation for that widget's opacity. Set the duration to something small like .2 seconds.
You can take this further if you have to load mutiple instances of the same widget. Rather than loading them all together. Load one widget and on its animation complete load the next one. Keep the animation duration's short so that they dont add up to become too long
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3. Using a Producer Consumer Model To Load Widgets
By default when you create a widget. Kivy will create the entire widget within a single frame. But if your widget is complex and has numerous widgets and layouts within it this can cause lag. This is because kivy will be holding back from displaying that frame until the widget is entirely created which will appear to your user as the program freezing or hanging.
For certain cases using a loading bar to depict that the app is in fact still running but just loading data is useful but not pleasing. It makes the user wait for the app to complete its operation which can be frustating. There has to be some sort of visual action.
Instead you could slowly load instances of your widgets over multiple frames. Basically the code works in a way where you would create a widget in a frame and then the next instance in the next frame and so on. Thus large quantities of data can be loaded quickly.
Note: This method is only effective if you have to load a large amount of simple widgets. If you have to load complex widgets I would suggest using animations like in method 2. Or else you could break your complex widget into smaller simpler ones and load them over multiple frames.
This is a really painful task to do but definitely worth it. If you can remove un-needed layouts and widgets you can significantly improve the performance of your apps.
Some tips:
Use Boxlayouts and GridLayouts as I found these layouts can help position your widget more efficiently than floatlayouts.
Join Labels together. Rather than having three label widgets. Join them together to form a single label and use markup to modify the font style/color and any other property.
This is an example of combining two completely differnet labels into a single label object. I pass the text as this string and when displaying it would appear as they are separate labels but in fact they are a single label.
This in some cases can cut the amount of widgets to create in half.
There is no way to update the user interface or create widgets in a thread as kivy doesnt garuntee stable behaviour in this way. Instead run your ui on your main thread and run your other app functions on a secondary thread. This if done properly and for the correct use case can be very effective in improving performance.
This method can be used to signifcantly increase your app load times on android. It works by loadig only the mainscreen and then slowly loading the other screens of your app over time.
The code is by @Kulothungan16 ...
Check his repo for more info (https://github.com/Kulothungan16/kivy-lazy-loading-template)
Reduce your import statements(improves start time but not by a lot).
Wrong:
import kivy
Correct:
from kivy import #Whatever you need to import
Be smarter with widget placement. Try to group widgets together into a single instance. Dont be afraid to play with kivy source code or create your more efficient custom widgets. Remember the kivy library must remain customizable so there is only so much that can be removed and optimized. But if you create your own custom widgets you can remove unnecessary code that could speed up widget creation.
Dont use too much animation instances as this is slow on android
Reduce animation step value to 1/30 so that the animation only updates every other frame.Useful especially for opacity animation as the difference is not visible at all. You can go as low as 1/10 for opacity based animations.
Animation(opacity = 1, d=.3, step = 1/30)
Try to do some preloading of widgets in the background, like when the user is not touching the screen for a certain period of time. You can then stop this loading on the next touch down event etc. But remember dont to much background loading as this can cause a large amount of memory usage and could result in an even slower user experience
Reuse widgets as much as you can. Rather than recreating a widget everytime some value chnages reuse already created ones and only change the necessary values.
good post indeed, so for number 6 which is lazy loading i tried, it seems good and is fast but you cant use it for complex code as it load screen to a point if in your current project you used something like MDBottom Navigation you wont be able to load screens inside it or above it, but it is good, i believe if the owner could improve the code it will help many people out there, and other thing about lazy loading is that in android, is hard to use custom back button as i tried many times when you press your app back button to navigate back on previous screen it wont work at all🤞, but at the moment am trying to use kivy_router to implent lazy loading as it seems to have its own build it navigation which might work in android,
good post indeed, so for number 6 which is lazy loading i tried, it seems good and is fast but you cant use it for complex code as it load screen to a point if in your current project you used something like MDBottom Navigation you wont be able to load screens inside it or above it, but it is good, i believe if the owner could improve the code it will help many people out there, and other thing about lazy loading is that in android, is hard to use custom back button as i tried many times when you press your app back button to navigate back on previous screen it wont work at all🤞, but at the moment am trying to use kivy_router to implent lazy loading as it seems to have its own build it navigation which might work in android,
Thank you for your words. Its been long since I have used Kivy, I will update this guide with some more methods and like you suggested some better code when I find the time
Thank you for thsi post ,really helpfull