Recycleview Explained¶
GitHub link¶
AI Transcript provided by KivyWhisper¶
Hello and welcome to Kivy School. Today I'm going to show you a Kivy Recycle View tutorial. It will be a deep dive for beginners and it will be Recycle View versus Scroll View, Examples, and Analysis.
Now this is going to be the GitHub repo. I will update this completely later, but just letting you know if you want to see any of these examples, visit this GitHub repo and then you can just run them. Okay so I did this and this.
Okay so what is a Recycle View? Recycle View is a widget that displays a selection of many widgets at once and then now you're saying okay I have Scroll View, why should I use Recycle View? And I'll show you why. First I'll tell you why.
Recycle View is very performant, it's not laggy, it lets your app handle a lot of data without having to draw the data aka lag out your app. So there are a couple use cases off the top of my head. One is going to be handling inventory. Let's say you're handling a lot of materials and stock in your little warehouse. Okay you're not going to have like one thing, you're not going to have like two things, you're going to have like hundreds, thousands of things. You need to handle a lot of data and then if you have like a hundred thousand widgets in your Kibia app, it's going to lag. It will just straight up lag.
So handling inventory is one use case. Another use case is handling a library of songs. Songs could be like you know you can have like one song, you can have 10 songs, you can have 3,000 songs. That would be another use case for Recycle View. Another use case for Recycle View is handling complex widgets that are lagging out Scroll View.
If your Scroll View is lagging out, check out Recycle View. If you check out Recycle View, that will be your solution. Now here's going to be a concrete example. You have workers that you need to pay, right? Signified by selection behavior. Okay so let's go poetry shelf, go into our virtual environment, and then okay let me reset this. I'm going to press control J. Oh okay, so like this, control J, like this.
Okay poetry shell, and here poetry shell to enter our virtual environment. Now we'll type python and then I know it's workers. Then you can press tab to autocomplete like this. So you will autocomplete and then you will have your workers paid. So right now look they're all sad, haven't paid them. So now I click like this. Oh I paid worker with ID 2.
Now they're happy. I will pay worker ID 10. Now they're happy. I'll pay ID 4. Now they're happy. Oh but the check bounced on worker ID 4. Okay now they're going to be sad. So you can see already that Recycle View is very good for handling this kind of thing. And then you can see right now that there's up to like 10 widgets.
Okay you can do the same with Scroll View, but right now I will show you why Recycle View will handle Scroll View a lot better. I guess we'll say we'll have like 100 widgets, a thousand widgets. You'll see this very shortly. But this is just a very quick example of you know some of the things you can do with the Recycle View.
Now another thing I have to note is this note right here. I'm using this trick, well not really a trick but from Kivy Core window import window. Windows always on top. For most of the examples just because if you press like this and then you see it, the window is not going to show. Why? Because it's not on top. You have to spend time to click on it to make it on top. And then you see if you click here it will be hidden. But if you do on top then you press up arrow and then re-enter the command.
It will always be on top. It's just good for displaying but don't use this for apps unless you know you're in dev mode. Okay so I've done this, this, this, this, this, this, this, this, this, this, this, this, this, this, this, this. Okay now we're in part two. I'm going to show you. Why should you use Recycle View? So this is a basic example from Kivy Org.
So let's go python basic. So you see I hear this is the basic example from Kivy Org. I've taken it from this, this one and I think it's, I think it's this example right here. Because there's a second example here. It's got like a checkbox which is not what I'm using. It's this one. So with this example you see you have, how many widgets do you think you have first of all? Right? I'll give you a little bit.
How many widgets do you think? So here it's going to be 100 widgets. Why is it 99? Because you count at zero. You start at zero. So zero to 99, 100 widgets. Now let's check out scroll view. Python scv.py. Let's check out scroll view. How many widgets is this? It's going to be 100 widgets as well. So okay seems performant.
Both scroll view and Recycle View have 100 widgets. But now let's do a performance test. Let's say I want 1000 widgets. So we go right here. It's rvbasic and then scroll view. So here it's just showing, making everything viewable in the window. So this is the data. 100 widgets. I'm going to put 1000 widgets. And then right here, 1000 widgets. So Python, what is this? rvbasic. Okay, it's going to be 1000 widgets.
You already see this bar, scroll bar is very small already. Let's see if we can go to 1000. Very quickly, 200. Can you select these? You can't. Okay, let me exit because I have pdb here. Actually, let me remove pdb right now. Where is this? Okay, so we're going all the way, all the way. We will see the 1000. So actually the last widget is going to be 999, not 1000. Because again, we started zero. So if you started zero, at the very end, you got a minus one because your first number is not one, it's zero. Going all the way, pretty fast, pretty performant. All the way to 999 widgets. So you're here.
Oh, you can't select it. Okay, 999 widgets. Cool, right? Now let's go with scroll view. So python tv.py. Okay, it's taking a while. It's taking a while to load. Now let's go all the way to 999. And it doesn't even have to be like the number of widgets. For example, like if you have complex widgets, that's also going to lag you out. So you because if you see this, these are all just buttons, right? So buttons, very simple widgets. But once you have complex widgets, then you should start thinking about implementing recycle view.
All the way up here. Also, we got 999, right? To 999. Okay, cool. It was a little bit laggy. Let's try. Okay, we tried 1000. Let's try 10,000 widgets. Enter. 10,000. Save and save. Here we go. Python rv basic. Okay, all the way to 10,000. Um, okay, some lag. Then I'm not sure if I can. I know there's a way to like make this bar draggable. I'm just I didn't implement it. Okay, let's go keep clicking. It's still very performant. You can still click like this, right? Just pass 999 just to show it is 10,000 widgets. See 10,000 widgets.
All right, now let's try Python. What are you? SCV. Enter. Okay, you know, it's taken quite a while. No, just uh, I hope it doesn't crash. Right. So with recycle view, it works with this. Oh, something happened. Oh, oh, my virtual machine died. Okay, I got to. Okay, so already lagging out. It's lagging so bad that my virtual machine cannot run it. So already at 10,000 widget is failed. Now, just just because I'm curious, let's try 100,000. Let's see this 100,000. We just saved and saved Python. Basic. Okay, see even at 100,000, it's still lacking out. But come on, it's 100,000 widgets, right? 100,000 widgets in the virtual machine.
Pretty good. If I say so myself. Okay. Now let's try Python SCV. Right. This most likely it's gonna lag out. Most likely it's gonna lag out on my machine. We'll see. So I'm still waiting, you know, 1000, 2000, 3000, 4000. But you get my point, right? If you have something scroll view, if you have a scroll view that's lagging, just use recycle view. Check it out. Okay, let me talk while this loading. So now now that I've shown you why you should use recycle view, I'm going to show you some examples of recycle view, just so you can see different kinds of things you can do. So hello, is it loaded? Okay, it's dead. Done. Okay.
Oh, wait, maybe I crashed my machine. Okay, it's so laggy. It's not even responding to inputs. It can't even respond to control C. So there's going to be a couple examples. Now let's try RV basic 2. So Python RV basic. If you press tab here, it's going to use the original one, right? So I need to say RV basic 2. Now we will do the correct the correct found it. Let's see this one. Do you have any notes? Okay. So this one is the second example from Kibor. Where are you here? This one is the one with the checkbox, right? It's just saying, oh, you can have a view class state and that you can have a staple label.
Basically, these labels are, you know, they're changeable. It will have a state. So for example, the most important part is I've got a checkbox, right? If I leave and I come back, oh, the checkbox is still checked, right? This checkbox is still checked. And the big part about implementing recycle view is knowing how to manage and maintain the state, which I will show later. So this is, you know, one more example what you can do with recycle view. Go here. Now we'll try Elliot's example.
Very specifically, this question on the Kivy Reddit was exactly why I made this video because recycle view is very good, but nobody uses it. And then the other thing is nobody has documentation. Rather, it's really hard to read Kivy org. So I'm making this video. So this example is here. It's going to be the two buttons. It's going to be the two buttons app from Elliot, Elliot DG. Now let's run it. So Python DG. So what it does is you've got a RV list. It's got a left button.
Oh, wait, I've changed it a little bit. Where's PDB? I have a set tray somewhere. Oh, I don't. Okay. Never mind. Okay. Left button, right button, right? This is also a slightly complex widget. Why? Because right here it's going to be two buttons. Okay. Right here's two buttons. One second. Where? Oh, here it is. So two buttons is a box layout right here. And then within each box layout, you have two buttons. So then you can keep adding, adding, adding, adding, adding, adding, adding, and then these are clickable buttons, right? It's a good example.
It's very complicated. And then you can see the change, right? So, and then you see this is always on top. So you can have information here. Good example. I really like it. Okay. So these are all the examples from Kivy.org. These are the prerequisites. You need to have watched this video first, which is the previous video I've made. Basically it's how to install Kivy and then run Kivy example. These are all going to be in the, let me just go there very quickly. Here. No. Okay. But they're going to be actually, I'm just going to copy this. Let's just install examples right now. Okay. It's installed. It's going to be under share Kivy examples. And there's a lot of examples right now. It's going to be widgets.
And then you're going to check for recycle view, which is right here. So in your virtual environment, you go here under share Kivy examples, widgets, recycle view. And these are the examples that I'm going to show you. I just copy and paste with it. Then you can run it and code in place. I've done this, done this, done this, done this. Okay. Now let's do Python basic data.py. So what's my notes? It says populate, sort and clear. See, it doesn't have the window on top. So I got to click, but it's not a big deal. So what does this recycle view do? Populate list and certain new item. All right. So A, B, A, B, C, D, certain new item, update first item. This is updates, remove first item.
So again, how to manipulate a list, right? Sort list. That's pretty cool. Clear list, right? So this is a basic, um, basic data where you have populate, sort and clear. Okay. Let's try Python, scroll.py. Okay. Click here. So this is just an infinite scroll, right? You see hi here. And then you just, if you go down, it will just populate with more messages, just populate. So pretty cool, right? And it has like the time and date stamp, right? Pretty neat. Okay. So that's another reason why you'd want to use a recycle view. Let's see Python key view class.
Here, it's going to be, um, very complex widgets right here, right? You still see, excuse me, you still have, see the checkbox right here. Pretty cool. And all these text inputs. All right. So this is a text input. And then if you scroll out and you scroll back, still preserves the info. Let's see. And then there's a button. Oh, this is a drop down right here. Drop down or a, a, a, let's see, a D A B. Okay. So remembers, right? So very good complex widget, you know, something that you can look at. Um, this one is key. Excuse me. Where are you? So it's key view class, right?
And another important thing is that where are you? Just want to highlight that the key view class is widget. Now why is it important? Because if you notice here, the heights of these widgets are different, especially, um, this widget right here. And it's important because sometimes you have a problem where you want your, um, recycle view to show different heights because your widgets are sized differently.
So you use key view class widget. And you can see that the height of class widget, not, um, you see, let's get an example. I don't think the key view class would be defined, but it will say the view class will be just be two buttons, right? Because you always have the two buttons class. It will most likely be a fixed size. If you want a different size, you just say widget and it will display the widget for you. Okay. There's a messenger. So Python, messenger.py and then just wait here. Enter. So hello world. So this is another recycle view example. And then they will respond to you. This is a cool hack. Oh, my enter key is exploded.
Okay. You really think so? Now I'm not so sure. Sure. This is another recycle view. If you see up there, you can see the view pretty neat. And then this is a text into excuse me. This is a text input. Okay. Pull to refresh. So here, um, you pull down. So hello, run, you pull down like this. It will refresh and 10 to 20 up there. Pull down again. It will refresh. Well, down to refresh. So it just populates the list and it's pretty neat. Neato. Scroll up and down. You see all these widgets.
Then they can be as simple or as complex as you want. The end result is recycle views very efficient and displaying widgets and especially like data like this and handling complex widgets. All right. We've seen pull to refresh. Now let's try Python. Pre-animate. So this one, what's the cool thing about this? Let's press the button. Ooh, fancy animation, right? The animation is outside the scope of this video, but we'll get to it at some point. See right here. Wow. This is a really nice animation.
Okay. Next. Okay. So I have more online examples. Let's do Python. First update. This one is another example here. It just has updated text input. So update it. And you can see if you scroll up right here, it still hasn't forgotten the message. Okay. And then let's do Python. Init. Every data. So this one, it just has a pre-initialized data because sometimes in the other examples, yeah, you got to press a button and then it adds the data. But here, the data is already initialized on App Star, which is pretty cool. Sometimes you want this. It just says update list. Okay. Updated. Updates list. And it just updates the data. So that's it.
I hope you enjoyed this video. If you did, please like, share, and subscribe. So this is how you would initialize the list plus how to update it. Okay. This is another one. It's not a complete example, but if you do Python. Basically, your app is not always going to be just a reactive view. You want to have screen manager and go through different screens. So here it says go to settings. I hope it still works. My settings button. Okay. Back to menu. Don't quit because if it quits, I think it will just quit. Okay. We go to settings. So it has several screens. Right?
Now this is the recycle view. And then you'll see here's the initial recycle view. And then this is how you could implement just an idea that your app should not always be just a recycle view. You should always combine all the components together. So this is how you would have a recycle view and then use screen manager at the same time. Okay. Let me skip these. All right. Now this is my reference. What is the requirements for recycle view? Okay. Okay. There are four components to recycle view behavior. Recycle view, recycle layout, view class, and data.
Recycle view is the base widget. Inside of recycle view is the recycle layout. It determines the layout of recycled children widgets. The truth is that recycle will recycle children widgets don't exist as a widget you create, but as a dictionary. These dictionaries are stored in recycle view dot data, a list. The dictionaries contain the values for the attributes of the widgets. The widget type is set in recycle view under view class attribute. So you need to create a custom. Okay.
I think that's just solving his problem. And then there are more examples in this link, right? Which is what I've shown already. So what do you need? A recycle view, recycle layout, view class, and data. So let's go line by line on RVBasic and Elliot's example. So in RVBasic, which is the example from KVorg, let's go line by line. So this is just generic imports where you're going to import app builder. Builder just means you load the string instead of having a separate KV file. It's very nice to keep things compact. What is next? Recycle view. You need this.
Recycle data view behavior. You need this. It's just how to make a recycle view. You need to import labels if you want to use them. Bullying properties, because this one is the, um, where are you? RVBasic. This one is the clickable one. Oh, I think it still has a hundred thousand widgets. Let's change this. Let's go back to 100. Actually, I should also change, scroll view so I don't blow up someone's computer. Okay. So like this, it's 100 widgets. They use the Boolean attribute just so you know if you know it's selected or not. Right? Okay, what's next? Recycle box layout.
That's for Recycle View. Focus behavior, just so you know if you've focused in on it. Layout selection behavior. Again, that's from Recycle View. So build your load string just to load the string instead of having a KV file. So it's a selectable label. Drop background to indicate selection. Canvas before. Okay, so this is just a canvas instruction. It will instruct it to color it like this if you're selected or else like this, which is nothing, nothing, nothing, and then one alpha. And then rectangle, self-pause.
So it will just color the rectangle. And then this is the Recycle View. The View class is selectable label. This is it. Selectable Recycle Box Layout. Default size. Size hint. These are all you can see this in KV org. Then selectable Recycle Box Layout. That's defined here. Otherwise, KV will complain, oh it's not defined because if you use something here in KV, you gotta define it here in the Python as a rule. You don't always have to do it. Add selection and focus behavior to the view.
So selection is here. Layout selection and then focus behavior is here. And then this is the selectable label, which is a Recycle Data View behavior and the labels inherits from both. Add selection support to the label. The index is none. Selected is a Boolean property, which initializes false. Selectable is a Boolean property, initializes true. Now this refresh the attributes. It's got four args, it's three args and then one, you know, self. So it's four arguments. Catch and handle the view changes.
You got self index equals index returns super. So this one is important just because they're calling the label the label. How to explain this? They're calling the label refresh view attributes. So they're calling the method of the super class. So if you press F12 on VS code, go right here. And then what is I looking for? You do alt left key, I think. Ah, here, let's do this. See if I can look at it. Oh yeah, it's just catching and handling the view changes. One second. I think it's from label.
So if you press F12 and label and control F, find refresh view. Nope. So then try here, recycle view data behavior. Right here, it's just calling this the super class from what you inherit from. It's called by recycle view adapter when the view is initially populated with the values of the data dictionary. Any positive size info should be removed. In any case, this just refreshes the view. So just so and then the super is just calling the parent classes and then it's calling this method on touchdown.
So add selection on touchdown super like this. All this means is that you're calling the touchdown method. So again, we look at the parents. Here, let's say does recycle view have a touchdown behavior or touchdown method? Nope. So we go here, label. Does label have a touchdown method? Yes. So you're going to call this method instead of, you know, redefining everything. So it calls the touchdown of the label. So you preserve the label behavior and then it says self collide point.
So this one just says if your mouse touch and you're selectable, then you try this like touch and then apply selection, respond to the selection of items in the view. So self selected is selected. If you are selected, it will change. And then if not, you will go like this. Now this is the recycle view. What do you really need from the recycle view? Just self dot data. So in the initialize, it will call the, it will initialize the recycle view parent. So if you press F12, you will see there's an in it here. It will just call this just to preserve the recycle view behavior because otherwise, if you don't call this, it will not run as a recycle view.
It will just be in it, do nothing. It will just be a class, a recycle view class with self dot data and it will not be properly initialized. That's why you need these supers. Then this is your test app builder and then build self return RV. This is just because you need to return a widget, which is this recycle view, and it will only show recycle view. The name equals main. This is just a, you know, it's like a guard. It means that if you are calling RV basic dot PI, it will run. But if this is like a module, it will not call it because it will be loaded. It will be imported and it will not be main. But because RV basic is your, you're calling RV basic, it will be main. But if you are importing it, it will not be main.
And then from Kivy core window, import window, set it to top. That's okay. Then run. So there's that. I've covered RV basic and then Elliot's example right here. So let's go over Elliot's example, right? A lot simpler, right? But I'm not sure if it has selection. I think the selection is from the selection behavior is from the button. Oh, there's no selection behavior. It's a bit simpler. So Kivy app, import app, Kivy lang, import builder. You need this to, you know, again, not reference Kivy file. Import recycle view, import box layout, and string properties. Okay. Kivy is this, this is the Kivy string. This is me. I made this change just to show later using Python debugging tools about inspecting, you know, the app. Don't worry about this.
This is the two buttons class declaration. This class is used as the view class in the recycle view. This means this widget will be instant to view one element of data from the data list. The recycle view data list is a list of dictionaries. The keys in the dictionary specify the attributes of the widget. So here's a button and then the text is root dot underscore left text. I'm released. This button is pressed. Don't worry about this. This is me. There's another button. So this class of two buttons has two buttons, right? There's a left text and a right text and I'm released. It will just say, okay, you're this button was pressed. Now box layout.
The orientation is vertical. This is the button, add a widget, RV list and on release run RV dot add and RV dot add is here. All it does is extend the data list. What else? This is the recycle view gives the ID. The view class is two buttons, which is here. And then if you notice there's left text and right text, which is actually going to be defined here. What else? Where are you? The data itself, the data list. So again, the view class has two buttons defined above. The data is a list of dictionaries defined below in the RV class. Scroll type bars, content bar with 10 recycle box layout. This layout is used to hold the recycle widgets.
Default size is none. DP 48. This is the height of the box layout that holds the two buttons instance. Default size is one, none. Default size is why none. So this is just sizing and then orientation vertical. And again here, when you define a new widget, you have to define it in KV as a class. And then again in Python as a class, just as specified as a rule, there's ways to cheat it. So this class of two buttons inherits from box layout. So it's a box layout and then it has two string properties, left text and right text. Who else is new? Okay, RV is new, right?
Because that's not really a widget. Let's see. So here RV is a recycle view and then this is a list property. A list property is used to hold data for the recycle view. See the KV code, right? So we'll see the KV code right here. This is the data, right? So again, RV data list, RV data list. And again, you got it in it, super in it, just so that you have the recycle view initialized correctly. And then in the initialize, you set the RV data list. And then this is a list. If you look, let's break this apart.
It's a list of dictionaries. So it's just list comprehension. It says that for i in range of two, you will add this dictionary. So what this will look like is a list like here. So range of two, zero, one and two. So at zero, you go like this. i is zero. This is just, it's going to be an F string. So actually it looks like this, like this. One looks like this, looks like this. So RV data will look like this. And I think you need commas.
So this is a list of dictionaries. And then these dictionaries will define these string properties, which will be inherited, not inherited, but it will be referenced through button text, right? So if we comment this, okay, so comment this out and come here, fix this. Here's the Python, Elliot, DG. So zero, oh, sorry, range of two, it doesn't do the end. So that's my mistake. So zero and then one. And then you have it correct. Okay, let me see what's next. Okay, this list comprehension is used to create the data list for the simple example. The data creator looks like this.
Again, right here. Notice the keys in the dictionary correspond to the KV properties in the two buttons class. The data needs to be in this kind of list of dictionary formats. The RecycleView instances the widgets and populates them with data from this list. Oh yeah, I'm supposed to remove the F because it's an F string. So left text, left zero, right text, right zero, comma. Okay. And then this is the add definition. And it'll just extend the data list. And then this is how they extend it.
And this is the to app, build, build or load string, KV core window, windows always on top. Then you just run. So ground line by line. Talk about builder load string. And this is the reference, which I think I read already. Okay, next. Okay, let's actually go like this. So you're looking for an RV RecycleView, right? RecycleView, you need the class right here. Where are you? Right here.
It means use brackets, right? You don't really need to use brackets here. But there's just a quick explanation of KV. RV is not equal to RV. Right here, they use the widget. But then if you say RV like this, this is going to be a class definition. And then you will, you know, say whatever you want. But for right now, because there's nothing special, they just use RV like this. And then they have a class definition here. And then TLDR read, again, you got to read more, read the rules context, right? But basically, the root rules declared, okay, like this class rules. So this is a class and this is the actual use of the widget. So there's that. There's a layout, which is defined here. Recycle layout.
Let's look for the recycle layout here, which is here, which is one second, recycle box layout right here. So they've defined this, our RecycleView, and they've defined the layout. And then what else are you looking for? So there, you just need this. Let's see what's next. Now you need an actual view class. This is defined as view class or key view class. Where are you here? Now, if you notice, this is going to be the name of the widget. Okay, view class, view class is done. This is the data attribute, right? Now this is data like this. You can usually, I've seen it called like RV data, but here because they call data like this, they're going to reference data as self.rv data list.
The data is the list of dictionaries defined below in the RV class. So data is defined. The attribute of the RecycleView widget that lists the data is defined. The attribute of the RecycleView widget that lists, that is a list of dictionaries, could be something else like self.rv data list. Okay. And then data is a list and each element is a dictionary. I'll just do the proof here. So in line 68, okay, not 68 better here. We're going to inspect this app and then we're going to do the add, through the add, we'll import Python debugging tools and such. So we'll go Python like this, Elliot, DG, enter. Now when I press enter, okay, let's go like this. It will set trace will be right here. So first let's look at the arcs. Where are my arcs, right? This is the self.rv object.
Now what I want to show you is the RV data, right? So let's find, okay, we're already there. We're at the RecycleView. So let's do, first let's do some inspection, right? There's self.name. No name is the directory of self. Here, control F, let's look for data, right? So you see already there's a data attribute to self. So if that's the case, self.data, let's look at it. And it's correct. This is going to be a list. Let's see where I move this. The data create looks like this. It's going to be square bracket, curly bracket, left text, left zero, right text, right zero, left text. Okay, looks good. And then now what's the proof I'm trying to show you? It is a list and each element is a dictionary. So what's the type? self.data.
It's an observable list. Okay, it's a list. And then try type of self.data of the first element. Actually, first, let's look at it. What's this? It's this guy. What is this guy? It's going to be a dictionary or observable dictionary. Let's just click this. Okay, it's a dictionary. Okay, so yeah, and then in this example, okay, I also want to talk about app.get, running app.root. So if you're really lost, you want to know where something is, this is going to be entering your app to the root widget. So let's see if app exists. Right? Now let's try get running app. It's going to be your rv2 app object. Okay, cool. Now let's look at the root widget going to be dot root.
It's going to be again, this box layout. So where are we at? We're right here, right in the box layout. Okay, let's do. Let's look at the children, right? You have an rv object, you have a bun object, right? Okay, cool. So I want to look at the rv object. Right, so children, I think you can go like zero. rv object, right? But let's look at the bun object very quickly. Let's grab the text, right? What is this? It's bun object. Okay, let's check the text, right? Add widget rv list. That's correct.
So we'll go back to okay, let's go this. Back to here. What is that looking for again? Oh yeah, we're looking for data. So this is rv object again, this dot data dot data will be the same. Looks like this. So I've shown to you that it is a list of dictionaries. Let's see if I'm missing anything. Oh, yeah, you can also go through IDs. So if that's the case, app dot get running app, this because if you do like this, it's just going to be a function, right? You have to actually call the function using the parentheses. Okay, to app object. Let's see. What did I call it here? One second IDs.
So that's the case. Let's look at the IDs. IDs. It doesn't exist. I have to go through root. Okay. Root IDs. So you see here, this is the IDs method. It says rv. Why? Because the ID we've put the ID here or Elliot put the ID here. And then you can do this. IDS. IDs. And then what was I asking for? That data. One second. This rv. Okay, so first rv is going to be the weak proxy to the main rv object. It's not the object itself. It's a proxy, but it's almost the same data. And then we got our data similarly to through using the children technique. But because your app is going to be with a lot of children, you should just use the IDs method just so that you can specify it. Okay, so she always use the IDs method because if you go up here, you got to do root children zero one, and then you know, the order might not be always the same. And you got to really specify it.
This is just good for inspection. But this children thing is not good in practice. You should always use the IDs to look for a widget. Let's see what's next. Okay. And then it's populated doing init can be populated at any time, which is the data attribute is populated on init. If you look, you can exit. And we can look right here. On initialization, the data list is being populated because let's say we don't populate it, nothing will show up. All right, but if we add widget, oh, we'll have PDB on here. Then you can still add it, but initialize, but we initialize nothing right here. Okay, so it is a list, dictionary, show the proof.
Okay, now there's some issues with the widget example from Kivi org. The issue is forcing recycle view to update specifically updating in place in a deep level. The example minimally modified does not do that for you. Now the essence of the issue is right here. The deaf being tracked because they're asking you to use all these properties, right? But sometimes you're going to have like a complex widget, complex data. Okay, only the top level of nested object is being tracked. For example, right here, you have a list property one and a dictionary high and zero. Changing the top level element will trigger all the callbacks. So if you change the first element here to four, you will update. Changing deeper element will be ignored by all the callbacks. So if you change high from zero to four, this will not work.
Now, took me a long time to figure this out. Actually, I didn't figure it out. I had to figure it out when I was talking to him. But in any case, if you have a recycle view, and then you have a lot of different data and the data becomes complex, it's going to you might end up having to modify in place data that is not in the top level. So for example, in the workers page right here, I manually call the update right here from parent dot parent refresh on data. Why do I manually recall it? It's because I'm going from app route dot data. So this route, the route is the recycle view. I go to the index and then from the index, I modify the text. Because I modified the text and it's not top level change, it will not trigger all the callbacks.
So that's the crux of the issue with all the examples on KV org, all the official examples. They're slightly simple and they always tell you to just use a property and modify the top level keys of the list in order to update things. But if you just modify in place on a deeper level that is not tracked, you will not force an update. If you're not getting forced updates, you should always call recycle view refresh from data.
That's the essence of the issue. KV properties only track the top level, how to force a receptive view to update manually called recycle view refresh from data. So that's the crux of the issue. The issue with a lot of the widget examples, because if you go like this, Python, are you workers? Actually, let's turn it off.
Let's turn it off so you don't see a refresh. So this actually took me a while to figure out, but thanks. Thanks, ArborGaza. So right there, if you check the new recycle view data, I've actually, let's go like new window. I've actually changed the name, right? You're a smiley face now, but why is it still showing a sad face?
It's because the top level is this and it's not, this inner level is not being tracked. I'm only very specifically updating this and I'm not updating the top level. And I'm not updating the top level. If I had like updated this entire dictionary, it would have triggered an update. But because I only updated this specific portion, which is in a deeper level, it did not trigger an update. So I'm going to do the last one.
Should be a smiley face, right? I see a smiley face here in the RV data and I see the smiley face here, but it didn't trigger an update. So that's just a caveat that I struggled with. And if I struggle with it, a lot of people will struggle with it too. So I'm just pointing it out there. And then new RV data, just to prove that it's RV data, print recycle view RV.data. Okay. And then let's exit. Come back here, untouch down. Now that I manually call refresh from data. Okay. You, okay. Now they're smiling again. Okay. This one is not triggering. Very interesting. But most of them are triggering.
Okay. So there are other solutions to update data. Solution zero. Choose to reset RV data. Does not manually call refresh from data, but this is, so an example is RV.data. Just straight up, replace it, right? Very bad if you have large data. It will force an update, however. Don't do it. I'm just letting you know that will force an update. Okay. And then solution one, choose to update properties. Does not manually call refresh from data. So this is the standard solution. This is Elliott solution. So here you declare interact data list as a KV property. One second. I don't think this is correct. It doesn't exist. I think this was for another example, but in any case, the properties I know are here. They're declaring string properties and then they are just modifying these string properties. Oh, I think this is the Okay. Here's another recycle view instability refresh, right? There's a suggestion. Declare the data list as a KV property.
In KV, assign data to this. And then right here, they declare the list property and in KV declare this. This will force RV data to update when the list is changed, but nobody is saying it's only changed from the top level. Just keep that in mind. It's changed from the top level. Rather than having to update manually, this may address your issue. Doesn't consider posting a minimal example. This is just another thing to do. Everyone says to update properties, right? But and then they're using KV structure itself to force automatic updates because these things in the top level are being tracked. Okay. So let me go on here. This is solution two. This is the solution I use for this.
My custom example that's based off of the example from KV org. Choose to update the recycle view data itself plus force RV, the recycle view to update with recycle view dot refresh from data. So my solution is to use this recycle view KV IDs data view behavior. Okay. What does this mean? So if you look right here, I'm not using the standard recycle data view behavior. I'm using KV IDs. Simply for me, I think it's more natural just to modify the RV data right here. It says, where are you? RV data. This is an ID. And then this is the like the text tribute. So if you look, I've given, where are you? I've given every widget an ID and it's just ID dot text, you know, ID dot text.
And then if you look here, let's read the text. It says second, similar to recycle view data behavior, except that data keys can signify properties of an object named with an ID in the KV root rule. Given a KV root root or given a KV rule, label ID name ID value, then sending the data list with name dot text value dot text would automatically set the corresponding labels. If the key doesn't have a period, the name property of the root widget will be set to the corresponding value.
If there's a period, the name property of the widget with the ID listed before the period will be set to the corresponding value. So this is just something to keep in mind because sometimes you have periods in the names. It just says the name property of the widget with the ID listed before the period will be set to the corresponding value. So play around with it. TLDR, don't put periods in your key names, key IDs. So here, this is for me, this is very cool and very intuitive,
I think, because you can just say name dot text. You can say value dot text in your data and will automatically update. That's something really cool. I don't think I've seen anybody else do it, but I read through the docs and I've seen it and I thought, where is it? I spent four days looking for this because I thought this was default behavior of the recycle view the entire time. Anyways, most likely you're going to end up referencing your widgets like every widget by ID. It's just like a good, it's just good practice. And then in my opinion, it makes it easier to make and handle complex view class widgets.
So where is color? Okay, I'm going to, I'll just show it off manually. Where are you? So for example, why do I think this is cool? Because if you see right here, and when you apply selection, I'm just going to say employ name, label ID. I'll just straight up change your color. I'm not sure what the hex color is. This RGB, it's 170. But if you look like, if you look right here, you press it, the color changes, it changes. Right. And I think that's really cool because if you wanted to change this using KV, you would have to like specify right here, you know, some sort of like color property, right. And then up here, you would have to specify like color right here and then do like root dot color. Okay. This bad naming, let's say color ID right here, right. Then here it would be like color ID. And then you would select the correct property.
I think it would be like numerical property if I remember the name correctly. Right. But if you use, you know, let's delete this. But if you use KV IDs, recycle KV IDs data view behavior, if you use that, you could just straight up specify, okay, the widget ID dot color, this one. Let's even try another one. Let's try if it's RGB, then try 255, I think 0, 0. So this would be mostly red unless it's BGR, which I'll be. Okay. I know what's going on. They're being combined. The colors are being combined. But in any case, pretty cool. You can manipulate the widget without having to to prepare everything beforehand. Right. So in my opinion, that's pretty cool and pretty useful. Okay. So the solution, this is kind of hard to read. Is this a wide? Okay. Okay. So the solution, why should you use the original solution, which is using properties? Right. Here's solution one.
Number one, the structure is flat. Handle everything through view class widgets and their properties. Number two, you have to set everything up correctly, which is, you know, you should always set up your app correctly. Right. But what's the con? You have to manually remember to property everything. Everything that you want to change should be a property in order to trigger all of the refreshes. So that's something, it's not really a con. It's like, you know, it's a style. It's just something you have to do. And if you do it correctly, it will make your life a lot easier. Right. In my opinion, it's a bit hard to manipulate the view box that view classes easily. I've been trying for two days. So the video has been around like four days in the making. I'm not sure, but for me anyways, it was more natural to use the KVIDs method than to use the string properties method.
And then you still might have to call refresh from data if you modify data in place, especially if you modify data in place in a lower level, then you're forced to call refresh from data. Why? Because only top level changes are being tracked with these properties. Not everything can be done in KV. So the KV line must be perfectly set up. So for me, the putting string properties is not as intuitive. But if you do through KVIDs, for me, it's intuitive. And also, you must have in your mind have already laid out how the app should look like in KV for this method to really be effective.
Like if you were to do this straight up, you need to have like a lot of experience and then it will work out for you. But if you don't have a lot of experience, then it might not be as intuitive, especially when you're making like more complex apps. It will not be as obvious. And then, you know, because not everything can be done in KV, you're going to end up doing it in Python anyways. So like I said here, this method is the best, but it's also easier if you're an expert. If you're not an expert, it's fine to do things manually. It's fine to do things strangely, simply because there's like not a lot of style guides out there and not a lot of people to talk to about this and not a lot of resources, which is why, you know, KV school exists.
So what I mean by flat structure of solution one, all you have to do is handle the view class widget and properties. So for solution one, which is just updating properties, you need to handle your KV declare everything as a property correctly, and then structure the app to be easy to make with KV. It's not always possible. It's not immediately obvious like the complex apps. So keep in mind that. And then you might have to manually force updates anyways, especially if you're updating things in a deeper level, because they only track top levels. So the structure of the app, if you were to do this solution, one solution, you'd be like this, this is your KV app, right? This is your recycle view.
You initially update on in it your data, right? Your data is picked up on in it with the widget. Where are you? So RV data, you're picked up by this view class widget, which is two buttons, right? Picked up by two buttons. And then all these this view class, which this view class widget right here will handle all the updates. Why? Because you're using properties using string properties, list properties, any property from KV properties will force updates because you're modifying top level data. And then this simple view class widget will define instances. And then because you're manipulating properties, it will force updates, right? So if you have user input, it will be handled by the view class widget.
So if you go to like class two buttons, it will be defined here. It'll be handled. Well, there's not really anything going on because it's a simple app, but it will be handled with this view class widget. And then you as a dev, what you're supposed to do, implement behavior through KV and properties. Very simple. If someone had taught you about this, if you knew what was like, like if you watch this video, now you would know, okay, this is the correct way to do it, right? This is the not super correct way, but still a solution. So solution two, which is the KV school for me, this is my opinion. Okay. I don't represent everyone. My opinion. Okay.
Now you should use KV IDs. Where are you? You should use recycle KV IDs data view behavior simply because number one, you can use and manipulate complex widgets by referencing with ID in your RV data. I think for me, that's pretty cool because I even thought it was default behavior, right? It's not, you gotta use KV IDs. All you have to do is say IDs. You're going to say IDs anyway. If you're going to reference these widgets, most likely you're going to say IDs anyway. You can modify KV at any time. That's pretty cool to me, especially having that power to modify because if you're going to modify with properties, right? Again, you would have to set up the property and then you have to manipulate the properties correctly.
So, oh, here's the color example. We already ran the color example. Basically you can say, this is the ID of the widget dot color, and then it will change it. And then here's the trade off. You trade in property structure for ID structure, which you already need for widget drilling, which and widget drilling is basically calling app dot get ready app dot root IDs, IDs, IDs, you know, the correct IDs. Most likely you have IDs anyways.
So this is not too far off from what you're already doing. Now I'll tell you the cons to the solution. You must manually update recycle view with refresh from data. The easiest ways on touchdown on touch up looks laggy. This is because you're going to have a, oh, what's going on here? Okay. This is because you're going to have like just a complex dictionary. You're going to have a complex dictionary like this. And then if you change like a data in place, you will not trigger any refreshes.
So you will be forced to call refresh from data. And then I'll show you touch up and touchdown. So look right here on touchdown, right? Refresh from data looks like this. Now let's, uh, okay. First let's do touchdown touchdown, fast update, right? Fast update, but you do touch up will actually look like it's lagging. This tricked me because I was like, Oh man, I got to fix the lag. Actually it's not that it's because I'm touching down. It's not a big, when I touch up, it updates touchdown, touch up, right? So you really need to know the correct event, which is, you know, this is like a dev error. I admit that, but this is just to say, look, look at this. It looks laggy.
It's not laggy. It's just because you're using, or I was using the touch up event. It's not touch up. You should use touchdown to make it fast. So again, first touchdown, like this fast update, use the correct event. It's more complicated to update KV after initialization. You can't reference your cycle view data because it's not satiated yet. So this is just, um, you can't like say root.getdata. You have to set it up correctly. It's a little bit more complicated. Oh, here, here's another one. Calling refresh from, refresh from data from view class causes infinite refreshes. So where are you? There's two refresh from data that are really bug you out. Okay. I think it's just this one. So look at this. You manually call refresh from data. It will infinitely bug out like this. Why? Because okay, I got to kill this before it destroys my machine. Applying selection. When you add, when you add these widgets, apply selection is going to be called.
And then because it's called, it will trigger a refresh from data. And because you refresh from data, you get more widgets and the new widgets are going to check for apply selection, which then select, uh, forces a refresh. Let's keep in mind it, uh, infinite loop like that might happen with these manual, um, refreshes. Let's see. I've done this and done this. How to manually call refresh from data again, parent dot parent. It's just, um, recycle view right here. I think I can even PDB. I think that's an appropriate time. So again, on touchdown, let's check it out. Touchdown. So what's the artist, right? All of this, the, let's see, self is the box layout.
Uh, that's correct. This is the touch. Okay. A huge amount of data for the touch. Basically it just says where you are, what you're doing, the motion, I think. Okay. What next? So self, who is self? Box layout. What's your parent? Now, because I have a complex widget, actually, I'm selecting left. So I'm here with the emojis. Now the parent is going to be the box layout, selectable box layout, right? Oh, okay. No, that's self. Parent is going to be selectable box right here. Recycle box layout.
So we're here. This is the parent, right? Check parent again. Parent. Now the, now you're at the recycle view. So this is the self, selectable box layout. This is the parent, recycle box layout. This is the parent recycle view. Then from recycle view, directory of recycle view, you can see, um, refresh, refresh from data method. So that's why there's two parents because self is selectable box layout right here, here and here. Then the parent is going to be selectable recycle box layout.
Then the parent is going to be recycle view and recycle view is the one that's refreshed from data. So let's not fix it and turn off PDB. Okay. So with this method, you have to keep track of two things, recycle view data and forcing updates. And then my expectation is that manipulating data forces an update. It's not always the case with updating data in place, especially in a deeper level, which you will end up doing with the key IDs, KV IDs like this.
So recycle view refresh from data may be required. And here's the structure of solution two. The dev must handle recycle view data and manual refreshes. So again, there are recycle view. You update on init. This is the data. Data is picked up on init to the view class widget. So the view class widget is selectable box layout, which is this.
This widget determines the format of the instances, right? User input, the user will interact with the view class widget and their instances. And then you as a dev, you must correctly manipulate RV data to update these widgets. You must also call manual updates. And then while the user is interacting with these view class widget, you will get inputs that you must handle and you must handle this correctly in the RV data.
And you must handle these inputs correctly in the view class widget. You're also doing the updates here, but because the user input is handled by the view class widget and these properties are always automatically updating, it's a bit simpler with more, with a more, you know, thought out setup. Let's see what else. So Y2Parents, I said this already. See PDB.
Okay. And that's it. All right. So that was a long one. Thank you for watching. Like, comment, and subscribe.
Article Error Reporting¶
Message @BadMetrics on the Kivy Discord.