| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
jopen
10年前发布

Android处理网络和图片的工具类

1:网络的底层环境 采用apache 的httpClient 链接池框架

2:图片缓存采用基于LRU 的算法

3:网络接口采用监听者模式

4 包含图片的OOM 处理(及时回收处理技术的应用)

import java.io.FilterInputStream;  import java.io.IOException;  import java.io.InputStream;  import java.lang.ref.SoftReference;  import java.util.HashMap;  import java.util.concurrent.RejectedExecutionException;      import org.apache.http.HttpEntity;  import org.apache.http.HttpResponse;  import org.apache.http.HttpStatus;  import org.apache.http.client.methods.HttpGet;      import xiaogang.enif.utils.HttpManager;  import xiaogang.enif.utils.IOUtils;  import xiaogang.enif.utils.LogUtils;  import xiaogang.enif.utils.LruCache;  import android.app.ActivityManager;  import android.content.Context;  import android.graphics.Bitmap;  import android.graphics.BitmapFactory;  import android.graphics.BitmapFactory.Options;  import android.graphics.Canvas;  import android.graphics.drawable.BitmapDrawable;  import android.os.AsyncTask;  import android.text.TextUtils;  import android.util.AttributeSet;  import android.widget.ImageView;      public class CacheView extends ImageView {      private static final int DEFAULT_RES_ID = 0;      private int mDefaultImage = DEFAULT_RES_ID;          private static LruCache<String, Bitmap> mLruCache;      private static HashMap<Integer, SoftReference<Bitmap>> mResImage;          private Context mContext;      private LogUtils mLog = LogUtils.getLog(CacheView.class);          public CacheView(Context context, AttributeSet attrs, int defStyle) {          super(context, attrs, defStyle);          init(context);      }          public CacheView(Context context, AttributeSet attrs) {          super(context, attrs);          init(context);          }          public CacheView(Context context) {          super(context);          init(context);      }          private void init(Context context) {          mContext = context;              if (mLruCache == null) {              final int cacheSize = getCacheSize(context);              mLruCache = new LruCache<String, Bitmap>(cacheSize) {                  @Override                  protected int sizeOf(String key, Bitmap bitmap) {                      // The cache size will be measured in bytes rather than                      // number of items.                      return bitmap.getRowBytes() * bitmap.getHeight();                  }                      @Override                  protected void entryRemoved(boolean evicted, String key, Bitmap oldValue,                          Bitmap newValue) {                      if (evicted && oldValue != null && !oldValue.isRecycled()) {                          oldValue.recycle();                          oldValue = null;                      }                  }              };          }              if (mResImage == null) {              mResImage = new HashMap<Integer, SoftReference<Bitmap>>();          }      }          @Override      protected void onDraw(Canvas canvas) {          BitmapDrawable drawable = (BitmapDrawable)getDrawable();          if (drawable == null) {              setDefaultImage();          } else {              if (drawable.getBitmap() == null || drawable.getBitmap().isRecycled()) {                  setDefaultImage();              }          }          try {              super.onDraw(canvas);          } catch(RuntimeException ex) {              }      }          public void setImageUrl(String url, int resId) {          setTag(url);          Bitmap bitmap = getBitmapFromCache(url);          if (bitmap == null || bitmap.isRecycled()) {              mDefaultImage = resId;              setDefaultImage();              try {                  new DownloadTask().execute(url);              } catch (RejectedExecutionException e) {                  // do nothing, just keep not crash              }          } else {              setImageBitmap(bitmap);          }      }          private void setDefaultImage() {          if (mDefaultImage != DEFAULT_RES_ID) {              setImageBitmap(getDefaultBitmap(mContext));          }      }          private Bitmap getDefaultBitmap(Context context) {          SoftReference<Bitmap> loading = mResImage.get(mDefaultImage);          if (loading == null || loading.get() == null || loading.get().isRecycled()) {              loading = new SoftReference<Bitmap>(BitmapFactory.decodeResource(                      context.getResources(), mDefaultImage));              mResImage.put(mDefaultImage, loading);          }          return loading.get();      }          private class DownloadTask extends AsyncTask<String, Void, Bitmap> {          private String mParams;              @Override          public Bitmap doInBackground(String... params) {              mParams = params[0];              final Bitmap bm = download(mParams);              addBitmapToCache(mParams, bm);              return bm;          }              @Override          public void onPostExecute(Bitmap bitmap) {              String tag = (String)getTag();              if (!TextUtils.isEmpty(tag) && tag.equals(mParams)) {                  if (bitmap != null) {                      setImageBitmap(bitmap);                  }              }          }      };          /*       * An InputStream that skips the exact number of bytes provided, unless it       * reaches EOF.       */      static class FlushedInputStream extends FilterInputStream {          public FlushedInputStream(InputStream inputStream) {              super(inputStream);          }              @Override          public long skip(long n) throws IOException {              long totalBytesSkipped = 0L;              while (totalBytesSkipped < n) {                  long bytesSkipped = in.skip(n - totalBytesSkipped);                  if (bytesSkipped == 0L) {                      int b = read();                      if (b < 0) {                          break; // we reached EOF                      } else {                          bytesSkipped = 1; // we read one byte                      }                  }                  totalBytesSkipped += bytesSkipped;              }              return totalBytesSkipped;          }      }          private Bitmap download(String url) {          InputStream in = null;          HttpEntity entity = null;          Bitmap bmp = null;          try {              final HttpGet get = new HttpGet(url);              final HttpResponse response = HttpManager.execute(mContext, get);              if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {                  entity = response.getEntity();                  in = entity.getContent();                  try {                      bmp = getDecodeBitmap(in, url);                  } catch (OutOfMemoryError err) {                      Runtime.getRuntime().gc();                      bmp = getDecodeBitmap(in, url);                  }              } else {                  get.abort();                  return bmp;              }              addBitmapToCache(url, bmp);          } catch (IOException e) {              return bmp;          } finally {              IOUtils.closeStream(in);          }          return bmp;      }          private final Bitmap getDecodeBitmap(InputStream in, String url) {          Options options = new Options();          options.inPurgeable = true;          options.inInputShareable = true;          return BitmapFactory.decodeStream(new FlushedInputStream(in), null, options);      }          private final void addBitmapToCache(String url, Bitmap bitmap) {          if (bitmap != null) {              mLruCache.put(url, bitmap);              Runtime.getRuntime().gc();          }      }          private final Bitmap getBitmapFromCache(String url) {          return mLruCache.get(url);      }          private int getCacheSize(Context context) {          // According to the phone memory, set a proper cache size for LRU cache          // dynamically.          final ActivityManager am = (ActivityManager)context                  .getSystemService(Context.ACTIVITY_SERVICE);          final int memClass = am.getMemoryClass();              int cacheSize;          if (memClass <= 24) {              cacheSize = (memClass << 20) / 24;          } else if (memClass <= 36) {              cacheSize = (memClass << 20) / 18;          } else if (memClass <= 48) {              cacheSize = (memClass << 20) / 12;          } else {              cacheSize = (memClass << 20) >> 3;          }          mLog.debug("cacheSize == "+cacheSize);          System.out.println("cacheSize == "+cacheSize);          return cacheSize;      }          public static void recycle() {          if (mLruCache != null && !mLruCache.isEmpty()) {              mLruCache.evictAll();              mLruCache = null;          }              if (mResImage != null) {              for (SoftReference<Bitmap> reference : mResImage.values()) {                  Bitmap bitmap = reference.get();                  if (bitmap != null && !bitmap.isRecycled()) {                      bitmap.recycle();                      bitmap = null;                  }              }              mResImage = null;          }      }  }          说明:    1)entryRemoved 在做Bitmap recyle 的时候的三个条件缺一不可    2)onDraw 里面判断图片是否被回收,如果回收  需要设置默认的图片    3)add bitmap 到cache 的时候 Runtime.getRuntime().gc 的调用