Loading images is the most common task for Android apps. Loading image task can be very simple. But if the image size is very big or there are lots of images to be downloaded, it will take a long time. During the downloading progress, all android UI will freeze. Therefore, we have to download images in different thread from main thread (UI thread). In this Android tutorial, I will give an example to show how to use Asynctask to download a list of images.
Download and Try Download Images In AsyncTask Android Example
At the beginning, I will create a ListView. In each row of the list, there are one image from internet. Therefore, we need to download the image in each row view for the list in the ArrayAdapter. For more information about ListView and ArrayAdapter, please check post:ListView and ArrayAdapter.
First, let show the MainActivity.java source code:
package com.jms.loadimagewithasynctask; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.ListView; public class MainActivity extends Activity { private String[] imageURLArray = new String[]{ "http://farm8.staticflickr.com/7315/9046944633_881f24c4fa_s.jpg", "http://farm4.staticflickr.com/3777/9049174610_bf51be8a07_s.jpg", "http://farm8.staticflickr.com/7324/9046946887_d96a28376c_s.jpg", "http://farm3.staticflickr.com/2828/9046946983_923887b17d_s.jpg", "http://farm4.staticflickr.com/3810/9046947167_3a51fffa0b_s.jpg", "http://farm4.staticflickr.com/3773/9049175264_b0ea30fa75_s.jpg", "http://farm4.staticflickr.com/3781/9046945893_f27db35c7e_s.jpg", "http://farm6.staticflickr.com/5344/9049177018_4621cb63db_s.jpg", "http://farm8.staticflickr.com/7307/9046947621_67e0394f7b_s.jpg", "http://farm6.staticflickr.com/5457/9046948185_3be564ac10_s.jpg", "http://farm4.staticflickr.com/3752/9046946459_a41fbfe614_s.jpg", "http://farm8.staticflickr.com/7403/9046946715_85f13b91e5_s.jpg", "http://farm8.staticflickr.com/7315/9046944633_881f24c4fa_s.jpg", "http://farm4.staticflickr.com/3777/9049174610_bf51be8a07_s.jpg", "http://farm8.staticflickr.com/7324/9046946887_d96a28376c_s.jpg", "http://farm3.staticflickr.com/2828/9046946983_923887b17d_s.jpg", "http://farm4.staticflickr.com/3810/9046947167_3a51fffa0b_s.jpg", "http://farm4.staticflickr.com/3773/9049175264_b0ea30fa75_s.jpg", "http://farm4.staticflickr.com/3781/9046945893_f27db35c7e_s.jpg", "http://farm6.staticflickr.com/5344/9049177018_4621cb63db_s.jpg", "http://farm8.staticflickr.com/7307/9046947621_67e0394f7b_s.jpg", "http://farm6.staticflickr.com/5457/9046948185_3be564ac10_s.jpg", "http://farm4.staticflickr.com/3752/9046946459_a41fbfe614_s.jpg", "http://farm8.staticflickr.com/7403/9046946715_85f13b91e5_s.jpg"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ListView listView = (ListView)this.findViewById(R.id.listView); ImageAdapter imageAdapter = new ImageAdapter(this, R.layout.imageitem, imageURLArray); listView.setAdapter(imageAdapter); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
In the MainActivity class, we define an array of image url for ListView to download and show. We are using one customized ArrayAdapter to generate the row view for ListView. Now, let’s see the source code of ImageAdapter class.
package com.jms.loadimagewithasynctask; import java.io.IOException; import java.net.URL; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; public class ImageAdapter extends ArrayAdapter<String> { private String[] imageURLArray; private LayoutInflater inflater; public ImageAdapter(Context context, int textViewResourceId, String[] imageArray) { super(context, textViewResourceId, imageArray); // TODO Auto-generated constructor stub inflater = ((Activity)context).getLayoutInflater(); imageURLArray = imageArray; } private static class ViewHolder { ImageView imageView; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolder viewHolder = null; if(convertView == null) { convertView = inflater.inflate(R.layout.imageitem, null); viewHolder = new ViewHolder(); viewHolder.imageView = (ImageView)convertView.findViewById(R.id.testImage); convertView.setTag(viewHolder); } viewHolder = (ViewHolder)convertView.getTag(); //load image directly Bitmap imageBitmap = null; try { URL imageURL = new URL(imageURLArray[position]); imageBitmap = BitmapFactory.decodeStream(imageURL.openStream()); viewHolder.imageView.setImageBitmap(imageBitmap); } catch (IOException e) { // TODO: handle exception Log.e("error", "Downloading Image Failed"); viewHolder.imageView.setImageResource(R.drawable.postthumb_loading); } return convertView; } }
Currently, we have finished the basic of the requirement. We create a ListView and show the images in the ListView. However, it is a big problem when you compile and run the app in your devices. The ListView response is horrible slow and sometimes it looks like no response at all when we drag the ListView up and down. That is because we are downloading the image on the main thread or the UI thread. To solve ListView hang problem when downloading the image, we have to move the downloading logic in a different thread.
Download Image in AsyncTask Example
As Android developers guide mentioned, AsyncTask must be subclassed to be used. Therefore, we will create subclass, DownloadAsyncTask, in our ImageAdapter. Once the ListView request a row View from ImageAdapter, we will start a new AsyncTask and download the image in the background. In the DownloadAsyncTask class, we will override the doInBackground method which will be called to start download the image and onPostExecute method which will update our ListView when the image downloading in AsyncTask finished. Here is the subclass of AsyncTask:
private class DownloadAsyncTask extends AsyncTask<ViewHolder, Void, ViewHolder> { @Override protected ViewHolder doInBackground(ViewHolder... params) { // TODO Auto-generated method stub //load image directly ViewHolder viewHolder = params[0]; try { URL imageURL = new URL(viewHolder.imageURL); viewHolder.bitmap = BitmapFactory.decodeStream(imageURL.openStream()); } catch (IOException e) { // TODO: handle exception Log.e("error", "Downloading Image Failed"); viewHolder.bitmap = null; } return viewHolder; } @Override protected void onPostExecute(ViewHolder result) { // TODO Auto-generated method stub if (result.bitmap == null) { result.imageView.setImageResource(R.drawable.postthumb_loading); } else { result.imageView.setImageBitmap(result.bitmap); } } }
Using AsyncTask to Download Images
As you can see, we move all the image downloading code in AsyncTask now. To instantiate the subclass of AsyncTask and start to download the image, we have to change our getView function a little bit. Instead of loading the image immediately in getView, we create a new AsyncTask class and call AsyncTask.execute every time. Here is the example code:
@Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolder viewHolder = null; if(convertView == null) { convertView = inflater.inflate(R.layout.imageitem, null); viewHolder = new ViewHolder(); viewHolder.imageView = (ImageView)convertView.findViewById(R.id.testImage); convertView.setTag(viewHolder); } viewHolder = (ViewHolder)convertView.getTag(); viewHolder.imageURL = imageURLArray[position]; new DownloadAsyncTask().execute(viewHolder); return convertView; }
That’s it. Now you can compile and try the new app in your device. The performance is getting much better. The ListView scrolls smoothly and image downloading also works fine. If you still have problems about downloading images in ListView, you can leave the reply and I will answer your questions if I can.
Here you can download this example .apk file and install it on your device.
Get Example Source Code at $0.99
You will get whole “Downloading Images by AsyncTask in ListView” Android source code at $0.99. With this source code, you can do everything you want:
- Load your own images from your server;
- Monetize the app with your own AdMob publish id;
- Use the source code in your own project;
- Publish this app in your android develop account;
Hi, my code works fine but there is a problem. When I scroll the list view a new images appers which are downloaded from url but when I scrool back, the images download again. It is like refreshing the images. How can I solve it?
Hi Pamir,
Because of the performance, ViewList will reuse the View which is used in hidden list row. Therefore, there maybe only 5 Views existing to serve the whole ViewList. And you will see that images are refreshed.
In my example, there is no cache mechanism. I think the http request may cache the image. To make it more efficient, it’s better to cache the images which is downloaded. Then, we don’t need to load image from internet everytime.
I think I will update my example later to support the local cache.
Thanks
Many thanks for your help!
Do you already have an example with local cache support?
Thanks in advance
Hello Jasper,
If you want to find a way for local cache, you may check this tutorial:
Android Save And Load Downloading File Locally
Best Regards
James
It’s Really Usefull,My biggest problem was now clear.Can You Please Send me the example code for how to cache the image from http??
Hello,
It’s very simple to cache the images. For example, save it on the sd cards. When you want to load it next time, you can load from local sd card instead of downloading by HTTP again.
Thanks
Any suggestions for changable url? I mean e.g: http://www.example.com/content/changable/img/ ???
Hi Tomay,
To change the image, it is quite simple. Just change the data array and update the adapter.
Thanks
I mean one element is dynamic, e.g: content/aa/img, or content /bb/img, any example for it ?:) Thank you
Hi James,
I’ve bought this source code but I’ve a question: where can I put this code in the Rss feed reader example?
Because I’m doing a feed reader with your code but I need to download the images indicated in the feed. How can I do this?
Thanks for all
Andrea
In RSS Reader, you have to build an data array to store that images. After that, you can apply this code inside. In my tutorial and tips, I aim to solve one problem at a time. I am not suppose to help solve a project.
Thanks.
Hi,
I bought the sample source, but does not contain the part relating to Google AD.
I need the complete source code.
Hello,
This tutorial doesn’t cover the Google AD tutorial. You’d better to check this post:
Adding Admob Banner in Android ListView Header
Thanks
Hi, where come from “imageitem” ?
It’s the layout of ListView row.
Layout of Listview row? Can you explain in detail.Didn’t get you
The Layout of Listview row is very simple. You can put a ImageView in a Relativelayout
Hi,
I have bought the code and also installed the apk in my SAMSUNG mobile, I could see all the wallpapers, but I could not download any of them. When I click on each image, nothing is happening
Hi, this source code is not for wallpaper app. In this post, I only show you how to load image in ListView row. If you want to check the wallpaper app source, please check this app:
http://jmsliu.com/2455/android-crop-image-and-assign-wallpaper.html
Thanks
thankyou…! its really useful for me
i want to download that source code
Make the purchase and the download link will appear.
Hi, firstly thank you very much this tutorial. I get an error like this “Downloading Image Failed” can you help me about it?
I downloaded my app on this page and check on my android phone. It seems to work properly.
can you give me your email address please. i will send you my code. i could not do it. please help me?
thank you very much i solve it. I forget allow the permission from AndroidMainfes.
“”
private class DownloadAsyncTask extends AsyncTask
asking create class ??
private class DownloadAsyncTask extends AsyncTask
here ViewHolder showing error and asking to create class
Then you need to create the ViewHolder class. BTW, in my source code example, I already show the ViewHolder source code there.
i’m trying to load 21 images from my Json data its loading fine, but when scrolling images are changing why??
Using private for DownloadAsyncTask showing error ??
Please check it carefully before you report the error. The source code is working properly for others.
hello sir, can you tell me how to set onclickListener for those images ?
Basic question, you can search on google. It will give you the best answer.
Images are downloading,But when i am scrolling images are downloading again..plz help me in this issue
Thanks inadvance
Hi, one question, what do you mean “when you are scrolling images are downloading again”? Can you please describe your problem more clearly?
I think your code is prone to errors due to possible configuration changes (like orientation) recreating the activity, so the viewholders keep pointing to the old images, as well as leaking them.
This behavior could be tested (haven’t tested it myself) when scrolling on a slow connection device and rotating the device.
I think after you make some configuration changes, like orientation, the app will recreating the activity. But this is not the reason why the viewholders keep pointing to the old images.
For ListView in Android, it will only create the necessary number of itemview to fit the space. When you scroll the ListView, it will re-use the old itemview for the new row. So you will see the old image in the new row.
To avoid the app downloading the images all the time, you can implement some cache mechanism. So the refresh speed will be fast.
For advanced usage, please check this two post:
Show Image In Listview
Android Save And Load Downloading File Locally
in DownloadAsyncTask class cannot resolve symbols:
imageURL and bitmap on viewHolder object..
btw the ViewHolder Class don’t have a bitmap field..
any clarification?
You need to update the ViewHolder class according to your needs. Or you can get the full source code.
hi James
i just bought the sample source, and that work very well,
thank u.
where at the source code i should write the onclickListener for each image.
thanks in adnavce
Hello,
You may check this post. Though I give an example about adding onClick event on a button, I think you can use the same approach to solve your problem. Here is the link:
http://jmsliu.com/2444/click-button-in-listview-and-get-item-position.html
Best Regards
James
Awesome link. working perfectly
Hi
nice tutorial
but i’m having one issue i want to set name or some label also in listview correspond to image but in that case images keeps getting downloading and row are changes ..
so how to set name or label corrospond that image…
Thanks
manoj
I am so glad that you can try more complicated functions basing on my tutorial. Here is another tutorial to show you how to download image and set label in the row list. Please check: http://jmsliu.com/2682/rss-reader-android-app-tutorial-6-show-image-in-listview.html
NIce tip for improving the performance! Loved it! 😀
Hope the tip will be helpful!
Useful information. Fortunate me I discovered your
website by chance, and I’m stunned why this
accident didn’t happened in advance! I bookmarked it.