title: Kivy Treeview for a directory structure consumes lot of memory
body: <p>I have an application which reads file from the usb drive to process further, So I have created the directory structure of the USB using the Treeview in Kivy. Each node of the Treeview is a Boxlayout which contains a Checkbox and a Label. We can select the files by clicking the Checkbox of respective File/Folder name. The challenge I am facing is if the directory structure contains more than 5000 files, the memory consumed is high when it is listed in the treeview and the application gets slow, if it is more than 10000 then the application freeze and sometime the application will get crash due to low memory.</p>
  <p>Please find the below code, I am loading the files from the folder /USBDRIVE to load the files, kindly create the folder and have some files in it, then execute the below python program</p>
  <pre><code>from kivy.app import App
  from kivy.uix.boxlayout import BoxLayout
  from kivy.uix.checkbox import CheckBox
  from kivy.uix.label import Label
  from kivy.uix.scrollview import ScrollView
  from kivy.uix.treeview import TreeView , TreeViewNode
  from kivy.clock import Clock
  from kivy.metrics import dp
  
  import os
  import subprocess
  from functools import partial
  import time
  
  
  file_folder_select={}
  selected_node=''
  class MyEachNode(BoxLayout):
  
      def __init__(self, **kwargs):
          self.text = kwargs.pop('text', 'None')
          super(MyEachNode, self).__init__(**kwargs)
          global file_folder_select, selected_node
          self.orientation = 'horizontal'
          self.base_name=os.path.basename(self.text)
          self.parent_name=os.path.dirname(self.text)
          self.size_hint_y = None
          self.height = dp(60)
          self.padding=(20,0,20,0)
          # make the parts of the node
          self.lbl = Label(text=self.base_name, size_hint_x=0.5, halign=&quot;left&quot;, valign=&quot;center&quot;, bold=True, font_size=25)
          #self.chkbx_each_node = CheckBox(size_hint_x=0.01, color=(1, 1, 1, 3.5))  # alpha=3.5 to make it more visible
          self.chkbx_each_node=CheckBox(size_hint_x= None, size_hint_y= None, height=60, width=50)
          #self.chkbx_each_node.background_checkbox_normal = 'includes/unchecked.png'
          #self.chkbx_each_node.background_checkbox_down = 'includes/checked.png'
          file_folder_select[self.text]=self.chkbx_each_node
          self.chkbx_each_node.bind(active=self.on_checkbox_active)
          self.lbl.bind(size=self.lbl.setter('text_size'))
          # add the parts to the BoxLayout
          self.add_widget(self.chkbx_each_node)
          self.add_widget(self.lbl)
          #if os.path.isfile(self.text):
          try:
              file_folder_select[self.text].active=file_folder_select[self.parent_name].active
          except:
              pass
      def on_checkbox_active(self,checkbox, value):
          global selected_node
          if os.path.isdir(self.text):
              self.folder_files=subprocess.getoutput(&quot;find \'%s\'&quot; %self.text)
              #for self.entries in  self.folder_files.splitlines()[:2]:
              if not selected_node in self.folder_files.splitlines():
                  for self.entries in  self.folder_files.splitlines():
                      try:
                          file_folder_select[self.entries].active = value
                      except:
                          pass
              else:
                  selected_node=''
              if value == False:
                  try:
                      if file_folder_select[os.path.dirname(self.text)].active == True:
                          selected_node=str(self.text)
                      file_folder_select[os.path.dirname(self.text)].active = value
                  except:
                      pass
                  
          else:
              if value == False:
                  #print(self.text)
                  try:
                      if file_folder_select[os.path.dirname(self.text)].active == True:
                          selected_node=str(self.text)
                      file_folder_select[os.path.dirname(self.text)].active = value
                  except:
                      pass
                  
  class MyTreeNode(MyEachNode, TreeViewNode):
      pass
  
  
  class MyTreeView(TreeView):
      def __init__(self):
          super(MyTreeView, self).__init__()
          self.size_hint_y=None
          self.bind(minimum_height=self.setter('height'))
          #self.on_node_expand=self.node_exp()
          self.bind(on_node_expand=self.node_exp)
          self.root_options={'text': 'USBDRIVE', 'bold':True, 'font_size':25}
          # The usb drive is mounted in /USBDRIVE or you can copy the files to /USBDRIVE
          self.my_drive='/USBDRIVE'
          self.extracted={}
          self.folder_files=subprocess.getoutput(&quot;find \'%s\' -maxdepth 1 &quot; %self.my_drive)
          self.nodes={}
          self.create_nodes()
      def create_nodes(self, *largs):
          for self.entries in self.folder_files.splitlines():
              self.dir_name=os.path.dirname(self.entries)
              self.base_name=os.path.basename(self.entries)
              if  self.dir_name != &quot;/&quot;:
                  #if len(self.folder_files) &lt;= 5500:
                      self.nodes[self.entries]=self.add_node(MyTreeNode(text=self.entries))
                      if os.path.isdir(self.entries):
                          self.nodes[self.entries].is_leaf=False
                  # else:
                  #     break
      def node_exp(self, node, exp_node):
          global running_windows, my_pid, file_manager_widget, file_folder_select
          self.exp_node=exp_node
          if not ( self.exp_node.text == 'USBDRIVE' or self.exp_node.text == 'DVDDRIVE'):
              if self.exp_node.is_loaded == False:
                  self.keys = [self.k for self.k, self.v in self.nodes.items() if self.v == self.exp_node]
                  self.folder_files=subprocess.getoutput(&quot;find \'%s\' -maxdepth 1 &quot; %self.keys[0])
                  Clock.schedule_once(partial(self.add_childs_inside_node, exp_node))
  
      def add_childs_inside_node(self,exp_node, *largs):
          global my_pid, running_windows, file_folder_select
          self.mycount=0
          for self.entries in self.folder_files.splitlines():
              # if len(file_folder_select) &lt;= 5500:
                  if self.mycount != 0:
                      if (self.mycount%1000) == 0 :
                          time.sleep(1)
                  self.dir_name=os.path.dirname(self.entries)
                  self.base_name=os.path.basename(self.entries)
                  if  self.dir_name == self.keys[0]:
                      self.mycount+=1
                      self.nodes[self.entries]=self.add_node(MyTreeNode(text=self.entries),self.nodes[self.keys[0]])
                      if os.path.isdir(self.entries):
                          self.nodes[self.entries].is_leaf=False
              # else:
              #     break
          self.exp_node.is_loaded=True
  
      def hide_widget(self,wid, dohide):
          if hasattr(wid, 'saved_attrs'):
              if not dohide:
                  wid.height, wid.size_hint_y, wid.opacity, wid.disabled = wid.saved_attrs
                  del wid.saved_attrs
          elif dohide:
              wid.saved_attrs = wid.height, wid.size_hint_y, wid.opacity, wid.disabled
              wid.height, wid.size_hint_y, wid.opacity, wid.disabled = 0, None, 0, True
  
  
  
  
  
  
  
  class FilelistApp(App):
         
      def build(self):
          
          MainBox = BoxLayout()
          InsideBox=BoxLayout(size_hint_y=.9)
          self.file_folder_tree=MyTreeView()
          self.scroll_view=ScrollView(size_hint=(1, 1),do_scroll_y=True,size=InsideBox.size)
          self.scroll_view.pos_hint_x=0
          self.scroll_view.pos_hint_y=1
          MainBox.add_widget(InsideBox)
          InsideBox.add_widget(self.scroll_view)
          self.scroll_view.add_widget(self.file_folder_tree)
   
          return MainBox
   
  root = FilelistApp()
     
  
  root.run()
  </code></pre>