Question

I have the following class to parse JSON and display name and other details too which i dont mention here in listview.
ShowViewActivity.java

public class ShowViewActivity extends ListActivity {

private static String url = "http://example.com/myfile.php";
private static final String TAG_ROOT = "root";
private static final String TAG_NAME = "name";
private static final String TAG_IMAGE = "image";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ArrayList<HashMap<String, String>> myList = new ArrayList<HashMap<String, String>>();
    JSONParser jParser = new JSONParser();
    JSONObject json = jParser.getJSONFromUrl(url);
    try {
        root = json.getJSONArray(TAG_ROOT);
        for (int i = 0; i < root.length(); i++) {
            JSONObject c = root.getJSONObject(i);
            String name = c.getString(TAG_NAME);
            String image = c.getString(TAG_IMAGE);
            HashMap<String, String> map = new HashMap<String, String>();
            map.put(TAG_NAME, name);
            map.put(TAG_IMAGE, image);
            myList.add(map);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }


    myAdapter adapter = new myAdapter(this, myList, R.layout.list_item,
            new String[] {}, new int[] {});

    setListAdapter(adapter);
    final ListView lv = getListView();

    // Launching new screen on Selecting Single ListItem
    lv.setOnItemClickListener(new OnItemClickListener() {

        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

        }

    });

}

private class myAdapter extends SimpleAdapter {

    public myAdapter(Context context, List<? extends Map<String, ?>> data,
            int resource, String[] from, int[] to) {
        super(context, data, resource, from, to);

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            convertView = getLayoutInflater().inflate(R.layout.list_item,
                    null);
        }

        HashMap<String, Object> data = (HashMap<String, Object>) getItem(position);

        TextView nameTextView = (TextView) convertView
                .findViewById(R.id.name);
        ImageView iconImageView = (ImageView) convertView
                .findViewById(R.id.listicon);

        String nameString = (String) data.get(TAG_NAME);
        nameTextView.setText(nameString);
        String imageUrl = (String) data.get(TAG_IMAGE);

        return convertView;
    }
}
}

I want to implement the following ImageDownloader class to show image from web url.

ImageDownloader.java

public class ImageLoader {

// the simplest in-memory cache implementation. This should be replaced with
// something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();

private File cacheDir;

public ImageLoader(Context context) {
    // Make the background thead low priority. This way it will not affect
    // the UI performance
    photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);

    // Find the dir to save cached images
    if (android.os.Environment.getExternalStorageState().equals(
            android.os.Environment.MEDIA_MOUNTED))
        cacheDir = new File(
                android.os.Environment.getExternalStorageDirectory(),
                "LazyList");
    else
        cacheDir = context.getCacheDir();
    if (!cacheDir.exists())
        cacheDir.mkdirs();
}

final int stub_id = R.drawable.icon;

public void DisplayImage(String url, Activity activity, ImageView imageView) {
    if (cache.containsKey(url))
        imageView.setImageBitmap(cache.get(url));
    else {
        queuePhoto(url, activity, imageView);
        imageView.setImageResource(stub_id);
    }
}

private void queuePhoto(String url, Activity activity, ImageView imageView) {
    // This ImageView may be used for other images before. So there may be
    // some old tasks in the queue. We need to discard them.
    photosQueue.Clean(imageView);
    PhotoToLoad p = new PhotoToLoad(url, imageView);
    synchronized (photosQueue.photosToLoad) {
        photosQueue.photosToLoad.push(p);
        photosQueue.photosToLoad.notifyAll();
    }

    // start thread if it's not started yet
    if (photoLoaderThread.getState() == Thread.State.NEW)
        photoLoaderThread.start();
}

private Bitmap getBitmap(String url) {
    // I identify images by hashcode. Not a perfect solution, good for the
    // demo.
    String filename = String.valueOf(url.hashCode());
    File f = new File(cacheDir, filename);

    // from SD cache
    Bitmap b = decodeFile(f);
    if (b != null)
        return b;

    // from web
    try {
        Bitmap bitmap = null;
        InputStream is = new URL(url).openStream();
        OutputStream os = new FileOutputStream(f);
        Utils.CopyStream(is, os);
        os.close();
        bitmap = decodeFile(f);
        return bitmap;
    } catch (Exception ex) {
        ex.printStackTrace();
        return null;
    }
}

// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
    try {
        // decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f), null, o);

        // Find the correct scale value. It should be the power of 2.
        final int REQUIRED_SIZE = 70;
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < REQUIRED_SIZE
                    || height_tmp / 2 < REQUIRED_SIZE)
                break;
            width_tmp /= 2;
            height_tmp /= 2;
            scale++;
        }

        // decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {
    }
    return null;
}

// Task for the queue
private class PhotoToLoad {
    public String url;
    public ImageView imageView;

    public PhotoToLoad(String u, ImageView i) {
        url = u;
        imageView = i;
    }
}

PhotosQueue photosQueue = new PhotosQueue();

public void stopThread() {
    photoLoaderThread.interrupt();
}

// stores list of photos to download
class PhotosQueue {
    private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();

    // removes all instances of this ImageView
    public void Clean(ImageView image) {
        for (int j = 0; j < photosToLoad.size();) {
            if (photosToLoad.get(j).imageView == image)
                photosToLoad.remove(j);
            else
                ++j;
        }
    }
}

class PhotosLoader extends Thread {
    public void run() {
        try {
            while (true) {
                // thread waits until there are any images to load in the
                // queue
                if (photosQueue.photosToLoad.size() == 0)
                    synchronized (photosQueue.photosToLoad) {
                        photosQueue.photosToLoad.wait();
                    }
                if (photosQueue.photosToLoad.size() != 0) {
                    PhotoToLoad photoToLoad;
                    synchronized (photosQueue.photosToLoad) {
                        photoToLoad = photosQueue.photosToLoad.pop();
                    }
                    Bitmap bmp = getBitmap(photoToLoad.url);
                    cache.put(photoToLoad.url, bmp);
                    if (((String) photoToLoad.imageView.getTag())
                            .equals(photoToLoad.url)) {
                        BitmapDisplayer bd = new BitmapDisplayer(bmp,
                                photoToLoad.imageView);
                        Activity a = (Activity) photoToLoad.imageView
                                .getContext();
                        a.runOnUiThread(bd);
                    }
                }
                if (Thread.interrupted())
                    break;
            }
        } catch (InterruptedException e) {
            // allow thread to exit
        }
    }
}

PhotosLoader photoLoaderThread = new PhotosLoader();

// Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable {
    Bitmap bitmap;
    ImageView imageView;

    public BitmapDisplayer(Bitmap b, ImageView i) {
        bitmap = b;
        imageView = i;
    }

    public void run() {
        if (bitmap != null)
            imageView.setImageBitmap(bitmap);
        else
            imageView.setImageResource(stub_id);
    }
}

public void clearCache() {
    // clear memory cache
    cache.clear();

    // clear SD cache
    File[] files = cacheDir.listFiles();
    for (File f : files)
        f.delete();
}

}

I see the lazyload examples which extends BaseAdapter but here i am using my my custom adapter name myAdapter which extends SimpleAdapter ?
How to implement this ImageLoader class to show imageview from web image url ?

Was it helpful?

Solution

First step is to get hold of an ImageDownloader instance. I suggest you to use some centralized location for an instance, e.g. your own extension of Application. That way you only need to create it once, but use it everywhere where required. Besides, if you (re)construct this object with every call, the provided caching will be of limited to no use. Alternatively you could set up the class as singleton, although I personally prefer the former.

Once you have an ImageDownloader object, simply make the changes to your custom adapter as outlined below. Since you need to pass in an Activity reference, keep a handle to the Context variable you pass into the constructor of myAdapter. Under normal circumstances this will actually be an Activity reference at runtime.

private class myAdapter extends SimpleAdapter {

    private Context mContext;

    public myAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
        super(context, data, resource, from, to);
        mContext = context;

    }

    ...

    @Override public View getView(int position, View convertView, ViewGroup parent) {
        ...

        // assuming you have an instance of ImageDownloader here
        // 
        mImageDownloader.DisplayImage(imageUrl,(Activity)mContext, iconImageView);
    }

    ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top