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

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"));
    }

}
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.
        }
    }
}

 

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);
    }
}


说明:

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>

例子的效果图如下:





完整例子代码详见:http://code.google.com/p/enif/

或者 http://download.csdn.net/detail/androidzhaoxiaogang/4797109 

 

 

 

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
本人测试过,挺好用的,省去了好多麻烦:afinal 0.3 主要更新如下: 1、更新FinalBitmap模块,解决线程并发没有回收线程的问题 2、重写了FinalHttp模块 具体 change log 如下: FinalBitmap添加三个方法 public void onResume() public void onPause() public void onDestroy() 在activity生命周期方法中调用给方法释放内存和暂停图片加载线程 FinalHttp添加方法如下(目前AjaxCallBack泛型只支持String和file。有时间将会扩展JSONObject,xmlDom,byte[],bitmap等): public HttpClient getHttpClient() public HttpContext getHttpContext() public void configCookieStore(CookieStore cookieStore) //配置cookie public void configUserAgent(String userAgent) public void configTimeout(int timeout)//配置超时时间 public void configSSLSocketFactory(SSLSocketFactory sslSocketFactory) //配置https请求 public void configRequestExecutionRetryCount(int count)//配置网络异常自动重复连接请求次数 public void addHeader(String header, String value) //添加http请求头 //------------------get 请求----------------------- public void get( String url, AjaxCallBack<? extends Object> callBack) public void get( String url, AjaxParams params, AjaxCallBack<? extends Object> callBack) public void get( String url, Header[] headers, AjaxParams params, AjaxCallBack<? extends Object> callBack) public Object getSync( String url) //同步get请求,请在子线程执行这个操作,否则非常有可能报ANR public Object getSync( String url, AjaxParams params) public Object getSync( String url, Header[] headers, AjaxParams params) //------------------post 请求----------------------- public void post(String url, AjaxCallBack<? extends Object> callBack) public void post(String url, AjaxParams params, AjaxCallBack<? extends Object> callBack) public void post( String url, HttpEntity entity, String contentType, AjaxCallBack<? extends Object> callBack) public void post( String url, Header[] headers, AjaxParams params, String contentType,AjaxCallBack<? extends Object> callBack) public void post( String url, Header[] headers, HttpEntity entity, String contentType,AjaxCallBack<? extends Object> callBack) public Object postSync(String url) //同步post请求,请在子线程执行这个操作,否则非常有可能报ANR public Object postSync(String url, AjaxParams params) public Object postSync( String url, HttpEntity entity, String contentType) public Object postSync( String url, Header[] headers, AjaxParams params, String contentType) public Object postSync( String url, Header[] headers, HttpEntity entity, String contentType) //------------------put 请求----------------------- public void put(String url, AjaxCallBack<? extends Object> callBack) public void put( String url, AjaxParams params, AjaxCallBack<? extends Object> callBack) public void put( String url, HttpEntity entity, String contentType, AjaxCallBack<? extends Object> callBack) public void put(String url,Header[] headers, HttpEntity entity, String contentType, AjaxCallBack<? extends Object> callBack) public Object putSync(String url) //同步put请求,请在子线程执行这个操作,否则非常有可能报ANR public Object putSync( String url, AjaxParams params) public Object putSync(String url, HttpEntity entity, String contentType) public Object putSync(String url,Header[] headers, HttpEntity entity, String contentType) //------------------delete 请求----------------------- public void delete( String url, AjaxCallBack<? extends Object> callBack) public void delete( String url, Header[] headers, AjaxCallBack<? extends Object> callBack) public Object deleteSync(String url) //同步delete请求,请在子线程执行这个操作,否则非常有可能报ANR public Object deleteSync( String url, Header[] headers) //---------------------下载--------------------------------------- public void download(String url,String target,AjaxCallBack<File> callback) public void download( String url,AjaxParams params, String target, AjaxCallBack<? extends Object> callback) 附送请求demo和下载demo

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值