android 上的一个网络接口和图片框架

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

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

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

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

package xiaogang.enif.image;

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

转载 http://blog.csdn.net/androidzhaoxiaogang/article/details/8211649

时间: 2024-11-10 09:24:36

android 上的一个网络接口和图片框架的相关文章

知乎上有一个问题“在mfc框架中,有上面方法能直接将opencv2.0库中的Mat格式图片传递到Picture Control”中显示?

一直以来,我使用的方法都是shiqiyu在opencvchina上面提供的引入directshow,并且采用cvvimage和cameraDs的方法.这个方法虽然在xp/win7/win8下面都能够成果使用,但是一直以来我都没有动机去深入看一看这个方法.这次在知乎上面看到 jie wu 提出的“将Opencv窗口添加到PictureControl”中的方法,感到思路很好,进行了具体实现 http://pan.baidu.com/s/1nuixdhR 具体可以看代码,我帖一些主要代码 void C

android上的缓存、缓存算法和缓存框架

1.使用缓存的目的 缓存是存取数据的临时地,因为取原始数据代价太大了,加了缓存,可以取得快些.缓存可以认为是原始数据的子集,它是从原始数据里复制出来的,并且为了能被取回,被加上了标志. 在android开发中,经常要访问网络数据比如大量网络图片,如果每次需要同一张图片都去网络获取,这代价显然太大了.可以考虑设置本地文件缓存和内存 缓存,存储从网络取得的数据:本地文件缓存空间并非是无限大的,容量越大读取效率越低,可设置一个折中缓存容量比如10M,如果缓存已满,我们需要采用合 适的替换策略换掉一个已

在 Android 上使用 RxNetty

在 Android 上使用 RxNetty Netty是由JBOSS提供的一个Java开源框架,是一个支持TCP/UDP/HTTP等网络协议的通信框架,和Mina类似,广泛应用于RPC框架.RxNetty则是支持RxJava的Netty开源框架,现在我们来看一下在Android上如何使用RxNetty. 添加RxNetty 在 Android Studio 中添加 RxNetty 的依赖: 把RxNetty的tcp包加入到依赖,直接这样编译会有两个问题,第一个问题是jar重复: com.andr

android上实现人脸识别的功能

====================问题描述==================== 如题,小弟想在android上实现一个基于人脸识别的功能,大致的实现框架是这样的: 1.通过前置照相机捕捉到人的脸部特征2.将人的脸部特征通过一些算法(网上查看诸如adaboost算法,PCA算法)取得特征值,然后ID化3.将人脸ID化的结果存入数据库4.重复1,2如果ID化的结果在人脸特征值数据库中某记录值的阈值范围内,则证明该值存在,通过验证,否则,提醒注册人脸特征库. 现在基本确定实现是这样的一个流程

Android Bitmap 开源图片框架分析(精华三)

主要介绍这三个框架,都挺有名的,其他的框架估计也差不多了 Android-Universal-Image-Loaderhttps://github.com/nostra13/Android-Universal-Image-Loader ImageLoaderhttps://github.com/novoda/ImageLoader Volley(综合框架,包含图片部分)https://github.com/mcxiaoke/android-volley 扯淡时间,可以跳过这段这些开源框架的源码还

Android Bitmap 开源图片框架分析(精华四)

disk缓存主要难点在于内存缓存,disk缓存其实比较简单,就是图片加载完成后把图片文件存到本地方便下次使用 同样,先贴一下官方主页的介绍(主页地址见文章最开始处)和内存缓存差不多,根据算法不同提供了几种类别,可以自行通过ImageLoaderConfiguration.discCache(..)设置<ignore_js_op> 硬盘缓存,保存是以文件的形式框架提供了4种类型,具体算法规则不同,看名字我们大概也能知道对应意思 UnlimitedDiscCache                

服务器基于PHP CodeIgniter,Android基于Volley实现多文件/图片上传(含服务器,web版和android客户端完整代码)

问题背景:app在上传图片时,同时传递参数,支持传递多个图片.本文中的环境默认已经配好了服务器的CodeIgniter框架.事实上不使用这个框架也是可以的. 一,服务器部分 1,在controllers下的helpers新建文件upload_helper.php <?php /** * Make multifile array input complaint with CI_Upload.<br> * For use files[ ] input name you must use it

Android Bitmap 开源图片框架分析(精华五)

本帖最后由 boredream 于 2014-5-27 09:07 编辑 ImageLoader和Volley图片部分还包括其他大部分图片框架,基本上图片处理都差不多,区别仅在于部分优化了,而优化方面UIL即Universal-Image-Loader框架做的最好,所以这部分章节算是温习一下图片处理以及寻找下其他框架里面一些不一样的图片处理方式(只关注图片方面) 首先是ImageLoaderhttps://github.com/novoda/ImageLoader主要还是分析图片加载的核心代码部

如何在android上 使用gif图片(android开源库android-gif-drawabl)

android开源库android-gif-drawable的使用 android的开源库是用来在android上显示gif图片的.我在网上查了一下,大家说这个框架写的不错,加载大的gif图片   不会内存溢出,于是我就想试试这个开源库,我下了作者的源代码和例子,但是我却跑不起来.不知道为什么,我又到网上去找使用这个开源库的例子发现有一个,我也下载了下来,发现还是跑不起来.我决定自己好好试试这个源代码,终于在我的努力下现在可以用了.废话完了 现在教大家怎么用这个库.大家不想看怎么做的 可以到后面