Kivyschool link: https://kivyschool.com/blog/2024/06/10/recycleview-explained/
- Recycleview VS Scrollview example and explanation
- kivy recycleview tutorial DEEP DIVE for beginners: recycleview vs scrollview, examples, and analysis
- github repo: https://github.com/kivy-school/recycleex
- What is recycleview?
- a widget that displays a selection of many widgets at once
- Why use recycleview? (telling) PT1
- very performant (not laggy)
- lets your app handle a LOT of data without having to DRAW the data (aka lag out your app)
- use case:
- handling inventory
- handling a library of songs
- handling complex widgets that are lagging out scrollview
- concrete example:
- note: using always on top = True
- have workers that you need to pay! (signified by the selection behavior)
-
workers_paid.py
- WHY USE Recycleview (showing) PT2
- basic example (from kivy org),
rvbasic.py
- basic example of scrollview:
scv.py
- recycleview VS scrollview (performance test)
- try at 1000 widgets
- try at 10000 widgets
- try at 100000 widgets
- basic example (from kivy org),
- EXAMPLES:
- basic example2 (from kivy org)
rvbasic2.py
- elliot's example: https://www.reddit.com/r/kivy/comments/1d5y3jm/recycle_view_the_replacement_for_listview_but/
- all the examples from kivy org
- PREREQ: "Kivy: How to Install and Run in Windows 2024 With Examples":
- https://www.youtube.com/watch?v=qiIFJIqMHV0&t=148s
-
python -m pip install "kivy[base]" kivy_examples
- Then you can run the code in place from .venv/share/kivy-examples/demo/kivycatalog/main.py
- https://www.reddit.com/r/kivy/comments/1d6dzvp/trying_to_get_this_example_from_kivyorgs_samples/
- basic_data
- populate, sort, clear
- inifinite_scrolling
- has infinite scroll
- key_viewclass
-
key_viewclass: 'widget'
means it will show your widget, and you are not locked to a fixed size for recycleview
-
- messenger
- messenger example
- pull_to_refresh
- (pull from top), self explanatory
- rv_animate
- has animation on press
- more examples from online:
- forceupdate.py has an updating textinput
- init_rv_data.py has an initialized list + updates
- screenmanagertoRV, has a screenmanager that goes to an RV in a screen
- SKIP: rvbasic3, rvbasic4
- PREREQ: "Kivy: How to Install and Run in Windows 2024 With Examples":
- basic example2 (from kivy org)
- REQUIREMENTS FOR A RECYCLEVIEW (use basic example 1)
- go LINE BY LINE on rv basic and elliot's example
- NOTE: using
Builder.load_string()
to loadkv
instead of having a separatekv
file
- NOTE: using
- reference: https://stackoverflow.com/a/68364350
- #1: RV widget CLASS (kv and py defs)
- means: USE BRACKETS
-
RV: != <RV>
-
RV:
is a widget instance -
<RV>
is the class definition - see: https://kivy.org/doc/stable/guide/lang.html#rule-context
- #2: Layout (kv and py defs)
-
SelectableRecycleBoxLayout
,RecycleLayout
-
- #3: actual viewclass (kv and py defs)
- defined as
viewclass:
orkey_viewclass
- defined as
- #4: .data attribute
- self.data (the data attribute of the recycleview widget that a list of dictionaries)
- could be something else, see ElliotDG line:
-
data: self.rv_data_list
-
- .data is a LIST and each element is a DICT
- Example:
- need:
data: data
AND it is a Listproperty- equivalent to setting
rv.data
attribute
- equivalent to setting
- need:
- proof:
type(self.data)
,type(self.data[0])
, usepdb
(line 68) -
pdb hints
:-
App.get_running_app().root
- hint: in
ElliotDG.py
, just look at rv.data: -
App.get_running_app().root.ids['rv'].data
- every widget needs an id for "widget drilling" to work?
-
- populated during
__init__
, can be updated at any time
- #5: ISSUES WITH WIDGET EXAMPLE FROM KIVY ORG:
- ISSUE: forcing recycleview to update (specifically updating in place in a deep level), the example minimally modified does not do that for you
- Essence of the issue:
- https://kivy.org/doc/stable/api-kivy.properties.html#depth-being-tracked
- KV properties only track the top level
- how to force rv to update:
- manually call
recycleview.refresh_from_data()
- manually call
- other solutions to update data:
- SOLUTION 0 choose to reset rv.data (does not manually call
.refresh_from_data()
)- example:
rv.data = [{'text': 'new data'}]
- very bad if you have large data
- it will force an update
- DON'T DO IT!
- example:
- SOLUTION 1 choose to update Properties (does not manually call
.refresh_from_data()
)- ElliotDG's solution (standard solution):
declare interactdatalist as a kivy ListProperty
- https://www.reddit.com/r/kivy/comments/zzmkg0/comment/j2e456n/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
- use kv structure itself to force automatic updates
- ElliotDG's solution (standard solution):
- SOLUTION 2 choose to update the recycleview data itself + force rv to update with
recycleview.refresh_from_data()
- my solution (use RecycleKVIDsDataViewBehavior)
- https://kivy.org/doc/stable/api-kivy.uix.recycleview.views.html
- I SPENT 4 DAYS LOOKING FOR THIS (I thought it was default behavior all this time)
- you might have to reference viewclass widgets by ID
- OPINION: makes it easier to make and handle complex viewclass widgets
- my solution (use RecycleKVIDsDataViewBehavior)
- SOLUTION 0 choose to reset rv.data (does not manually call
- go LINE BY LINE on rv basic and elliot's example
SOLUTION 1 (ELLIOTDG) PRO | SOLUTION 1(ELLIOTDG) CON |
---|---|
structure is flat (handle everything through Viewclass Widget and properties) | you have to manually remember to property EVERYTHING |
have to set everything up correctly | a bit hard to manipulate the boxlayout viewclass as easily (I have been trying for 2 days) |
still might have to call refresh_from_data if you modify data in place | |
not everything can be done in kv (kv lang MUST be perfectly set up) | |
method is the best, but also easier if you are an expert. |
What I mean by a flat structure of Solution 1, all you have to handle is Viewclass Widget and Properties
- handle KV
- declare everything as a property correctly
- structure the app to be easy to make with kv (not always possible or immediately obvious, like with complex apps)
- might have to manually force update anyways
graph BT
subgraph KivyApp
A((RecycleView))
AA[RecycleView.data]
B((Simple Viewclass Widget))
BB[Properties, String, List, any property from kivy.properties]
C((Viewclass Widget Instances))
A -- initially updates on __init__ --> AA
AA -- data is picked up on init --> B
B -- updates after init --> AA
B -- handles updates --> BB
BB -- defines --> C
end
D{{user input}}
E{{dev manipulation}}
D -- is handled by ----> B
E -- implements behavior through KV and properties ----> B
SOLUTION 2 (KIVYSCHOOL/PENGUIN) PRO | SOLUTION 2 (KIVYSCHOOL/PENGUIN) CON |
---|---|
can use/manipulate very complex widgets by referencing with id | you must manually update the recycleview with recycleview.refresh_from_data() . easiest way is on_touch_down, on_touch_up looks laggy |
all you have to do is set ids | more complicated to update from kv after init, you cannot reference recycleview data because it is not instantiated yet |
You can modify kv at any time | calling rv.refresh_from_data() from viewclass causes infinite refreshes (because each viewclass widget will cause a refresh...) |
color example App.get_running_app().root.data[index]['employee_name_labelID.color'] = (170,170,170) |
SelectableBoxLayout's apply_selection will have infinite updates |
trade in property structure for id structure (which you NEED for widget drilling). Widget drilling is App.get_running_app().root.ids ids ids ids.... |
have to manually call refresh_from_data |
- you have to keep track of 2 things: Recycleview data and forcing updates
- my expectation is that manipulating data forces an update. It is not always the case with updating data in place, so
recycleview.refresh_from_data()
may be required.
Structure of Solution 2, the dev must handle RecycleView Data and manual refreshes
graph BT
subgraph KivyApp
A((RecycleView))
AA[RecycleView.data]
B((Simple Viewclass Widget))
C((Viewclass Widget Instances))
A -- initially updates on __init__ --> AA
AA -- data is picked up on init --> B
B -- determines format of --> C
end
D{{user input}}
E{{dev manipulation}}
D -- interacts with ----> B
B -- sends inputs for devs to handle ----> E
E -- correctly manipulates ----> AA
E -- calls manual updates ----> B
-
why 2 parents at
self.parent.parent.refresh_from_data()
inworkers_paid.py
?- use pdb
- notes:
- canvas.before goes before everything else
- how to use pdb to check out what's going on:
-
workers_paid
, on touch down set trace - example: flipping sadface to happy face (since they got paid)
- get running app
- get root:
App.get_running_app().root
- check out id's (nothing)
- check out .children[0]
- check out self
- check out
__name__
- check out
dir()
-
exit
- get args:
args
-
- notes:
- use pdb
-
=-=-=-==-=-=-==-=-= FINISH ! =-==-=-=-==-=-=-==-=-=-=