android上的一个网络接口和图片缓存框架enif简析

1.底层网络接口采用apache的httpclient连接池框架;

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

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

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

图片核心处理类:CacheView.java

复制代码 代码如下:

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 recycle的时候的3个条件缺一不可;

2)onDraw里面判断图片是否被回收,如果回收,需要设置默认图片;

3)add bitmap到cache的时候Runtime.getRuntime().gc();的调用;

4)getCacheSize可以根据手机具体的内存来动态设置我们实际需要的缓存大小;

5)退出时,记得调用recycle()方法;

网络接口核心类:WSAPI.java, WSCfg.java, WSTask.java

复制代码 代码如下:

<STRONG>package xiaogang.enif.net;

import java.util.ArrayList;

import org.apache.http.message.BasicNameValuePair;

/**

* web service configuration file

* */

public class WSCfg {

public static final int USER_LOGIN = 0;//action

public static final int USER_LOGOUT = 1;//action

public static ArrayList<BasicNameValuePair> sValuePairs;//common vps

static {

sValuePairs = new ArrayList<BasicNameValuePair>();

sValuePairs.add(new BasicNameValuePair("v", "1.0"));

sValuePairs.add(new BasicNameValuePair("format", "json"));

}

}</STRONG>

复制代码 代码如下:

<STRONG>package xiaogang.enif.net;

import java.util.ArrayList;

import java.util.concurrent.RejectedExecutionException;

import org.apache.http.message.BasicNameValuePair;

import xiaogang.enif.net.WSTask.TaskListener;

import android.content.Context;

public class WSAPI {

private WSAPI() {

}

public static void execute(Context context, TaskListener listener, int action,

ArrayList<BasicNameValuePair> vp) {

try {

new WSTask(context, listener, action, vp).execute();

} catch (RejectedExecutionException e) {

// do nothing, just keep not crashing.

}

}

}

</STRONG>

复制代码 代码如下:

<STRONG>package xiaogang.enif.net;

import java.io.IOException;

import java.io.InputStream;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Iterator;

import org.apache.http.HttpEntity;

import org.apache.http.HttpResponse;

import org.apache.http.HttpStatus;

import org.apache.http.client.entity.UrlEncodedFormEntity;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.message.BasicNameValuePair;

import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;

import xiaogang.enif.utils.HttpManager;

import xiaogang.enif.utils.IOUtils;

import xiaogang.enif.utils.LogUtils;

import android.app.Activity;

import android.content.Context;

import android.os.AsyncTask;

import android.text.TextUtils;

public class WSTask extends AsyncTask<Void, Void, Object> {

private int mAction;

private String mErrorCode;

private Object mParameter;

private Context mContext;

private TaskListener mTaskListener;

private Exception mReason;

private final LogUtils mLog = LogUtils.getLog(WSTask.class);

public WSTask(Context context, TaskListener listener, int action, Object paramObject) {

mContext = context;

mTaskListener = listener;

mParameter = paramObject;

mAction = action;

}

@Override

public Object doInBackground(Void... arg0) {

Object result = null;

try {

@SuppressWarnings("unchecked")

ArrayList<BasicNameValuePair> vps = (ArrayList<BasicNameValuePair>)mParameter;

final String jsonString = request(mContext, "your url", vps);

mLog.debug(jsonString);

result = parseJson(jsonString);

if (result != null && result instanceof String

&& TextUtils.isDigitsOnly((String)result)) {

mErrorCode = (String)result;

return null;

}

} catch (Exception e) {

mReason = e;

mLog.error(e.getMessage());

return null;

}

return result;

}

@Override

public void onPostExecute(Object result) {

if (mContext== null) {

clearTask();

return;

}

if (mContext instanceof Activity && ((Activity) mContext).isFinishing()) {

clearTask();

return;

}

if (result == null || mReason != null) {

mTaskListener.onFailed(mAction, mErrorCode, mReason);

} else {

mTaskListener.onSuccess(mAction, result);

}

clearTask();

}

private String request(Context context, String url, ArrayList<BasicNameValuePair> vp)

throws IOException {

final HttpPost post = new HttpPost(url);

post.setEntity(new UrlEncodedFormEntity(vp, "UTF_8"));

InputStream in = null;

HttpEntity entity = null;

try {

final HttpResponse response = HttpManager.execute(context, post);

final int statusCode = response.getStatusLine().getStatusCode();

if (statusCode == HttpStatus.SC_OK) {

entity = response.getEntity();

if (entity != null) {

in = entity.getContent();

return IOUtils.stream2String(in);

}

} else {

post.abort();

mLog.error("http code: " + response.getStatusLine().getStatusCode());

}

return null;

} catch (IOException ex) {

post.abort();

throw ex;

} catch (RuntimeException ex) {

post.abort();

throw ex;

} finally {

if(entity!=null) {

entity.consumeContent();

}

IOUtils.closeStream(in);

}

}

private Object parseJson(String jsonString) throws IOException {

try {

JSONObject jobj = new JSONObject(jsonString);

if (jobj.has("errorcode")) {

return jobj.optString("errorcode");

}

if (jobj.has("resultlist")) {

ArrayList<HashMap<String, String>> arrList;

arrList = new ArrayList<HashMap<String, String>>();

JSONArray jsonArray = jobj.optJSONArray("resultlist");

final int len = jsonArray.length();

for (int i = 0; i < len; i++) {

final JSONObject obj = (JSONObject)jsonArray.opt(i);

arrList.add(parse2Map(obj));

}

return arrList;

} else {

return parse2Map(jobj);

}

} catch (JSONException e) {

IOException ioe = new IOException("Invalid json String...");

ioe.initCause(e);

throw ioe;

}

}

private HashMap<String, String> parse2Map(JSONObject jsonObj) throws IOException {

final HashMap<String, String> hashMap = new HashMap<String, String>();

@SuppressWarnings("unchecked")

final Iterator<String> keyIter = jsonObj.keys();

String key, value;

while (keyIter != null && keyIter.hasNext()) {

key = keyIter.next();

value = jsonObj.optString(key);

hashMap.put(key, value);

}

return hashMap;

}

private void clearTask() {

mTaskListener = null;

mParameter = null;

mContext = null;

}

public interface TaskListener {

public void onSuccess(int action, Object result);

public void onFailed(int action, String errcode, Exception ex);

}

}

