In an
Android application we need to set ImageView src as web url. The times we need to download the image using web request and then save the image in phone and set this to the particular ImageView, this will be the normal flow for setting an ImageView url from web server. 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.
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 screen shot also,