android 网络图片工具类,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 mLruCache;

private static HashMap> 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(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>();

}

}

@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 loading = mResImage.get(mDefaultImage);

if (loading == null || loading.get() == null || loading.get().isRecycled()) {

loading = new SoftReference(BitmapFactory.decodeResource(

context.getResources(), mDefaultImage));

mResImage.put(mDefaultImage, loading);

}

return loading.get();

}

private class DownloadTask extends AsyncTask {

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 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 的调用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值