</STRONG>

说明:

1)根据你的服务器接口实际情况,去修改parseJson方法;

2)WSCfg里面可以定义接口的action;

sample:

复制代码 代码如下:

package xiaogang.enif.ui;

import java.util.ArrayList;

import org.apache.http.message.BasicNameValuePair;

import xiaogang.enif.R;

import xiaogang.enif.image.CacheView;

import xiaogang.enif.net.WSAPI;

import xiaogang.enif.net.WSCfg;

import xiaogang.enif.net.WSTask.TaskListener;

import xiaogang.enif.widget.ListsApdater;

import android.app.Activity;

import android.os.Bundle;

import android.widget.ListView;

public class MainActivity extends Activity implements TaskListener {

ListView mList;

ListsApdater mAdapter;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

setupViews();

}

private void setupViews() {

mList = (ListView)findViewById(R.id.list);

mAdapter = new ListsApdater(this, mUrls);

mList.setAdapter(mAdapter);

final ArrayList<BasicNameValuePair> vp = new ArrayList<BasicNameValuePair>();

vp.addAll(WSCfg.sValuePairs);

vp.add(new BasicNameValuePair("imei", "123"));

vp.add(new BasicNameValuePair("imsi", "123"));

WSAPI.execute(this, this, WSCfg.USER_LOGIN, vp);

}

@Override

protected void onDestroy() {

super.onDestroy();

mAdapter.recycle();

CacheView.recycle();

}

