recycleview on android

164 views
Skip to first unread message

purushottam yadav

unread,
Jul 9, 2021, 10:32:17 AM7/9/21
to Kivy users support
I want to display the images in the android device , using recycleview .


when recycle view is called  , it is calling  one function    ( takingper(self) ) to take permissions  and this function calls other function to load images into recycleview . 

 In this case apk is crashing on android just after starting , only blackscreen is displayed for 5 secs .  nothng I found in logs related to recycleview . 

when i tried to display images that are captured only today , In this case apk is taking 15 secs to display the images on the black screen . but it is working fine  , but why 15 secs just to display images . ?



from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.image import Image
from kivy.properties import (
    AliasProperty,
    BooleanProperty,
    BoundedNumericProperty,
    ListProperty,
    NumericProperty,
    ObjectProperty,
    OptionProperty,
    StringProperty,
)
from plyer  import storagepath
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
import glob
from kivy.utils import platform

Builder.load_string('''


<Piccollect>:
    #on_release: app.calll(root.source)



<RV>:

    viewclass: 'Piccollect'
    RecycleGridLayout:
        orientation: 'lr-tb'
        cols: 4
        spacing: ['5dp' , '10dp']
        padding: ['5dp']
        #default_size: None, dp(rv.width/self.cols*.6)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height

''')

class RV(RecycleView):

    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)


        self.takingper()


    def takingper(self):
        # only  Request permissions on Android , not loading images path
        if platform == 'android' :
            from android.permissions import Permission, request_permissions


            def call__back(permission, results):
                if all([res for res in results]):
                    print("Got all permissions>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
                    self.per = True
                    return self.loadaddress()
                    #print("called loadaddress function ======================")

                else:
                    print("Did not get all permissions>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")


            request_permissions([Permission.WRITE_EXTERNAL_STORAGE, Permission.READ_EXTERNAL_STORAGE], call__back)


    def loadaddress(self):

#this piece of code is for formatting the date string as required
            from datetime import date
            # calling the today
            # function of date class
            today = date.today()

            if len(str(today.month)) == 1 :
                self.m = "0" + str(today.month)
            else :
                self.m = str(today.month)

            if len(str(today.day)) == 1 :
                self.d = "0" + str(today.day)
            else :
                self.d = str(today.day)


            self.dddate = str(today.year) + str(self.m) + str(self.d)
            # self.dddate will be 20210709 as todays date is 9/7/2021

            print(str(self.dddate) , "date>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")



        if platform == 'android':
            print("loading....=============================")

            #In this case apk is taking 15 secs to display the images on the screen
            self.data = [{'source': file} for file in glob.glob(f"/storage/emulated/0/DCIM/Camera/IMG_{self.dddate}_*.*")]  #when i want to collect today captured images

            # In this case apk is crashing on android just after starting , only blackscreen is displayed for 5 secs
            #self.data = [{'source': file} for file in glob.glob(f"/storage/emulated/0/DCIM/Camera/IMG_*.*")]     #when i want to collect all the captured images (800 images ) in the device


            print(self.data)
            print(len(self.data))



class Piccollect(Image):
    source = StringProperty('')
    print("created=====================================================")
    def on_touch_down( self, touch ):

        if  self.collide_point( *touch.pos ):
            print("selecting......" , self.source)
            #k.calll(self.source)


class TestApp(App):
    def build(self):
        return RV()

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

Robert

unread,
Jul 9, 2021, 1:11:52 PM7/9/21
to Kivy users support
 In this case apk is crashing on android just after starting , only blackscreen is displayed for 5 secs .  nothng I found in logs related to recycleview .

when i tried to display images that are captured only today , In this case apk is taking 15 secs to display the images on the black screen . but it is working fine  , but why 15 secs just to display images . ?

As I understand, it takes a long time with a smaller amount of work and crashes with more work.

Perhaps the work is too hard?

1) I think there are other posts in this group about using lots of images with RV, Elliot would know better than me, I know nothing about RV. (but perhaps one solution might be loading thumbnails)

2) Android is very picky about UI responsiveness so slow tasks must not be in the UI thread. I'm gonna guess an unresponsive UI thread is the cause of the crash. But there may still be a latency issue, it may well benefit up to the number of threads equal to the number of cores - 1.

purushottam yadav

unread,
Jul 10, 2021, 7:46:34 AM7/10/21
to Kivy users support
what about this code this works fine on android without  any delay   , what is making above code crash but not this . 

this below code is displaying 1000 images , previous  code  should display  800 images .


        self.data = [{'source'    "download.jpg "  } for x in range(1000)   ]


    

class Piccollect(Image):
    source = StringProperty(' ')
    print("created=====================================================")
    def on_touch_down( self, touch ):

        if  self.collide_point( *touch.pos ):
            print("selecting......" , self.source)
           


