Array adapter, image downloader and internal storage - android

Note
This question is not aiming code answers. It intend to get some ideas
for best code practices that deals with the problem proposed.
Problem
List view that is connected as usual with array adapter of countries.
country object have 2 attributes. an image url and country name. at
the very first time images will be downloaded from the url and must be
saved on the internal memory. next time images will be loaded from the
internal memory if exist. otherwise, they will be downloaded.
What is the best structure to solve this problem?
Spot lights
a bitmap object is the container that a download steam will write to.
an image in the internal will also be sit to the bitmap object before we set bitmap to the image view.
(is this point optional) a bitmap ref. should be a member of the country class.
on download complete the downloaded image may and may not still needed because it's view is no longer visible (actually it is visible
but another country owns it). is it better to check that before we set
the image bitmap. or its better to just notify data changed.
What do you think?

Use this library for image downloading
https://github.com/nostra13/Android-Universal-Image-Loader
It has tons of features, you can cache in memory or on disk, has image loading events, and a ton of more stuff.

Related

Image Caching With Anroid Libraries

My app is getting a list of movie objects, which includes a movie poster url, and it's displaying those posters and titles, then when a user clicks on that movie, it goes to a movie detail activity, that also has the poster and title, along with some more info. Pretty simple. I've noticed though that when I click the movie, there's still a second or two where the poster hasn't loaded, and I'd like to eliminate that, which seems relatively easy with caching. I was using Picasso, I recently switched to Coil for image loading, and they both claim to handle caching behind the scenes, but I'm assuming that isn't happening because of this loading time. In both activities I'm just loading it with:
posterImageView.load(it.posterURL ?: {url of "no poster found" image})
Is there anything extra I need to be doing in order to be loading these from cache instead of loading the image from url every time?
According to the official documentation here you should use LruCache as defined in here. But there is also a way around:
For storing a large number of images you should first create a temporary folder that can only be accessed by your application (usually inside data/data/package_name/) and then save every image you download for the first time in that folder giving the key as the name of the image. After that whenever you need to show the image just use the " if " condition to check if the image for that particular key (the name from which you saved the image) is stored or not. If it is then show the image. (Just remember to clear the folder images another time the app is opened).

How to fix long delays in an app with Bitmaps?

I'm making an android app where you can add items to a RecyclerList and the items contain an image and some text but the app takes a long time to start up and resume due to those Bitmaps.
The way my app works is this: When you add a new items to the RecyclerView it prompts you for an image and then I decode that into a Bitmap (I reduce the image size) and save it in that Item's data model. Then on onBindViewHolder() I get the image from the Item and add it to the Layout. Also on onCreate() I iterate through all the saved Bitmaps (Saved in a folder) and initialize my list from there but this takes a relatively long time.
How can I make the Bitmaps load faster so that the app won't have long delays on onCreate() and onResume() (This one is because of the RecyclerView)?
What I thought about was maybe not saving the Bitmaps in the item at all since I'm saving a UUID and the UUID is the Bitmap's file name so this way I only load the images in onBindViewHolder() and then I can immediately recycle() them but I don't know if this will work.
I also read something about LruCache but I didn't really understand it, can it help in my case?
If there's any more information I should post about my app so answering this will be easier please tell me.
EDIT: The images are prompted and are from the user's gallery.

Best practice of storing and loading a lot of images in a ListView

My application has a ListView.
The ListView has lots of images.
1) What is the best/most efficient way to preload these images into my ListView? (I am setting the images in bindView() of SimpleCursorAdapter). Should I store them as assets, raw files or in the drawable directory?
If I store my images in drawable, I basically have their name but not the int resource.
2) Is getIdentifier() the way to go here?
The application queries the server if a new set of images are available. If they are available it lazy downloads them and stores them into the cache. Now the old images are useless.
3) Is there any way to get rid of them?
I suggest you to try Picasso.It takes care of handling cache and image loading.
In the getView method of the Adapter class, all you need is one line of code.
Picasso.with(context).load(image_url).into(holder.imageView);
What is the best/most efficient way to preload these images into my
ListView?
You are already using LazyList so that's perfetct
Should I store them as assets, raw files or in the drawable directory?
That depends on your choice
Is there any way to get rid of them?
yeah go to the FileCache class in lazylist,that in there there would be a variable cacheDir
which actually tells you the directory where the older/cached images are stored and hence you can perform whatever you want to,from there
Edit: here is the link for lazylist
https://github.com/thest1/LazyList
what it does is,it downsamples the images before loading into the iamgeview hence saving a lot of memory,i guess it uses viewholder pattern and hence nothing to worry about memory leaks also it loads images asynchronously and hence UI doesn't lag for the time images are being loaded