private String[] mUrls = {

"http://a3.twimg.com/profile_images/670625317/aam-logo-v3-twitter.png",

"http://a3.twimg.com/profile_images/740897825/AndroidCast-350_normal.png",

"http://a3.twimg.com/profile_images/121630227/Droid_normal.jpg",

"http://a1.twimg.com/profile_images/957149154/twitterhalf_normal.jpg",

"http://a1.twimg.com/profile_images/97470808/icon_normal.png",

"http://a3.twimg.com/profile_images/511790713/AG.png",

"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",

"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",

"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",

"http://a1.twimg.com/profile_images/349012784/android_logo_small_normal.jpg",

"http://a1.twimg.com/profile_images/841338368/ea-twitter-icon.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",

"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",

"http://a1.twimg.com/profile_images/655119538/andbook.png",

"http://a3.twimg.com/profile_images/768060227/ap4u_normal.jpg",

"http://a1.twimg.com/profile_images/74724754/android_logo_normal.png",

"http://a3.twimg.com/profile_images/681537837/SmallAvatarx150_normal.png",

"http://a1.twimg.com/profile_images/63737974/2008-11-06_1637_normal.png",

"http://a3.twimg.com/profile_images/548410609/icon_8_73.png",

"http://a1.twimg.com/profile_images/612232882/nexusoneavatar_normal.jpg",

"http://a1.twimg.com/profile_images/213722080/Bugdroid-phone_normal.png",

"http://a1.twimg.com/profile_images/645523828/OT_icon_090918_android_normal.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a3.twimg.com/profile_images/77641093/AndroidPlanet.png",

"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",

"http://a1.twimg.com/profile_images/655119538/andbook_normal.png",

"http://a3.twimg.com/profile_images/511790713/AG_normal.png",

"http://a3.twimg.com/profile_images/956404323/androinica-avatar.png",

"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",

"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",

"http://a1.twimg.com/profile_images/349012784/android_logo_small_normal.jpg",

"http://a1.twimg.com/profile_images/841338368/ea-twitter-icon_normal.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a3.twimg.com/profile_images/77641093/AndroidPlanet.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300.jpg",

"http://a1.twimg.com/profile_images/655119538/andbook_normal.png",

"http://a3.twimg.com/profile_images/511790713/AG_normal.png",

"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",

"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",

"http://a3.twimg.com/profile_images/121630227/Droid.jpg",

"http://a1.twimg.com/profile_images/97470808/icon_normal.png",

"http://a3.twimg.com/profile_images/511790713/AG_normal.png",

"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",

"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man.png",

"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",

"http://a1.twimg.com/profile_images/349012784/android_logo_small_normal.jpg",

"http://a1.twimg.com/profile_images/841338368/ea-twitter-icon_normal.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a3.twimg.com/profile_images/77641093/AndroidPlanet.png",

"http://a3.twimg.com/profile_images/121630227/Droid_normal.jpg",

"http://a1.twimg.com/profile_images/957149154/twitterhalf_normal.jpg",

"http://a1.twimg.com/profile_images/97470808/icon.png",

"http://a3.twimg.com/profile_images/511790713/AG_normal.png",

"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",

"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",

"http://a1.twimg.com/profile_images/349012784/android_logo_small_normal.jpg",

"http://a1.twimg.com/profile_images/841338368/ea-twitter-icon.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",

"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",

"http://a1.twimg.com/profile_images/655119538/andbook_normal.png",

"http://a3.twimg.com/profile_images/768060227/ap4u_normal.jpg",

"http://a1.twimg.com/profile_images/74724754/android_logo.png",

"http://a3.twimg.com/profile_images/681537837/SmallAvatarx150_normal.png",

"http://a1.twimg.com/profile_images/63737974/2008-11-06_1637_normal.png",

"http://a3.twimg.com/profile_images/548410609/icon_8_73_normal.png",

"http://a1.twimg.com/profile_images/612232882/nexusoneavatar_normal.jpg",

"http://a1.twimg.com/profile_images/213722080/Bugdroid-phone_normal.png",

"http://a1.twimg.com/profile_images/645523828/OT_icon_090918_android.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",

"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",

"http://a1.twimg.com/profile_images/655119538/andbook.png",

"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",

"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",

"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",

"http://a1.twimg.com/profile_images/349012784/android_logo_small_normal.jpg",

"http://a1.twimg.com/profile_images/841338368/ea-twitter-icon.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",

"http://a1.twimg.com/profile_images/655119538/andbook_normal.png",

"http://a3.twimg.com/profile_images/511790713/AG_normal.png",

"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",

"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",

"http://a3.twimg.com/profile_images/121630227/Droid_normal.jpg",

"http://a1.twimg.com/profile_images/957149154/twitterhalf.jpg",

"http://a1.twimg.com/profile_images/97470808/icon_normal.png",

"http://a3.twimg.com/profile_images/511790713/AG_normal.png",

"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",

"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",

"http://a1.twimg.com/profile_images/841338368/ea-twitter-icon_normal.png",

"http://a3.twimg.com/profile_images/64827025/android-wallpaper6_2560x160_normal.png",

"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png"

};

@Override

public void onSuccess(int action, Object result) {

switch (action) {

case WSCfg.USER_LOGIN:

break;

case WSCfg.USER_LOGOUT:

break;

}

}

@Override

public void onFailed(int action, String errcode, Exception ex) {

switch (action) {

case WSCfg.USER_LOGIN:

break;

case WSCfg.USER_LOGOUT:

break;

}

}

}

复制代码 代码如下:

package xiaogang.enif.widget;

import xiaogang.enif.R;

import xiaogang.enif.image.CacheView;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.TextView;

public class ListsApdater extends BaseAdapter {

private String[] mUrls;

private LayoutInflater mInflater;

public ListsApdater(Context context, String[] urls) {

mUrls = urls;

mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

}

@Override

public int getCount() {

return mUrls.length;

}

@Override

public Object getItem(int position) {

return position;

}

@Override

public long getItemId(int position) {

return position;

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder holder = null;

if (null == convertView) {

holder = new ViewHolder();

convertView = mInflater.inflate(R.layout.item, null);

holder.view = (CacheView)convertView.findViewById(R.id.image);

holder.text = (TextView)convertView.findViewById(R.id.text);

convertView.setTag(holder);

} else {

holder = (ViewHolder)convertView.getTag();

}

holder.text.setText("item "+position);

holder.view.setImageUrl(mUrls[position], R.drawable.stub);

return convertView;

}

public void recycle() {

mUrls = null;

mInflater = null;

}

private class ViewHolder {

CacheView view;

TextView text;

}

}

