Load Image to ImageView from Web Url
In an
Android application, we need to set ImageView src as a web URL. The times we need to download the image using web requests and then save the image in the phone and set this to the particular ImageView, this will be the normal flow for setting an ImageView URL from the webserver. If there are one or two images then it's okay but if there are a lot of images to load this will be a big problem and we need to handle all the requests and all the files. Here I am going to tell you how we can download images in the background and set to the corresponding ImageView as they are available.
In the task, I have a ListView and it's populated at the runtime, that is, we need to download the data from web service to populate the ListView. This data contains a title and web URL of the image to be shown in the ListView. After getting the data from web service we need to show the ListView with its title and a dummy image. At the time of getting each image from the internet, we need to update the ImageView with the actual image. This is the task I am going to perform.
First, we need to create the main layout file like the following it will contain only a listview.
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="match_parent"
- android:layout_height="match_parent">
- <ListView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/listView"
- android:layout_gravity="center_horizontal" />
- </LinearLayout>
In this listview we need to show the title and ImageView so create a custom layout for the list item and it should be like the following,
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal" android:layout_width="match_parent"
- android:layout_height="match_parent">
- <ImageView
- android:layout_width="0dp"
- android:layout_margin="10dp"
- android:layout_weight=".25"
- android:id="@+id/imageItem"
- android:layout_height="match_parent" />
- <TextView
- android:layout_width="0dp"
- android:id="@+id/text"
- android:layout_weight=".75"
- android:layout_height="wrap_content" />
- </LinearLayout>
Now we need to call the initial JSON image that contains title and image url. For that we need to create an http communication class as Async task and here is the code below that will get the JSON data from webservice and will show it in the listview,
- @Override
- protected Output doInBackground(Void...voids)
- {
- BufferedReader in = null;
- String data = null;
- InputStream inputStream = null;
- String result = "";
- try
- {
-
- HttpClient httpclient = new DefaultHttpClient();
-
- HttpResponse httpResponse = httpclient.execute(new HttpGet("https://randomapi.com/api/?key=LMW0-SW97-ISC4-FF25&id=t60ldyb&results=20"));
-
- inputStream = httpResponse.getEntity().getContent();
-
- if (inputStream != null)
- result = convertInputStreamToString(inputStream);
- else
- result = null;
- } catch (Exception e)
- {
- Log.d("InputStream", e.getLocalizedMessage());
- result = null;
- }
- Log.e("response----", "" + result);
- if (result != null)
- {
- Output response = new Gson().fromJson(
- result, Output.class);
- return response;
- }
- return null;
- }
-
- private static String convertInputStreamToString(InputStream inputStream) throws IOException
- {
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
- String line = "";
- String result = "";
- while ((line = bufferedReader.readLine()) != null)
- result += line;
- inputStream.close();
- return result;
- }
Now we need to call the Asynctask to load this JSON from our mainActivity,
- HttpHelper httpHelper = new HttpHelper(this,getActivity());
- httpHelper.execute();
Now we need to create an interface that will handle the downloaded image,
- public interface ImageCallback
- {
- public void setImage(String tag, Bitmap bitmap);
- }
Now we need to create a class for the Image Downloader this class will download the image and handle this image,
- class ImageDownloaderTask extends AsyncTask < String, Void, Bitmap >
- {
-
- String tag = null;
-
- private ImageCallback imageCallback = null;
- public ImageDownloaderTask(ImageCallback imageCallback, String TAG)
- {
-
- this.imageCallback = imageCallback;
- this.tag = TAG;
- }
- @Override
- protected Bitmap doInBackground(String...params)
- {
- HttpURLConnection urlConnection = null;
- try
- {
- URL uri = new URL(params[0]);
- urlConnection = (HttpURLConnection) uri.openConnection();
- int statusCode = urlConnection.getResponseCode();
- if (statusCode != HttpStatus.SC_OK)
- {
- return null;
- }
- InputStream inputStream = urlConnection.getInputStream();
- if (inputStream != null)
- {
- Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
- return bitmap;
- }
- } catch (Exception e)
- {
- urlConnection.disconnect();
- Log.w("ImageDownloader", "Error downloading image from ");
- } finally {
- if (urlConnection != null)
- {
- urlConnection.disconnect();
- }
- }
- return null;
- }
- @Override
- protected void onPostExecute(Bitmap bitmap)
- {
- if (isCancelled())
- {
- bitmap = null;
- }
-
- imageCallback.setImage(tag, bitmap);
- }
-
- }
Here comes the main part of the listview that is the Adapter for binding the items to listview,
- public class ListAdapter extends BaseAdapter
- {
- private ArrayList < ResultData > result = null;
- private Context context = null;
- LayoutInflater inflater;
- private ImageCallback imageCallback = null;
- private HashMap < String, Bitmap > imageMap = new HashMap < String, Bitmap > ();
-
- public void addItem(String key, Bitmap bitmap)
- {
- if (imageMap.get(key) == null)
- imageMap.put(key, bitmap);
- }
- public ListAdapter(Context context, ArrayList < ResultData > result, ImageCallback imageCallback)
- {
- this.result = result;
- this.context = context;
- inflater = LayoutInflater.from(context);
- this.imageCallback = imageCallback;
- }
- @Override
- public int getCount()
- {
- return result.size();
- }
- @Override
- public Entity getItem(int i)
- {
- return result.get(i).getEntity();
- }
- @Override
- public long getItemId(int i)
- {
- return 0;
- }
- @Override
- public View getView(int arg0, View convertView, ViewGroup arg2)
- {
- ViewHolder viewHolder = new ViewHolder();
- if (convertView == null)
- {
- convertView = inflater.inflate(R.layout.list_item, null);
- viewHolder.titleText = (TextView) convertView.findViewById(R.id.text);
- viewHolder.imageItem = (ImageView) convertView.findViewById(R.id.imageItem);
- convertView.setTag(viewHolder);
- } else
- {
- viewHolder = (ViewHolder) convertView.getTag();
- }
- viewHolder.titleText.setText(getItem(arg0).getDescritpion());
- if (viewHolder.imageItem != null)
- {
- viewHolder.imageItem.setTag(getItem(arg0).getThumbnail());
- Bitmap bitmap = null;
- bitmap = imageMap.get(getItem(arg0).getThumbnail());
- if (bitmap == null)
- new ImageDownloaderTask(imageCallback, getItem(arg0).getThumbnail()).execute(getItem(arg0).getThumbnail());
- else
- viewHolder.imageItem.setImageBitmap(bitmap);
- }
-
- return convertView;
-
- }
- class ViewHolder
- {
- private TextView titleText = null;
- private ImageView imageItem = null;
- }
- }
Here we created a HashMap<String, Bitmap> this will store the downloaded images in the hashmap. and will avoid loading the same image while scrolling the listview. In the getview() of adapter, we will check whether the image is available in the hashmap or if not available then we will get it from the server. Please find the screenshot also,
Read more articles on Android