Android Open Source - WebImageView Web Image View






From Project

Back to project page WebImageView.

License

The source code is released under:

MIT License

If you think the Android project WebImageView listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.rsv.widget;
//from w  ww  . j ava 2  s.c o m
import java.lang.ref.WeakReference;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.widget.ImageView;

import com.rsv.comp.IProgressListener;
import com.rsv.comp.ImageLoader;
import com.rsv.utils.LogUtils;

/**
 * ImageView but load from an url
 * 
 */
public class WebImageView extends ImageView {

  /**
   * An AsyncTask instance to manage the url loading
   */
  private RetrieveImageTask task;

  /**
   * The image url
   */
  private String webImageUrl;

  /**
   * The loading progress, 0~100
   */
  private long progress = -1;

  /**
   * The time span to expire, in seconds
   */
  private long expireInSecs = -1;

  /**
   * The outer side listener
   */
  private WebImageProgressListener userImgLoadListener;

  private WebImageProgressListener internImgLoadListener = new WebImageProgressListener() {

    @Override
    public void onError(WebImageView v, Exception e) {
      if (WebImageView.this.userImgLoadListener != null)
        WebImageView.this.userImgLoadListener.onError(v, e);

      WebImageView.this.progress = -2;
    }

    @Override
    public void onStart(WebImageView v) {
      if (WebImageView.this.userImgLoadListener != null)
        WebImageView.this.userImgLoadListener.onStart(v);

      WebImageView.this.progress = 0;
    }

    @Override
    public void onLoading(WebImageView v, int progress) {
      if (WebImageView.this.userImgLoadListener != null)
        WebImageView.this.userImgLoadListener.onLoading(v, progress);

      WebImageView.this.progress = Math.min(99, progress);
    }

    @Override
    public void onLoad(WebImageView v) {
      if (WebImageView.this.userImgLoadListener != null)
        WebImageView.this.userImgLoadListener.onLoad(v);

      WebImageView.this.progress = 100;
    }
  };

  private Runnable runBgTask = null;

  private Handler handler = new Handler();

  /**
   * The image placeholder
   */
  protected Drawable webImagePlaceholder;

  public WebImageView(Context context) {
    super(context);
  }

  public WebImageView(Context context, AttributeSet attrs) {
    super(context, attrs);

    loadAttrs(context, attrs);
  }

  public WebImageView(Context context, AttributeSet attrs, int defaultStyle) {
    super(context, attrs, defaultStyle);
    loadAttrs(context, attrs);
  }

  /**
   * Load some custom attrs, like webImageUrl
   * 
   * @param context
   * @param attrs
   */
  private void loadAttrs(Context context, AttributeSet attrs) {
    if (attrs == null)
      return;

    TypedArray ts = context.obtainStyledAttributes(attrs, R.styleable.WebImageView);

    {
      String url = ts.getString(R.styleable.WebImageView_webImageUrl);

      if (url != null) {

        this.setWebImageUrl(url);
      }
    }
    {
      int expire = ts.getInt(R.styleable.WebImageView_webImageExpireInSecs, -1);

      if (expire >= 0) {

        this.setWebImageExpireInSecs(expire);
      }
    }

    ts.recycle();
  }

  /**
   * Listen for the image loading progress
   */
  public void setWebImageProgressListener(final WebImageProgressListener imgLoadListener) {
    this.userImgLoadListener = imgLoadListener;
  }

  /**
   * Set web image placeholder, which will showed before the real image loaded
   * 
   * @param placeholder
   */
  public void setWebImagePlaceholder(final Drawable placeholder) {
    this.webImagePlaceholder = placeholder;
  }

  /**
   * Set web image placeholder, which will showed before the real image loaded
   * 
   * @param placeholder
   */
  public void setWebImagePlaceholder(final Bitmap placeholder) {
    this.webImagePlaceholder = new BitmapDrawable(this.getContext().getResources(), placeholder);
  }

  /**
   * Set web image placeholder, which will showed before the real image loaded
   * 
   * @param placeholder
   */
  public void setWebImagePlaceholder(int resouceId) {
    this.webImagePlaceholder = this.getContext().getResources().getDrawable(resouceId);
  }

  private void fillPlaceholder() {
    if (webImagePlaceholder != null) {
      setImageDrawable(webImagePlaceholder);

    } else {
      // setImageResource(android.R.color.transparent);
    }
  }

  /**
   * 
   * @return the web image url
   */
  public String getWebImageUrl() {
    return this.webImageUrl;
  }

  public void setWebImageUrl(int resourceId) {
    this.setWebImageUrl(getResources().getString(resourceId));
  }

  /**
   * Set the webimage url
   * 
   * @param url
   */
  public void setWebImageUrl(final String url) {

    if (this.webImageUrl == null && url == null)
      return;

    if (url != null && url.equals(this.webImageUrl)) {

      if (this.progress >= 100) {
        this.internImgLoadListener.onLoad(this);
      }

      return;
    }

    if (task != null) {
      task.tryCancel();
      this.disconnectWebImageTask();
    }

    this.webImageUrl = url;

    this.fillPlaceholder();

    if (runBgTask != null) {
      handler.removeCallbacks(runBgTask);
    }

    if (this.webImageUrl == null)
      return;

    runBgTask = new Runnable() {

      @SuppressLint("NewApi")
      @Override
      public void run() {

        try {
          task = new RetrieveImageTask(WebImageView.this);

          WebImageView.this.internImgLoadListener.onStart(WebImageView.this);

          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
          else
            task.execute();

        } catch (Exception e) {
          LogUtils.logException(e);
        } finally {

          WebImageView.this.runBgTask = null;
        }

      }
    };

    // delayed a little, as the View might be adjust many times
    handler.postDelayed(runBgTask, 10);
  }