class TestApp(App):
    def build(self):
        return RV()

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

Robert

unread,
Jul 10, 2021, 12:39:43 PM7/10/21
to Kivy users support
Presumably because this is only one file.
Message has been deleted

purushottam yadav

unread,
Jul 12, 2021, 9:24:46 AM7/12/21
to Kivy users support

Any suggestions from Elliot and any other member of this group about how to display large number of widgets in  android ?

Elliot Garbus

unread,
Jul 12, 2021, 10:19:26 AM7/12/21
to kivy-...@googlegroups.com

Some suggestions.

Here are a few things I see in your code.

 

I suspect your issue is: You have redefined source in Piccollect.  Image has an attribute source.  You have added a kivy property named source.  Just use self.source of Image.

 

Use a ListProperty to for the rv data.

In the kv code add it…

<RV>:

    data: self.rv_data

    viewclass: 'Piccollect'

    RecycleGridLayout:

        orientation: 'lr-tb'

        cols: 4

        spacing: ['5dp' , '10dp']

        padding: ['5dp']

        #default_size: None, dp(rv.width/self.cols*.6)

        default_size_hint: 1, None

        size_hint_y: None

        height: self.minimum_height

 

And in Python:

class RV(RecycleView):

    rv_data = ListProperty()

 

 

I also suggest you move your permission code, takingper() to the on_start method of app.  The __init__ of recycle view is an odd place for this code.

 

 

Make sure your code is running on a desktop, then add the android specifics.

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/d962bf45-6173-4c5e-ad9d-7b9492008659n%40googlegroups.com.

 

purushottam yadav

unread,
Jul 18, 2021, 2:35:00 PM7/18/21
to Kivy users support
This  is a memory issue .  Someone online suggested me that  

 "if your code works with few images, then your code is not broken. i would assume there's a memory issue here and simply too much data. try running it on a more powerful desktop and see if it works in principle... "

After this I used AsyncImage  for piccollect instead of  Image . 

This can be useful as it prevents your application from waiting until the image is loaded. If you want to display large images or retrieve them from URL’s, using AsyncImage will allow these resources to be retrieved on a background thread without blocking your application.



class Piccollect(AsyncImage):  ,  Now there is no delay on starting the app  in all the cases , but it has delay to display images  in all the  cases  .

 when I tried to display  few images , there was no delay to start but default images were displayed for a while ( 2 secs )  , and actually images where displayed . 
 

 when I tried to display  all the  images , there was no delay to start but default images were displayed for a while ( 2 secs )  , and actually images started to display and again  APK CRASHED   , and my phone got hanged for  a while .     



Below are screen shots  during that  2 secs of loading  the images  . 

 Now the problem is that while displaying few images  APK did not CRASH  but CRASHED  when tried to display all the images in the android device . 

I guess  , this is because of loading alot of data at once  .

why this is happening and how to handle this issue    ? 


WhatsApp Image 2021-07-18 at 11.32.25 PM.jpegWhatsApp Image 2021-07-18 at 11.32.25 PM (1).jpeg
 

Elliot Garbus

unread,
Jul 18, 2021, 2:50:22 PM7/18/21
to kivy-...@googlegroups.com

Share a minimal executable that demonstrates the issue. 

 

From: purushottam yadav
Sent: Sunday, July 18, 2021 11:35 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: recycleview on android

 

This  is a memory issue .  Someone online suggested me that  

 

 "if your code works with few images, then your code is not broken. i would assume there's a memory issue here and simply too much data. try running it on a more powerful desktop and see if it works in principle... "

 

After this I used AsyncImage  for piccollect instead of  Image . 

 

This can be useful as it prevents your application from waiting until the image is loaded. If you want to display large images or retrieve them from URL’s, using AsyncImage will allow these resources to be retrieved on a background thread without blocking your application.

 

 

class Piccollect(AsyncImage):  ,  Now there is no delay on starting the app  in all the cases , but it has delay to display images  in all the  cases  .

 

 when I tried to display  few images , there was no delay to start but default images were displayed for a while ( 2 secs )  , and actually images where displayed . 

 

 

 when I tried to display  all the  images , there was no delay to start but default images were displayed for a while ( 2 secs )  , and actually images started to display and again  APK CRASHED   , and my phone got hanged for  a while .     

 

 

 

Below are screen shots  during that  2 secs of loading  the images  . 

 

 Now the problem is that while displaying few images  APK did not CRASH  but CRASHED  when tried to display all the images in the android device . 

 

I guess  , this is because of loading alot of data at once  .

 

why this is happening and how to handle this issue    ? 

 

 

 

WhatsApp Image 2021-07-18 at 11.32.25 PM.jpeg
WhatsApp Image 2021-07-18 at 11.32.25 PM (1).jpeg

