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

有缘人生love

有缘人生love

2016-02-19 11:21

下面图老师小编跟大家分享一个简单易学的android上的一个网络接口和图片缓存框架enif简析教程,get新技能是需要行动的,喜欢的朋友赶紧收藏起来学习下吧!
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 LruCacheString, Bitmap mLruCache;
private static HashMapInteger, SoftReferenceBitmap 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 LruCacheString, 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 HashMapInteger, SoftReferenceBitmap();
}
}
@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) {
SoftReferenceBitmap loading = mResImage.get(mDefaultImage);
if (loading == null || loading.get() == null || loading.get().isRecycled()) {
loading = new SoftReferenceBitmap(BitmapFactory.decodeResource(
context.getResources(), mDefaultImage));
mResImage.put(mDefaultImage, loading);
}
return loading.get();
}
private class DownloadTask extends AsyncTaskString, 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 (SoftReferenceBitmap 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
代码如下:

STRONGpackage 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 ArrayListBasicNameValuePair sValuePairs;//common vps
static {
sValuePairs = new ArrayListBasicNameValuePair();
sValuePairs.add(new BasicNameValuePair("v", "1.0"));
sValuePairs.add(new BasicNameValuePair("format", "json"));
}
}/STRONG

代码如下:

STRONGpackage 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,
ArrayListBasicNameValuePair vp) {
try {
new WSTask(context, listener, action, vp).execute();
} catch (RejectedExecutionException e) {
// do nothing, just keep not crashing.
}
}
}
/STRONG

代码如下:

STRONGpackage 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 AsyncTaskVoid, 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")
ArrayListBasicNameValuePair vps = (ArrayListBasicNameValuePair)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, ArrayListBasicNameValuePair 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")) {
ArrayListHashMapString, String arrList;
arrList = new ArrayListHashMapString, 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 HashMapString, String parse2Map(JSONObject jsonObj) throws IOException {
final HashMapString, String hashMap = new HashMapString, String();
@SuppressWarnings("unchecked")
final IteratorString 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 ArrayListBasicNameValuePair vp = new ArrayListBasicNameValuePair();
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

例子的效果图如下
展开更多 50%)
分享

猜你喜欢

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

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

简析Win8网络和共享中心

电脑入门
简析Win8网络和共享中心

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

简析Chrome和Webkit的渊源

浏览器
简析Chrome和Webkit的渊源

JAVA几个常见错误简析(上)

编程语言 网络编程
JAVA几个常见错误简析(上)

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

一个SQL管理员的web接口

PHP
一个SQL管理员的web接口

共享自己写一个框架DreamScript

Web开发
共享自己写一个框架DreamScript

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Windows8.1预览版升级安装过程

Windows8.1预览版升级安装过程

Javascript实现的分页函数

Javascript实现的分页函数
下拉加载更多内容 ↓