I'm developping an application for custom menu navigation in restaurants. I have finished my demo app for presentation purpose. My app contains a bunch of images that i added to the resource file. Now i want to create a short installation that gives people the opportunity to add their own images & menuitems to the App at runtime. Here's a screen of my app:
The images would be located on an AzureBlobStorage. A person will be able to give a unique key ( GUID ), the app would then connect to the azure MobileServices where a database is located, containing all the MenuItems ( Name, Category, ImageName,... ) and map it to it's own local SQL lite database. The images are .PNG files with 2 different dimensions. ( 150x150 & 1072x611 )
My question would be, what is the best approach for adding images to the application once the .APK has been created without losing speed?
Nothing you can do about the speed of retrieving from Azure (short of selecting a cloud service based on performance but Azure is probably as good as any) and assuming your SQL code is efficient, the Q becomes where and how to store/retrieve and how to keep the UI responsive as you download and install the images.
I would store in private storage since it's generally much higher performance than SDCard and has fewer unknowns.
You should also scale down the bigger images to the minimum resolution that still works on your highest resolution target devices for your UI. Remember that a bitmap in memory takes x*y*4 bytes by default which is about 2.6MB each in your case.
Android: high quality image resizing / scaling
I assume that the main UI you have shown is a ListView of some sort so you should be implementing lazy loading of the images and definitely recycling them in getView() in your underlying adapter.
Lazy load of images in ListView
There is not much you can do about the speed to download from the cloud so you should be doing that on a background thread, e.g. AsyncTask, and using placeholder images in your list view until the actual image is downloaded. Use notifyDataSetChanged() on your adapter to let the list view know that there's been a change.
http://android-developers.blogspot.co.uk/2010/07/multithreading-for-performance.html
http://codehenge.net/blog/2011/06/android-development-tutorial-asynchronous-lazy-loading-and-caching-of-listview-images/
Finally, if you really want a good Android OOP solution, consider implementing a content provider.
http://developer.android.com/guide/topics/providers/content-providers.html#creating
What is the use of private Content Providers?
Related
We're building an app (ios and Android) that lists ~1000 records. This list is displayed in a tableview/listview with an image related to each record displayed in the view. When a record is selected, a detail view opens up and displays multiple images related to that record.
What are some of the best (and simplest) ways to organise these image assets in both platforms and access them?
More info:
There is also a few lines of text related to each detailed screen. This also needs to be handled.
The images should be packaged with the app as the app will be used offline a lot.
For iOS ::
Collection view for display once selecting would probably be the most simple.
1000+ images? That is pretty big and will bloat your ipa for the store, also it locks you into having to add all images. You should really have those on a server and download them when needed, or download all on first load or something.
I'd have thumbnails or something for the tableview then when selected download the related images into a directory on the app bundle. That temp directory can act as your source. Just create a wrapper that reads the directory and creates and ImageObject for each image found (image and text description if available) and compile into a Dictionary with the key being whatever identifies each record.
The wrapper is an important layer when compiling all the images associated with the records because you can swap the implementation if needed as long as you maintain the interface contract of using a Dictionary to organize your data.
The tableview displays all the records and downloads the thumbnails when needed (this is pretty standard). Selecting the record then goes to a collection view that asks the wrapper for the records images/descriptions. The wrapper grabs the either from the system or the server and returns the dictionary. Then the collection view uses the dictionary as the data source displays all the images with the image descriptions
That's how I'd do it based off your vague specs anyhow.
First of all, it is definitely not recommended to store them in Core Data. Core Data has low performance and can't be cross-platform. I don't see any benefit in storing images into Core Data, and you need to serialize it when displaying.
I recommend that you store your records in a SQLite database. SQLite is a high-performance, cross-platform embedded database that is fully supported by both platforms.
Create a SQLite 3 database and store all the records, but there are two cases for the image:
The image is very small, such as the icon of the button, the number of images is less, then you can store them directly in the database.
The image is large, the number is large, then it should be stored in the system, only store the name or path of the image into database.
I recommend storing the image in the system, because blob data can't be queried and indexed. It's more troublesome when you need to do something with the image. Reading from the system will be more faster than reading from the database.
Images should be compressed before packaging. If the image is large, creating a corresponding thumbnail will improve UI fluency.
Then you just need to copy the database and images (if not stored in the database) to your apps. When the data changes in the future, you only need to replace the database for your apps.
I have a xamarin forms project for the company I work for. I have 6000+ images used in two ways : a thumbnail page and a full size page. I have both the thumbnail image and the full size image. The thumbnail page shows 12 products at a time, but it lives in a carousel page so it could have up to 18 content pages within the carousel.
I've tried three ways of saving/accessing the images:
Including them as bundle/android resources. This works the best but takes forever to build the project and on android will mean I have to use expansion files.
Included the binary image from the database when downloading the product listing. Causes the app to crash randomly on download.
Downloading all of the files from the web. This works, but on both Android and iOS, the thumbnail screen slows to a crawl and half of the time crashes on Android.
Has anyone had to do something similar and if so, what way did you decide to go? Unfortunately, this app does have to be usable offline so I need the images local. I'm kind of in a time crunch so any help would be appreciated!!
I had similar issues someday back and understood that it won't be successful with standard Image class with such a large amount of images (no memory caching, no task queueing, etc). Then I made CachedImage. It's basically an API compatible replacement for Image with advanced caching capabilities (and some other features). You could try that.
Just remember to use:
Downsampling feature : that way image would be resized to view size to save memory
Caching feature (it's enabled by default not including StreamImageSource for which you have to provide custom cache key factory)
Use FileImageSource (app dir) or StreamImageSource (eg. from image database) with custom cache keys
https://github.com/molinch/FFImageLoading (See WIKI for docs)
Lets consider the following, I have an app with several dozen photos I want to show the user at any given time.
Right now I'm creating multiple files for each image, sizing them for different screen sizes and storing them in their respective drawable folders.
It's increasing the size of my app dramatically.
So here is my question: Is it possible to store the images on a server and use an image library like Picasso, Fresco or something else (open to anything) to fetch that image and scale it down for the device it's running on without risking running out of memory?
I'm worried that fetching a large image, loading it into memory and then resizing it will cause the same problem as trying to display it on older devices with little memory available to them.
You can write methods to request different images sizes from your server based on client info. Just write a method to measure the screen size and then request the appropriate image based on a URL endpoint (like http://myimageserver.com/images/ldpi/image1.png).
You can do optimization post-download, such as scaling, before saving the image to a local file store.
Using a reputable image loading library is a valid method (my own favourite is Glide).
The answer to your question really depends on the number of images you want to show! If there are lots, then yes storing them on a server is probably best, but also the most time-consuming and expensive (both in time and money).
Your other (easier) option is to keep the originals in the assets folder, and use your image loader to scale and load them for you. The correct path for an image in your assets folder is file:///android_asset/your_image_here.jpg. This way, you're only keeping one version of each photo in your apk and they'll load much faster.
I am building an Android app that shows full screen images in a carousel. The app downloads 100 objects from the server and stores them in the app. Each object is represented by a full-screen image and some text.
The user will see all downloaded objects as full screen images.
Question: is it more efficient to use lazy loading one image at the time when the user goes through the carousel or download images in full batches?
Google suggests using batching and pre-fetching:
http://developer.android.com/training/efficient-downloads/efficient-network-access.html#BatchTransfers
Also, it is my understanding that one of the key benefits of lazy loading is avoiding downloading images that will not be used. In my case, the user will see all images of the all downloaded objects.
Thanks!
The first target is that the user sees the images without delay. By creating a batch starting from the first image it is probable that he will have the following images loaded when he scrolls through them. If in your case the user can scroll fast through the images, you can change the batch list and set a higher priority on the images he is going to see (like 3 plus and minus from the current position).
The question regarding thumbnail creation seems to get asked a great deal, and each time there seems to be a great many different solutions proposed. From my experience none of the supplied answers are actually sufficient and all seem to have their own flaws.
a) Memory issues when re-sizing
b) Performance issues / slow to render
I therefore wanted to post a question regarding a very common functional requirement that I am hoping someone can assist with.
'User generates a report using activity and takes associated photo using internal camera. The report along with the image path is saved to SQLLite database. User wants to view reports in a scrollable list view at some point in the future. Number of reports could be 1..100'
So given these requirements the questions I have are as follows
1) Given that to data I have not found a reliable / performent / memory optimised way of resizing full size images at run time to a given thumbnail, should I create a smaller image at image capture time?
2) If you need to display many items in a ListView should you use paging or should it be possible to display a 100 items in one ListView?
Thanks
Regarding number 2: What you could do is load a subset first (say the first 30, depending on your listview item size), and load the rest asynchronously and append them to your adapter. This will decrease the loading time of your screen.
1/ Why do you want to reinvent the wheel :) There are libraries that already do for you and do it well. See picasso or AQuery for instance (there are other libraries too).
Basically, they have a thumbnail cache somewhere on the SDcard/internal memory to keep last N requested thumbnails.
I don't know if you are keeping the image data within the database, in which case you may have to adapt one of those libraries to load the image data from the DB and not from a file as it is usually the case.
2/ Why do you want to reinvent the wheel :) There are libraries that already do for you and do it well. See https://github.com/commonsguy/cwac-endless for instance (and google for more)