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

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/3235.html

(0)
上一篇 2021年7月16日
下一篇 2021年7月16日

相关推荐

发表回复

登录后才能评论