purushottam yadav

unread,
Jul 18, 2021, 2:58:36 PM7/18/21
to Kivy users support
I have attached main file . 
main.py

Elliot Garbus

unread,
Jul 19, 2021, 10:22:11 AM7/19/21
to kivy-...@googlegroups.com

In the code below I have made a few changes, some are fixes some are just style so I could run the app on my laptop.  My guess is the fundamental issue is that you are dealing with a large number of high resolution images on the phone.  I would recommend you create thumbnails for all of the images and display the thumbnail.  The app can switch to the full resolution image when required.  You may consider storing the thumbnails or the path to the thumbnails in an SQLite database.  There may already be a SQLite database on the phone for picture thumbnails – I know apple does it this way.

 

# from tile import SmartTile
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ListProperty

from kivy.uix.image import Image
from kivy.uix.recycleview import RecycleView
from kivy.utils import platform


from pathlib import Path

# from tile import SmartTile

kv = '''
<PicCollect>:
    #on_release: app.calll(root.source)

<RV>:
    viewclass: 'PicCollect'
    data: self.rv_data

    RecycleGridLayout:
        orientation: 'lr-tb'
        cols: 4
        spacing: ['5dp' , '10dp']
        padding: ['5dp']
        #default_size: None, dp(rv.width/self.cols*.6)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height

BoxLayout:
    RV:
        id: rv
'''


class RV(RecycleView):
    rv_data = ListProperty()

   
def __init__(self, **kwargs):
       
super(RV, self).__init__(**kwargs)
       
# self.takingper()
       
self.dd = None  # used for building the rv_data list

    # def on_start(self):                  # These are all methods of App, not RecycleView
    #     print("created  app  " * (20))
    #
    # def on_stop(self):
    #     print(" stoped  app  " * (20))
    #
    # def on_pause(self):
    #     print(" paused   app  " * (20))
    #
    # def on_resume(self):
    #     print(" resumed  app  " * (20))

   
def takingper(self):
       
# only  Request permissions on Android , not loading images path
       
if platform == 'android':
           
pass
           
# from android.permissions import Permission, request_permissions
            #
            # def call__back(permission, results):
            #     if all([res for res in results]):
            #         print("Got all permissions>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
            #         self.per = True
            #         return self.loadaddress()
            #         print("called loadaddress function ======================")
            #
            #     else:
            #         print("Did not get all permissions>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
            #
            # request_permissions([Permission.WRITE_EXTERNAL_STORAGE, Permission.READ_EXTERNAL_STORAGE], call__back)

       
else:
           
self.load_address()

   
def load_address(self):

       
# this piece of code is for formatting the date string as required
       
from datetime import date
       
# calling the today

        # function of date class
       
today = date.today()
       
self.dddate = f'{today.year}{today.month:02d}{today.day:02d}'
       
# if len(str(today.month)) == 1:
        #     self.m = "0" + str(today.month)
        # else:
        #     self.m = str(today.month)
        #
        # if len(str(today.day)) == 1:
        #     self.d = "0" + str(today.day)
        # else:
        #     self.d = str(today.day)
        #
        # self.dddate = str(today.year) + str(self.m) + str(self.d)


        # self.dddate will be 20210709 as todays date is 9/7/2021

       
