How to set image from Url using AsyncTask?
android, android-asynctask, android-drawable, multithreading
Solution
well, I dont know why android SDK does not provide support for it (yet) I extended the ImageView class by UrlImageView class with asynchronous loading and caching support. I put the code of my class below, which is plug and play. The class body is at the end of my post, now I write two lines how to use it the convenient way.
Two more methods now are supported:
setImageUrl(URL url) // sets the bitmap by its URL
cancelLoading(); // tell this view to cancel pending load
How to use your java-code:
// [somewhere in your activity]
UrlImageView urlImg = new UrlImageView(this).setImageUrl("http://abc.png");
...
urlImg.setImageUrl("http://abc2.png"); // works like expected
How to bind in your layouts:
<!-- thumbnail -->
<com.gplushub.android.view.UrlImageView
android:id="@+id/thumbnail"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_vertical"
android:layout_marginRight="2dp"
android:scaleType="fitXY" />
..and again in your activity java code:
((UrlImageView)findViewById(R.id.thumbnail)).setImageUrl("http://foo.bar.png");
I use it in lists with more than 100 entries - flinging very well. Here the class body, you can use it, modify it, extend it, whatever you like:
package com.gplushub.android.view;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
/**
* an {@link ImageView} supporting asynchronous loading from URL. Additional
* APIs: {@link #setImageURL(URL)}, {@link #cancelLoading()}.
*
* @author ep@gplushub.com / Eugen Plischke
*
*/
public class UrlImageView extends ImageView {
private static class UrlLoadingTask extends AsyncTask<URL, Void, Bitmap> {
private final ImageView updateView;
private boolean isCancelled = false;
private InputStream urlInputStream;
private UrlLoadingTask(ImageView updateView) {
this.updateView = updateView;
}
@Override
protected Bitmap doInBackground(URL... params) {
try {
URLConnection con = params[0].openConnection();
// can use some more params, i.e. caching directory etc
con.setUseCaches(true);
this.urlInputStream = con.getInputStream();
return BitmapFactory.decodeStream(urlInputStream);
} catch (IOException e) {
Log.w(UrlImageView.class.getName(), "failed to load image from " + params[0], e);
return null;
} finally {
if (this.urlInputStream != null) {
try {
this.urlInputStream.close();
} catch (IOException e) {
; // swallow
} finally {
this.urlInputStream = null;
}
}
}
}
@Override
protected void onPostExecute(Bitmap result) {
if (!this.isCancelled) {
// hope that call is thread-safe
this.updateView.setImageBitmap(result);
}
}
/*
* just remember that we were cancelled, no synchronization necessary
*/
@Override
protected void onCancelled() {
this.isCancelled = true;
try {
if (this.urlInputStream != null) {
try {
this.urlInputStream.close();
} catch (IOException e) {
;// swallow
} finally {
this.urlInputStream = null;
}
}
} finally {
super.onCancelled();
}
}
}
/*
* track loading task to cancel it
*/
private AsyncTask<URL, Void, Bitmap> currentLoadingTask;
/*
* just for sync
*/
private Object loadingMonitor = new Object();
public UrlImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public UrlImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public UrlImageView(Context context) {
super(context);
}
@Override
public void setImageBitmap(Bitmap bm) {
cancelLoading();
super.setImageBitmap(bm);
}
@Override
public void setImageDrawable(Drawable drawable) {
cancelLoading();
super.setImageDrawable(drawable);
}
@Override
public void setImageResource(int resId) {
cancelLoading();
super.setImageResource(resId);
}
@Override
public void setImageURI(Uri uri) {
cancelLoading();
super.setImageURI(uri);
}
/**
* loads image from given url
*
* @param url
*/
public void setImageURL(URL url) {
synchronized (loadingMonitor) {
cancelLoading();
this.currentLoadingTask = new UrlLoadingTask(this).execute(url);
}
}
/**
* cancels pending image loading
*/
public void cancelLoading() {
synchronized (loadingMonitor) {
if (this.currentLoadingTask != null) {
this.currentLoadingTask.cancel(true);
this.currentLoadingTask = null;
}
}
}
}
Problem
I'm a newbie programmer an I'm making an android program that displays an image on ImageView from a given url. My problem is how do you use this on the AsyncTask? These codes work on min SDK 2.2 but I switched to min SDK 3.0 so it needs to run on the AsyncTask. Thank you for your help! :) ``` protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); satellite(); //satellite's image from main menu } //******satellite url private void satellite() { // TODO Auto-generated method stub ImageView imgView =(ImageView)findViewById(R.id.satellite); Drawable drawable = LoadImageFromWeb("http://www.pagasa.dost.gov.ph/wb/sat_images/satellite.gif"); imgView.setImageDrawable(drawable); } private Drawable LoadImageFromWeb(String url){ try{ InputStream is = (InputStream) new URL(url).getContent(); Drawable d = Drawable.createFromStream(is, "src name"); return d; }catch (Exception e) { System.out.println("Exc="+e); return null; } } ```