Java tutorial
/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.blogspot.codigogoogle.listloadingsamples; import android.annotation.TargetApi; import android.app.Activity; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Build; import android.support.v4.util.LruCache; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.net.URL; import java.util.ArrayList; import java.util.Map; import static com.blogspot.codigogoogle.listloadingsamples.ImageCommons.decodeSampledBitmapFromResource; /** * @author netomarin */ public class ImageLoaderListAdapter extends BaseAdapter { private LruCache<String, Bitmap> mMemoryCache; private Bitmap mPlaceHolderBitmap; private Activity context; private ArrayList<Map<String, String>> listItems; public ImageLoaderListAdapter(Activity context, ArrayList<Map<String, String>> listItems) { this.context = context; this.listItems = listItems; mPlaceHolderBitmap = decodeSampledBitmapFromResource(context.getResources(), R.drawable.img_placeholder, 20, 20); final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override protected int sizeOf(String key, Bitmap bitmap) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR1) { return bitmap.getByteCount() / 1024; } else { return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } } }; } public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); } @Override public int getCount() { return listItems.size(); } @Override public Object getItem(int i) { return listItems.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int position, View convertView, ViewGroup container) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.list_item_img_title_desc, container, false); } Map<String, String> item = (Map<String, String>) getItem(position); ((TextView) convertView.findViewById(R.id.listItemTitle)).setText(item.get("title")); ((TextView) convertView.findViewById(R.id.listItemDescription)).setText(item.get("description")); final ImageView thumbnail = (ImageView) convertView.findViewById(R.id.listItemImage); loadBitmap(item.get("flag"), thumbnail); return convertView; } public void loadBitmap(String imageUrl, ImageView imageView) { final Bitmap bitmap = getBitmapFromMemCache(imageUrl); if (bitmap != null) { imageView.setImageBitmap(bitmap); } else { if (cancelPotentialWork(imageUrl, imageView)) { final BitmapWorkerTask task = new BitmapWorkerTask(imageView); final AsyncDrawable asyncDrawable = new AsyncDrawable(context.getResources(), mPlaceHolderBitmap, task); imageView.setImageDrawable(asyncDrawable); task.execute(imageUrl); } } } class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> { private final WeakReference<ImageView> imageViewReference; // private int resId = 0; private String imageUrl; public BitmapWorkerTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can be garbage collected imageViewReference = new WeakReference<ImageView>(imageView); } // Decode image in background. @Override protected Bitmap doInBackground(String... params) { imageUrl = params[0]; ImageView thumbnail = imageViewReference.get(); try { InputStream is = (InputStream) new URL(imageUrl).getContent(); Bitmap bitmap = ImageCommons.decodeSampledBitmapFromInputStream(is, thumbnail.getWidth(), thumbnail.getHeight()); addBitmapToMemoryCache(imageUrl, bitmap); return bitmap; } catch (IOException e) { e.printStackTrace(); return null; } } // Once complete, see if ImageView is still around and set bitmap. @Override protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null && bitmap != null) { final ImageView imageView = imageViewReference.get(); final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (this == bitmapWorkerTask && imageView != null) { imageView.setImageBitmap(bitmap); } } } } static class AsyncDrawable extends BitmapDrawable { private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference; public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { super(res, bitmap); bitmapWorkerTaskReference = new WeakReference<BitmapWorkerTask>(bitmapWorkerTask); } public BitmapWorkerTask getBitmapWorkerTask() { return bitmapWorkerTaskReference.get(); } } public static boolean cancelPotentialWork(String imageUrl, ImageView imageView) { final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (bitmapWorkerTask != null && bitmapWorkerTask.imageUrl != null) { final String bitmapWorkerTaskImageUrl = bitmapWorkerTask.imageUrl; if (!bitmapWorkerTaskImageUrl.equals(imageUrl)) { // Cancel previous task bitmapWorkerTask.cancel(true); } else { // The same work is already in progress return false; } } // No task associated with the ImageView, or an existing task was cancelled return true; } private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { if (imageView != null) { final Drawable drawable = imageView.getDrawable(); if (drawable instanceof AsyncDrawable) { final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; return asyncDrawable.getBitmapWorkerTask(); } } return null; } }