  /**
   * Set an expire time(in seconds), default -1
   * 
   * when >0, memory cache will be disabled.
   * 
   * @param secs
   *            0 means no cache; <0 means never expired;
   */
  public void setWebImageExpireInSecs(long secs) {
    this.expireInSecs = secs < 0 ? -1 : secs;
  }

  /**
   * Get the expire time in secs
   * 
   * @return
   */
  public long getWebImageExpireInSecs() {
    return this.expireInSecs;
  }

  /**
   * Web image data got
   * 
   * @param bm
   */
  private void setWebImageBitmap(final Bitmap bm, final Exception e) {

    if (bm == null) {

      // well, something wrong
      this.setScaleType(ScaleType.CENTER_INSIDE);
      // this.setImageResource(R.drawable.holder);

    } else {

      /*
       * if (this.mMaxWidth > 0 && this.mMaxHeight > 0) { bm =
       * Bitmap.createScaledBitmap(bm, this.mMaxWidth, this.mMaxHeight,
       * false); }
       */

      super.setImageBitmap(bm);
    }

    if (e != null) {
      this.internImgLoadListener.onError(this, e);

    } else {
      this.internImgLoadListener.onLoading(this, 100);
    }

    this.internImgLoadListener.onLoad(this);

  }

  private void disconnectWebImageTask() {
    task = null;
  }

  /**
   * 
   * Manage the image loading
   */
  private class RetrieveImageTask extends AsyncTask<Void, Integer, Bitmap> {

    /**
     * Keep a weak reference, as the view instance might be destroyed during
     * the app life cycle
     */
    private final WeakReference<WebImageView> imageViewReference;

    /**
     * the last reported progress
     */
    private long lastReportedProgress = 0;

    /**
     * the last reporting timestamp
     */
    private long lastReportedTime = 0;

    private Exception bgExp = null;

    private RetrieveImageTask(final WebImageView imageView) throws Exception {
      this.imageViewReference = new WeakReference<WebImageView>(imageView);

    }

    private void tryCancel() {
      this.clearRef();

      if (this.getStatus() == Status.PENDING || !this.isCancelled()) {

        // LogUtils.i(this, "cancel RetrieveImageTask");
        this.cancel(false);
      }
    }

    private void clearRef() {
      this.imageViewReference.clear();
    }

    private WebImageView tryGetImageView() {
      return this.imageViewReference.get();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {

      final WebImageView imageView = this.tryGetImageView();

      if (imageView != null) {

        final int lp = values[0];

        imageView.internImgLoadListener.onLoading(imageView, lp);
      }
    }

    @Override
    protected Bitmap doInBackground(Void... args) {

      WebImageView imageView = this.tryGetImageView();

      if (imageView != null) {

        try {

          // LogUtils.v(this, "Load " + imageView.webImageUrl);

          ImageLoader imgLoader = ImageLoader.getImageLoader(imageView.getContext());

          return imgLoader.downloadImg(imageView.webImageUrl, imageView.expireInSecs,
              new IProgressListener() {

                @Override
                public void reportProgress(long progress) {

                  if (lastReportedProgress == progress)
                    return;

                  long ctime = System.currentTimeMillis();

                  if (ctime - lastReportedTime > 100
                      && progress - lastReportedProgress > 0) {

                    lastReportedProgress = progress;
                    lastReportedTime = ctime;

                    RetrieveImageTask.this.publishProgress((int) progress);
                  }

                }
              });

        } catch (Exception e) {
          LogUtils.logException(e);

          bgExp = e;
          return null;
        }

      } else {
        LogUtils.w(this, "doInBackground miss ref to imageView");
      }

      return null;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {

      if (!isCancelled()) {

        WebImageView imageView = this.tryGetImageView();

        if (imageView != null) {

          imageView.setWebImageBitmap(bitmap, this.bgExp);

        } else {
          LogUtils.w(this, "onPostExecute miss ref to imageView");
        }

        imageView.disconnectWebImageTask();
      }

      this.clearRef();
    }
  };

  /**
   * Listen for web image loading
   * 
   */
  public interface WebImageProgressListener {

    /**
     * Web image start loading
     * 
     * @param view
     */
    public void onStart(final WebImageView view);

    /**
     * Web image loading
     * 
     * @param view
     * @param progress
     *            0~100
     */
    public void onLoading(final WebImageView view, final int progress);

    /**
     * Web image loaded
     * 
     * @param view
     */
    public void onLoad(final WebImageView view);

    /**
     * Some error happened during loading
     * 
     * @param view
     * @param e
     */
    public void onError(final WebImageView view, Exception e);

  }

}




Java Source Code List

com.rsv.cache.BaseFileCache.java
com.rsv.cache.BaseMemCache.java
com.rsv.cache.LmtSizeMemCache.java
com.rsv.cache.LmtSpaceFileCache.java
com.rsv.comp.IProgressListener.java
com.rsv.comp.ImageLoader.java
com.rsv.config.ConfigReader.java
com.rsv.config.Constants.java
com.rsv.utils.FileUtils.java
com.rsv.utils.HttpClientUtils.java
com.rsv.utils.IOUtils.java
com.rsv.utils.ImgUtils.java
com.rsv.utils.LogUtils.java
com.rsv.utils.OSUtils.java
com.rsv.utils.StorageUtils.java
com.rsv.widget.WebImageView.java