main.xml和item.xml

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical" >

<ListView

android:id="@+id/list"

android:layout_width="fill_parent"

android:layout_height="0dip"

android:layout_weight="1" />

</LinearLayout>

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="wrap_content" >

<xiaogang.enif.image.CacheView

android:id="@+id/image"

android:layout_width="50dip"

android:layout_height="50dip"

android:scaleType="centerCrop"

android:src="@drawable/stub" />

<TextView

android:id="@+id/text"

android:layout_width="0dip"

android:layout_height="wrap_content"

android:layout_gravity="left|center_vertical"

android:layout_marginLeft="10dip"

android:layout_weight="1"

android:textSize="20dip" />

</LinearLayout>

例子的效果图如下:

时间: 2024-09-20 12:15:24

android上的一个网络接口和图片缓存框架enif简析的相关文章

android上的一个网络接口和图片缓存框架enif简析_Android

1.底层网络接口采用apache的httpclient连接池框架: 2.图片缓存采用基于LRU的算法: 3.网络接口采用监听者模式: 4.包含图片的OOM处理(及时回收处理技术的应用): 图片核心处理类:CacheView.java 复制代码 代码如下: package xiaogang.enif.image; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; imp

如何在android上实现一个基于贝叶斯的垃圾短信过滤软件

问题描述 如何在android上实现一个基于贝叶斯的垃圾短信过滤软件 有哪位高人做过在android上实现一个基于贝叶斯的垃圾短信过滤软件,求思路. 解决方案 在客户端本地做贝叶斯不合适的吧?

移动应用开发(IOS/android等)中一个通用的图片缓存方案讲解(附流程图)

在移动应用开发中,我们经常会遇到从网络请求图片到设备上展示的场景. 如果每次都重复发起请求,浪费流量.浪费电量,用户体验也不佳: 将图片持久化到磁盘也不失为一种策略:但每次从文件读取图片也存在一定的io开销,就算采用此策略,我们也需要控制磁盘缓存的容量,以免占用过多系统资源. 其实没有一个方案可以说是完美的方案,只有最适合自己业务需求的方案,才可以说是一个好方案. 我们下面所讲解的方案具备很强的通用性,设计思路简单而清晰: 1.假设每个网络图片的url具有唯一性,如果网络上的图片变化了,会引起输

在Android上,一个完整的UDP通信模块应该是怎样的?

CP与UDP差异对比分析 在这篇文章中,在可靠性.数据发送.适用场景等多个方面分析了二者的区别.而本文的目的是想给大家介绍下在 Android 设备上,一个手机通过热点连接另一个手机.这种场景下,完整的 UDP 通信模块应该考虑哪些方面,又应该如何优化,如何避开一些坑呢? UDP 在 Java 中的使用 我们都知道,开发一个 Android 应用程序,目前大多数还是使用的是 Java 语言.在 Java 语言中怎么去使用 UDP 协议呢? 上篇文章中我们没说 Socket,其实 Socket 可

picasso图片缓存框架

picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/,可以实现图片下载和缓存功能. picasso使用简单,如下 [java] view plaincopyprint? Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);   主要有以下一些特性: 在adapter中回收和取消当前的下载: 使用最少的内

Android图片缓存之Bitmap详解(一)_Android

前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类.  Bitmap:Bitmap是Android系统中的图像处理的最重要类之一.用它可以获取图像文件信息,进行图像剪切.旋转.缩放等操作,并可以指定格式保存图像文件. 重要函数  •public void recycle() // 回收位图占用的内存空间,把位图标记为Dead  •public final boolean isRecycled()

Android图片缓存之初识Glide(三)_Android

前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实现方案不能满足项目的需求改用Afinal,由于Afinal不再维护而选择了师出同门的Xutils,中间也接触过别的开源框架比如Picasso,对Picasso的第一次印象就不太好,初次接触是拿到了公司刚从外包公司接手过来的图片社交类app,对内存占用太大,直接感受就是导致ListView滑动有那么一

Android图片缓存之初识Glide(三)

前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实现方案不能满足项目的需求改用Afinal,由于Afinal不再维护而选择了师出同门的Xutils,中间也接触过别的开源框架比如Picasso,对Picasso的第一次印象就不太好,初次接触是拿到了公司刚从外包公司接手过来的图片社交类app,对内存占用太大,直接感受就是导致ListView滑动有那么一

Android图片缓存之Bitmap详解(一)

前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. Bitmap: Bitmap是Android系统中的图像处理的最重要类之一.用它可以获取图像文件信息,进行图像剪切.旋转.缩放等操作,并可以指定格式保存图像文件.  重要函数  •public void recycle() // 回收位图占用的内存空间,把位图标记为Dead  •public final boolean isRecycled(