I have a listactivity and each row has a different image that i load from the web and some text.
I'd like to implement asynctask so the images would load on the background.
I've searched many tutorials but haven't found none that use different images per row. The problem is the method doInBackground that is supposed to load the images from the internet. But since they are all different and they depend on its row, how can the thread load them?
Global variables: Bitmap bm; BitmapFactory.Options bmOptions;
In my getView method, I have
ImageView img = (ImageView) v.findViewById(R.id.icon);
if (img!=null){
bm = LoadImage(o.getLink(), bmOptions);
img.setImageBitmap(bm);
}
along with the text load... this img should be load on the doInBackground method, but then I'd have no access to the o (of type User) object that I know because getView gives me the position.
Does anyone have any idea on how to solve this problem?
Thanks,
Rita
There are two ways you can do this: the easy way or the boring way.
If you can add extra dependencies, then I would strongly recommend you take the easy route and use GreedDroid. You can use the item framework they have in there or use the AsyncImageView. Personally I'd use the latter.
The boring way, on the other hand, would be to break out the HttpClient and download the image manually, then use BitmapFactory.decodeStream method to create a Bitmap.
The downloading needs to happen away from the UI thread, so it may feel natural to use an AsyncTask to run it all, and the use a Handler to actually poke the Bitmap into the ImageView (being careful not to set the Bitmap on a view which has already been recycled).
Unfortunately, on many implementations, the ExecutorService that runs the AsyncTasks are limited to using one Thread. This gives an unfortunate feel to the List where the images load one by one, instead of the as-many-as-possible-all-at-once feel to it you may be expecting.
In that case, you'll probably be wanting to (essentially) roll your own AsyncTask.
I'm not a massive fan of AsyncTasks, as you can tell.
The above is such a common task, and such an annoying thing to get right, I'd very much recommend using someone else's library.
I believe you will need to write your own List Adapter so that as more and more list items are displayed (by scrolling down for example), the adapter creates more AsyncTasks and displays the images once they have been fetched.
http://developer.android.com/reference/android/widget/ListAdapter.html
This is where images will be downloaded using async task just have look
http://developer.android.com/resources/articles/painless-threading.html
Related
I'm a little confused: as a rule when async loading images to some sort of list view (whether on Android or iOS or in the abstract on another platform), you essentially must do this ..
-- make a note of "which" cell this is (say, #213)
-- start getting the image from the net.
-- it has loaded from the net. What cell are we now?
-- if we are "still" 213, load the image to the image view!
-- if we are "no longer" 213, just forget about it.
this is a basic in lazy-loading async images. For example, Lucas Rocha explains it perfectly in a famous article here:
http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
(scroll down to exactly "Here is just a simplistic sketch of one way you could do it:" ...)
Well now, as I understand it Picasso in fact does this for you, completely automatically.
On its own, Picasso 'knows' if the view has changed. If the view has changed, Picasso knows not to bother loading it
Am I completely correct? This is a built-in feature of Picasso, and I need do nothing else?
(Aside - I'm somewhat confused "how" Picasso does this; glancing at it I can't see any magic code in Picasso where it makes a note of the id, or something of the holder? view? in question.)
Just to be clear, I'm using Picasso in the usual way exactly like this, essentially at the end of getView...
Picasso.
with(State.mainContext).
load(imageFile.getUrl()).
placeholder(R.drawable.default).
noFade().
into(v.hexaIV);
yes, Picasso is that beautiful. You only need that one line inside the getView() method Picasso.with(c).load(url).into(img);
how they exactly do it, I'm not sure, but before Picasso existed I did my own image loader and it's not so difficult.
Let's say you have a map of Url and ImageView somewhere in your image loader code.
So whenever the code pass img to it, it checks against this map, if it is already loading other URL for the same img using basic Java mImg.equals(img), if it matches, it knows that, even thou still will cache that URL, it should not deliver the Drawable to the ImageView.
There're a few rare cases that you might want to directly cancel a load, on those cases you can call Picasso.with(c).cancel(img);, but that's rare to be necessary.
I've a ListView in which each row item contains many ImageViews apart from some content.
That is, there will be many list items, each containing many images.
In order to not to hold user unnecessarily, I'm showing the content first & then downloading the images asynchronously.
Currently, for each image I'm starting a new AsycTask.
Although, it working alright, but this not a good approach.
In place of this, what should I use?
use this library, best in android for image loading..
https://github.com/nostra13/Android-Universal-Image-Loader
Your scenario seems to fit exactly to use LazyLoading of images. This basically loads images in the background and shows them as soon as they're loaded.
You might want to see this:
Lazy load of images in ListView
An alternative would be using a ThreadPoolExecutor with the images to load, but the above works pretty well and is recommended.
Try using the library
http://square.github.io/picasso/
Many common pitfalls of image loading on Android are handled automatically by Picasso:
Handling ImageView recycling and download cancelation in an adapter.
Complex image transformations with minimal memory use.
Automatic memory and disk caching.
Yes, I know that I am doing bad things, but...
In some cases I'm using the nostra13's ImageLoader to load images from res/drawable folders. Is there a built-in option to block UI thread while image is loading?
I suspect that there may not be such thing, because the primary goal of ImageLoader is to load images from the Internet, and in this case asynchronous mode is the only option. But in my situation this would be handy.
Currently I'm using it for loading and downscaling big background images and it takes some noticeable time.
if you're just loading a background for a fragment from the res/drawable just do it the "normal" way then.
Put that image in the Fragment XML file as the background of the root view.
of, if it's user/theme selectable, just call setBackgroundResource on the root view during onCreateView
edit:
ImageLoader itself I don't know, but I've been using lately the Picasso library and it's beautiful, handles images VERY VERY well, it's very flexible and it can achieve what u want by calling: Picasso.with(context).load(<resID>).get()
There's now a method which can load and scale Bitmap synchronously: https://github.com/nostra13/Android-Universal-Image-Loader/blob/master/library/src/com/nostra13/universalimageloader/core/ImageLoader.java#L550
But it's almost never a good idea to do this, because GUI applications should be responsive, that means — never block UI thread for a noticeable time.
I'm developing an Android app with a list view that contains lots of drawables.
Most of them are the same so I'm trying to use a HashMap that returns the same allocated bitmap when it's needed but still there are lots of allocations and GC actions so that the list gets stuck from time to time when scrolling.
What can I do to optimize the performance in such case?
Caching method - loadImage Using google code
mImageWorker.loadImage(pic_url, holder.pic);
holder.*some bitmap*.setImageBitmap(Utility.getBitmap(context, id); //can be one of 5 bitmaps do I use caching with a hashMap
see this example
this will helps you....
don't put so much process under the getView() method . this will lack the listview scroll performance
if you want to do image crapping or drawable to bitmap conversition or anything .. just do all process
before loading adapter.. and just assign values for each row in getView()...
Try to use lazy loading technique using caching, you can find many tutorial on the web:
You have to see this SO thread
Also see this:
Multithreading For Performance, a tutorial by Gilles Debunne.
This is from the Android Developers Blog. The suggested code uses:
AsyncTasks.
A hard, limited size, FIFO cache.
A soft, easily garbage collected cache.
A placeholder Drawable while you download.
If you want to optimize the code, try lazy loading concept for loading images in list. Please refer: Lazy Load images on Listview in android(Beginner Level)?
I need to show a certain number of images within a imageview dynamically, every few seconds, I need show in that imageview around 40 images, without onclick events or others, just go changing the image, preferably obtain them from a website, how can I start with this?
really would appreciate your help.
Use a Handler to change the image each time delay you specify. Post a Runnable that changes the image with whatever time delay you wish.
Often people use an async-task for loading things online. I personally have never needed to, but you may need to load the images in an async task because it can slow up the UI and prompt a force-quit. Check on that though.
Bitmap bmp = MediaService.getDisplayImage("image_url", getApplicationContext());
((ImageView)findViewById(R.id.yourimageviewid)).setImageBitmap(bmp);
in this way you can retrieve image from network and set into your ImageView... rest all shuffling images etc detail you can manage with using timer..