print(str(self.dddate), "date>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
       
# self.dd = []

       
if platform == 'android':
           
print("loading....=============================")

           
# for file in glob.glob(f"/storage/emulated/0/DCIM/Camera/IMG_{self.dddate}_*.*")  :
            # shutil.copy( str(file) ,  ".")
            #    self.dd.append({ 'source' : str(file) } )

            # In this case apk is taking 15 secs to display the images on the screen
            # self.dd = [{'source': file} for file in glob.glob(
            #     f"/storage/emulated/0/DCIM/Camera/IMG_{self.dddate}_*.*")]  # when i want to collect today captured images


            # In this case apk is crashing on android just after starting , only blackscreen is displayed for 5 secs
            # self.dd = [{'source': file} for file in glob.glob(f"/storage/emulated/0/DCIM/Camera/IMG_*.*")]     #when i want to collect all the captured images (800 images ) in the device

       
else:
           
print("load_address, not android")

           
# self.dd = [{'source': file} for file in glob.glob(f"home/purushottam2/Pictures/*.*")]
           
p = Path.home() / 'OneDrive'/ 'Pictures' / 'family pics
           
self.dd = [{'source': str(file)} for file in p.glob('*.jpg')]

           
# from plyer import storagepath

            # for root, dirs, files in os.walk(str(storagepath.get_pictures_dir())):
            #     for file in files:
            #         if (file.endswith(".jpeg")) or (file.endswith(".png")):
            #             ss = str(os.path.join(root, file))
            #
            #             self.dd.append({'source': ss})

       
self.rv_data = self.dd
       
# print(f'{len(dd)}')
        # print(f'{self.rv_data}')
        # print(f'len(self.rv_data))
        # print(self.data)
        # print(len(self.data))


class PicCollect(Image):
   
# source = StringProperty('')
    # nocache = True
    # print("created=====================================================")

   
def on_touch_down(self, touch):
       
if self.collide_point(*touch.pos):
           
print("selecting......", self.source)
           
# k.calll(self.source)


class TestApp(App):
   
def build(self):
       
return Builder.load_string(kv)

   
def on_start(self):
        
self.root.ids.rv.takingper()


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

 

 

From: purushottam yadav
Sent: Sunday, July 18, 2021 11:58 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: recycleview on android

 

I have attached main file . 

On Monday, July 19, 2021 at 12:20:22 AM UTC+5:30 ElliotG wrote:

Share a minimal executable that demonstrates the issue. 

 

From: purushottam yadav
Sent: Sunday, July 18, 2021 11:35 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: recycleview on android

 

This  is a memory issue .  Someone online suggested me that  

 

 "if your code works with few images, then your code is not broken. i would assume there's a memory issue here and simply too much data. try running it on a more powerful desktop and see if it works in principle... "

 

After this I used AsyncImage  for piccollect instead of  Image . 

 

This can be useful as it prevents your application from waiting until the image is loaded. If you want to display large images or retrieve them from URL’s, using AsyncImage will allow these resources to be retrieved on a background thread without blocking your application.

 

 

class Piccollect(AsyncImage):  ,  Now there is no delay on starting the app  in all the cases , but it has delay to display images  in all the  cases  .

 

 when I tried to display  few images , there was no delay to start but default images were displayed for a while ( 2 secs )  , and actually images where displayed . 

 

 

 when I tried to display  all the  images , there was no delay to start but default images were displayed for a while ( 2 secs )  , and actually images started to display and again  APK CRASHED   , and my phone got hanged for  a while .     

 

 

 

Below are screen shots  during that  2 secs of loading  the images  . 

 

 Now the problem is that while displaying few images  APK did not CRASH  but CRASHED  when tried to display all the images in the android device . 

 

I guess  , this is because of loading alot of data at once  .

 

why this is happening and how to handle this issue    ? 

 

 

 

On Monday, July 12, 2021 at 7:49:26 PM UTC+5:30 ElliotG wrote:

purushottam yadav

unread,
Jul 21, 2021, 8:49:56 AM7/21/21
to Kivy users support
I did not notice     .thumbnails      folder  in DCIM till now . 

I just made below  change and  now everything is fine and application is working good . 
But I dont know  how to identify the thumbnail for particular image .
I have image captured with name IMG_20210720_001512.jpg  , how do I know thumbnail image name is 1626723980890.jpg ?
  


        if platform == 'android':
            print("loading....=============================")
            self.rv_data = [{'source': file} for file in glob.glob(f"/storage/emulated/0/DCIM/.thumbnails/*.*")]     #when i want to collect all the captured images (800 images ) in the device





Elliot Garbus

unread,
Jul 21, 2021, 12:33:23 PM7/21/21
to kivy-...@googlegroups.com

I have no idea… search google, look in the exif data of the thumbnail, see if you can find a SQLite database file.

purushottam yadav

unread,
Jul 23, 2021, 12:06:32 PM7/23/21
to Kivy users support
Any suggestions from ROBERT  or ANYONE  on this issue 

 I dont know  how to identify the thumbnail for particular image  in android device . 
I have image captured with name IMG_20210720_001512.jpg  , how do I know thumbnail image name is 1626723980890.jpg ?
 
By the way , Should I raise this as  a separate issue ?

Robert

unread,
Jul 23, 2021, 12:48:06 PM7/23/21
to Kivy users support
You are not going to like it.....

So the question is about Android's management of a particular type of hidden file.
I get that you can see the files, but seeing how Android associates them is not the same thing.

A couple of minutes with Google shows there appear to be two approaches.
From Python both would involve Pyjnius.

1) MediaStore        
2) ThumbnailUtils

Option 2) is not available to you because it requires a ContentResolver, you could modify p4a to include one but it is non trivial. So I expect option 1) , first  you will have to learn about a 'uri'.

There may be some other way, as Elliot said ...research.... If you find a clever solution please share.

Robert

unread,
Jul 23, 2021, 3:38:41 PM7/23/21
to Kivy users support
It occurs to me that if you never want to run on Android 10 or higher:

A) Try sorting the image list and the thumbnail list by file creation date. Very Pythonic but it might not work.

B) Create your own thumbnails, perhaps using Pillow (in a thread), though sampling a texture might be faster.

No I don't have an example.
Reply all
Reply to author
Forward
0 new messages