Android: Hardcode images with paths

I am working on an a simple android application that stores objects in an array, and displays them to the user via a listview. Each object contains a photo and a single text field. For demonstration purposes, I would like to pre-populate this array with some hardcoded objects.
The trouble is that the images are typically acquired through the camera interface, and each object only stores the path to that image. I can add the hardcoded images as drawables, but then they don't have a file path. I could when the app is initialized, convert the drawables to bitmaps and save the bitmaps to the SD card, but that seems too complicated to be the correct answer...
Any ideas on the best way to get these images into file storage so that I refer to them via their URIs?
Thanks!
When you create your views in your adapter, have a ImageView in your layout and use a loader or custom AsyncTask to load the image in the background and have it update the ImageView instance once it has the data.
check the background from this on loading images from the network.
You acquire images from the camera but notice that when you do a resource chooser where mimetype = img/*, the selector just merges local camera(gallery) storage with other photo, content providers. An example of common chooser for photos is in 'Evernote' where you go to the composer view with the 2X2 grid and touch the 'attachment' icon... thats a photo chooser...
In other words , it helps to understand the general practice for managing photos and for presenting them in imageViews.
Typically, there is a lazyLoader that has an interface with args for the imgView and the URI of the image source. Under the covers on a call to 'loadImage(view, uri), the implementation checks the following:
is the bitmap already in a memCache?
the local file , that backs the bitmap, does it exist in the folder reserved for this purpose?
if none of above, go get the array of bytes for the img from across the network ( or in your case , get bytes from camera ).
Even though your question is a little different , IMO , the standard practices for images may apply and you may want to adapt one of the many libs for image presentation to your specific requirements.

Android: Turn off lazy loading of listview

In my Android App I have a listview containing 30 rows, and each row consists of several textviews of which one is spannable and sometimes contains a lot of formatted text and images.
Those images are loaded from the web asynchroneously: A placeholder is displayed until the image has been downloaded is then replaced by the image.
Unfortunately, the rows of the listview are loaded when I scroll over them. This makes the whole thing very slow. Also, those images are loaded from the web again and again, whenever I scroll over the row.
How can I turn it off, that the ListView rows are loaded when I scroll over them? They should be loaded once when I start the activity and never again.
Best regards and thanks in advance,
Jan Oliver
When you do a lazy-loading ListView, is because you want to speed it up your app. Turn it off is not the best solution. So, what you can do is implementing a basic cache system in order to avoid downloading and setting the ImageView again and again.
The easiest way to do so is implementing a HashMap with URLs as keys and Bitmaps as values. Something like this:
Map cache = new HashMap();
// then, on your lazy loader
Bitmap image = cache.get(urlOfTheImage);
if( image == null ){
// download and decode the image as normal,
// then assign the decoded bitmap to
// the 'image' variable
cache.put(image);
}
imageView.setImageBitmap(image);
If those images will be the same always, meaning that each time you open the app the same images will be downloaded, then you better save those images in the filesystem and use them from there.
On the other hand, if the images tend to change, you could implement some interesting stuff: use SoftReferences. There's an explanation in this video. This can also be used if you are loading images from the filesystem.
Edit
With regards to your comment, I highly recommend you watching the video I posted. It's one hour long, but it really worths the effort. When using an adapter, checking if the convertView is null is just a simple way to improve performance, though there are some other techniques that will improve your app even more. Also, if you had have problems while using that trick, is because you are probably implementing it the wrong way. Remember: even if you don't re-inflate the views, you do have to set the value of each one of the children views, otherwise you will experience some problems.
If you can, start with an Image Array full of the "placeholder images", then download the images in to an Array firing an AsyncTask during on Create. During row view building just refer to the array. That way if it has the new image it will load it, if not it will get the placeholder.
If you have a lot of data its gonna get real slow and be a crappy expirience for the user.
Create a list of objects that represent each row. Create a loader as a background thread that updates the objects as it loads the data. Your list view will draw data from the objects.
(Not a good idea if you have hundreds of rows and a huge amount of data in each row - in that case, you should only load data within a few rows of the currently active row and have some sort of MRU cache).

Categories

Resources