天天看點

開源架構之Volley

在Android開發中有很多的開源架構,比如Volley,xUtils,okhttp,

afinal等開源架構,由于本人接觸Android時間不長,所接觸到的開源架構并不多,了解的也不深,如果有說的不對的地方你他媽來打我啊

Volley是Google官方的開源架構,是一款輕量級的開源架構

可以用他實作多種網絡請求(json的下載下傳。檔案的上傳)

第一步 在Application初始化請求隊列

package com.longyue.customvolley2;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;

import android.app.Application;

public class VolleyApplication extends Application {

    /**
     * 01. 建立  請求隊列
     * 02. 将 請求隊列 加入到 AndroidMain.xml中
     * 03. 
     */

    private static RequestQueue queue;

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        queue=Volley.newRequestQueue(getApplicationContext());
    }

    //入口
    public static RequestQueue getQueue(){
        return queue;
    }
}
           

第二步 定義三級緩存路徑(記憶體,軟引用,磁盤)

1:記憶體緩存工具類 采用LruCaChe算法

package com.longyue.volley;

import java.io.File;

import android.graphics.Bitmap;
import android.util.Log;
import android.util.LruCache;
import com.android.volley.toolbox.ImageLoader.ImageCache;

public class VolleyBitmapCache implements ImageCache{
    private LruCache<String,Bitmap> cache;
    //設定最大的 尺寸值
    // 磁盤緩存對象
    // 懶漢式:
    private static VolleyBitmapCache mCache;
    private DiskLruCache mDisk;
    private VolleyBitmapCache() {
        //構造方法 實作 LruCache 緩存 圖檔
        int maxSize=**;
        cache=new LruCache<String,Bitmap>(maxSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes()*value.getHeight();
            }
            // 從LruCache移除某個條目的方法
            @Override
            protected void entryRemoved(boolean evicted, String key,
                    Bitmap oldValue, Bitmap newValue) {
                // 把LruCache中要移除的條目,放到軟引用中.
                if (evicted) {
                    ImageSoftReference.getInstance().putSoftReference(key,
                            oldValue);
                }
                super.entryRemoved(evicted, key, oldValue, newValue);
            }
        };
        // 建立磁盤緩存大小
        mDisk = DiskLruCache.openCache(new File(Constant.cachepath),Constant.MAXBYTESIZE);
    }

    public static VolleyBitmapCache getInstance() {
        if (mCache == null) {
            mCache = new VolleyBitmapCache();
        }
        return mCache;
    }


    @Override
    public Bitmap getBitmap(String url) {
        // 從LruCache中取
        Log.e("ccccc","1111");
        Bitmap bitmap = cache.get(url);
        Log.e("ccccc","2222");
        if (bitmap == null) {
            // 從SoftReference中取
            bitmap = ImageSoftReference.getInstance().getSoftReference(url);
            // 如果軟引用中沒有.則從磁盤中取
            if (bitmap == null) {
                // TODO:從磁盤中取:
                bitmap = mDisk.get(url);
            }
        }
        return bitmap;
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        // 設定
        cache.put(url, bitmap);
        mDisk.put(url, bitmap);
    }
    // 擦除緩存的方法
    public void evictAll() {
        cache.evictAll();
        mDisk.clearCache();
    }

    // 擦除緩存的方法
    public void evictOne(String key) {
        cache.remove(key);
    }
}
           

2:軟引用 工具類 可有可無 有總比沒有好

package com.longyue.volley;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

import android.graphics.Bitmap;

public class ImageSoftReference {

    // 新買的手機---->強引用.
    // 玩了一段時間後:手機套---->手機放在套子中:軟引用
    // 往map中放東西.----
    // SoftReference:手機套
    // Bitmap:手機

    // 存放軟引用的集合
    private Map<String, SoftReference<Bitmap>> mMap = null;

    private static ImageSoftReference mSoftReference;

    private ImageSoftReference() {
        mMap = new HashMap<String, SoftReference<Bitmap>>();
    }

    public static ImageSoftReference getInstance() {
        if (mSoftReference == null) {
            mSoftReference = new ImageSoftReference();
        }
        return mSoftReference;
    }

    // 将Bitmap存到軟引用中
    public void putSoftReference(String key, Bitmap value) {
        mMap.put(key, new SoftReference<Bitmap>(value));
    }

    // 從軟引用中擷取圖檔
    public Bitmap getSoftReference(String key) {
        // 得到一個"套着手機的套子"
        SoftReference<Bitmap> softReference = mMap.get(key);
        // 先驗證"裝着手機的套子還存在不"?
        if (softReference != null) {
            return softReference.get();
        }
        return null;
    }
}
           

3 磁盤緩存 工具類

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.longyue.volley;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.android.volley.BuildConfig;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;



/**
 * 磁盤緩存工具類 A simple disk LRU bitmap cache to illustrate how a disk cache would
 * be used for bitmap caching. A much more robust and efficient disk LRU cache
 * solution can be found in the ICS source code
 * (libcore/luni/src/main/java/libcore/io/DiskLruCache.java) and is preferable
 * to this simple implementation.
 */
public class DiskLruCache {
    private static final String TAG = "DiskLruCache";
    private static final String CACHE_FILENAME_PREFIX = "";
    private static final int MAX_REMOVALS = ;
    private static final int INITIAL_CAPACITY = ;
    private static final float LOAD_FACTOR = f;

    private final File mCacheDir;
    private int cacheSize = ;
    private int cacheByteSize = ;
    private final int maxCacheItemSize = ; // 64 item default
    // 預設的緩存大小
    private long maxCacheByteSize =  *  * ; // 5MB default
    private CompressFormat mCompressFormat = CompressFormat.JPEG;
    private int mCompressQuality = ;

    private final Map<String, String> mLinkedHashMap = Collections
            .synchronizedMap(new LinkedHashMap<String, String>(
                    INITIAL_CAPACITY, LOAD_FACTOR, true));

    /**
     * A filename filter to use to identify the cache filenames which have
     * CACHE_FILENAME_PREFIX prepended.
     */
    private static final FilenameFilter cacheFileFilter = new FilenameFilter() {
        @Override
        public boolean accept(File dir, String filename) {
            return filename.startsWith(CACHE_FILENAME_PREFIX);
        }
    };

    /**
     * Used to fetch an instance of DiskLruCache.
     * 
     * @param cacheDir
     *            :圖檔要儲存的目錄
     * @param maxByteSize
     *            :緩存目錄可存空間的最小值
     * @return
     */
    public static DiskLruCache openCache(File cacheDir, long maxByteSize) {
        // 如果緩存路徑不存在,就建立出來
        if (!cacheDir.exists()) {
            cacheDir.mkdir();
        }

        // Utils.getUsableSpace(cacheDir):判斷指定路徑上可用的空間大小
        if (cacheDir.isDirectory() && cacheDir.canWrite()
                && Utils.getUsableSpace(cacheDir) > maxByteSize) {
            return new DiskLruCache(cacheDir, maxByteSize);
        }

        return null;
    }

    /**
     * 磁盤緩存DiskLruCache的構造方法 Constructor that should not be called directly,
     * instead use {@link DiskLruCache#openCache(Context, File, long)} which
     * runs some extra checks before creating a DiskLruCache instance.
     * 
     * @param cacheDir
     * @param maxByteSize
     */
    private DiskLruCache(File cacheDir, long maxByteSize) {
        mCacheDir = cacheDir;
        maxCacheByteSize = maxByteSize;
    }

    /**
     * Add a bitmap to the disk cache. 把一個圖檔存到磁盤緩存中
     * 
     * @param key
     *            :bitmap對應的唯一标示 A unique identifier for the bitmap.
     * @param data
     *            :要存儲的圖檔 The bitmap to store.
     */
    public void put(String key, Bitmap data) {
        synchronized (mLinkedHashMap) {
            if (mLinkedHashMap.get(key) == null) {
                try {
                    final String file = createFilePath(mCacheDir, key);
                    if (writeBitmapToFile(data, file)) {
                        put(key, file);
                        flushCache();
                    }
                } catch (final FileNotFoundException e) {
                    Log.e(TAG, "Error in put: " + e.getMessage());
                } catch (final IOException e) {
                    Log.e(TAG, "Error in put: " + e.getMessage());
                }
            }
        }
    }

    private void put(String key, String file) {
        mLinkedHashMap.put(key, file);
        cacheSize = mLinkedHashMap.size();
        cacheByteSize += new File(file).length();
    }

    /**
     * 清空磁盤中的緩存.如果磁盤緩存中緩存的檔案容量超過了指定的緩存總大小,就清除最早的那個bitmap. Flush the cache,
     * removing oldest entries if the total size is over the specified cache
     * size. Note that this isn't keeping track of stale files in the cache
     * directory that aren't in the HashMap. If the images and keys in the disk
     * cache change often then they probably won't ever be removed.
     */
    private void flushCache() {
        Entry<String, String> eldestEntry;
        File eldestFile;
        long eldestFileSize;
        int count = ;

        while (count < MAX_REMOVALS
                && (cacheSize > maxCacheItemSize || cacheByteSize > maxCacheByteSize)) {
            eldestEntry = mLinkedHashMap.entrySet().iterator().next();
            eldestFile = new File(eldestEntry.getValue());
            eldestFileSize = eldestFile.length();
            mLinkedHashMap.remove(eldestEntry.getKey());
            eldestFile.delete();
            cacheSize = mLinkedHashMap.size();
            cacheByteSize -= eldestFileSize;
            count++;
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "flushCache - Removed cache file, " + eldestFile
                        + ", " + eldestFileSize);
            }
        }
    }

    /**
     * Get an image from the disk cache. 從磁盤緩存中取出key對應的圖檔
     * 
     * @param key
     *            The unique identifier for the bitmap
     * @return The bitmap or null if not found
     */
    public Bitmap get(String key) {
        synchronized (mLinkedHashMap) {
            final String file = mLinkedHashMap.get(key);
            if (file != null) {
                if (BuildConfig.DEBUG) {
                    Log.d(TAG, "Disk cache hit");
                }
                return BitmapFactory.decodeFile(file);
            } else {
                final String existingFile = createFilePath(mCacheDir, key);
                if (new File(existingFile).exists()) {
                    put(key, existingFile);
                    if (BuildConfig.DEBUG) {
                        Log.d(TAG, "Disk cache hit (existing file)");
                    }
                    return BitmapFactory.decodeFile(existingFile);
                }
            }
            return null;
        }
    }

    /**
     * Checks if a specific key exist in the cache. 判斷key對應的圖檔是否存在
     * 
     * @param key
     *            The unique identifier for the bitmap
     * @return true if found, false otherwise
     */
    public boolean containsKey(String key) {
        // See if the key is in our HashMap
        if (mLinkedHashMap.containsKey(key)) {
            return true;
        }

        // Now check if there's an actual file that exists based on the key
        final String existingFile = createFilePath(mCacheDir, key);
        if (new File(existingFile).exists()) {
            // File found, add it to the HashMap for future use
            put(key, existingFile);
            return true;
        }
        return false;
    }

    /**
     * 清除磁盤緩存中所有的bitmap Removes all disk cache entries from this instance cache
     * dir
     */
    public void clearCache() {
        DiskLruCache.clearCache(mCacheDir);
    }

    /**
     * Removes all disk cache entries from the application cache directory in
     * the uniqueName sub-directory. 清除某個key對應的圖檔
     * 
     * @param context
     *            The context to use
     * @param uniqueName
     *            A unique cache directory name to append to the app cache
     *            directory
     */
    public static void clearCache(Context context, String uniqueName) {
        File cacheDir = getDiskCacheDir(context, uniqueName);
        clearCache(cacheDir);
    }

    /**
     * 清除某個檔案下面的緩存内容(圖檔) Removes all disk cache entries from the given
     * directory. This should not be called directly, call
     * {@link DiskLruCache#clearCache(Context, String)} or
     * {@link DiskLruCache#clearCache()} instead.
     * 
     * @param cacheDir
     *            The directory to remove the cache files from
     */
    private static void clearCache(File cacheDir) {
        final File[] files = cacheDir.listFiles(cacheFileFilter);
        for (int i = ; i < files.length; i++) {
            files[i].delete();
        }
    }

    /**
     * Get a usable cache directory (external if available, internal otherwise).
     * 得到磁盤緩存路徑
     * 
     * @param context
     *            The context to use
     * @param uniqueName
     *            A unique directory name to append to the cache dir
     * @return The cache dir
     */
    public static File getDiskCacheDir(Context context, String uniqueName) {

        // Check if media is mounted or storage is built-in, if so, try and use
        // external cache dir
        // otherwise use internal cache dir
        final String cachePath = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
                || !Utils.isExternalStorageRemovable() ? Utils
                .getExternalCacheDir(context).getPath() : context.getCacheDir()
                .getPath();

        return new File(cachePath + File.separator + uniqueName);
    }

    /**
     * 建立磁盤緩存到的檔案 Creates a constant cache file path given a target cache
     * directory and an image key. 建立一個緩存路徑
     * 
     * @param cacheDir
     * @param key
     * @return
     */
    public static String createFilePath(File cacheDir, String key) {
        try {
            // Use URLEncoder to ensure we have a valid filename, a tad hacky
            // but it will do for
            // this example
            return cacheDir.getAbsolutePath() + File.separator
                    + CACHE_FILENAME_PREFIX
                    + URLEncoder.encode(key.replace("*", ""), "UTF-8");
        } catch (final UnsupportedEncodingException e) {
            Log.e(TAG, "createFilePath - " + e);
        }

        return null;
    }

    /**
     * Create a constant cache file path using the current cache directory and
     * an image key.
     * 
     * @param key
     * @return
     */
    public String createFilePath(String key) {
        return createFilePath(mCacheDir, key);
    }

    /**
     * 設定圖檔壓縮的格式和品質 Sets the target compression format and quality for images
     * written to the disk cache.
     * 
     * @param compressFormat
     * @param quality
     */
    public void setCompressParams(CompressFormat compressFormat, int quality) {
        mCompressFormat = compressFormat;
        mCompressQuality = quality;
    }

    /**
     * 把圖檔存到某個指定的檔案下面 Writes a bitmap to a file. Call
     * {@link DiskLruCache#setCompressParams(CompressFormat, int)} first to set
     * the target bitmap compression and format. 将圖檔存到某個路徑下,并對圖檔進行了壓縮處理.
     * 
     * @param bitmap
     * @param file
     * @return
     */
    private boolean writeBitmapToFile(Bitmap bitmap, String file)
            throws IOException, FileNotFoundException {

        OutputStream out = null;
        try {
            out = new BufferedOutputStream(new FileOutputStream(file),
                    Utils.IO_BUFFER_SIZE);
            // mCompressFormat:圖檔壓縮儲存的格式-->jpeg;
            // mCompressQuality:壓縮的品質.
            return bitmap.compress(mCompressFormat, mCompressQuality, out);
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }
}
           

4兩個工具類和常量

//常量類
package com.longyue.volley;

import java.io.File;

import android.os.Environment;

public class Constant {
    // 磁盤緩存路徑
    public static String cachepath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "緩存練習";
    public static long MAXBYTESIZE =* * ;
}


//utils工具類
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.longyue.volley;

import java.io.File;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;

/**
 * Class containing some static utility methods.
 */
public class Utils {
    public static final int IO_BUFFER_SIZE =  * ;

    private Utils() {
    };

    /**
     * Workaround for bug pre-Froyo, see here for more info:
     * http://android-developers.blogspot.com/2011/09/androids-http-clients.html
     */
    public static void disableConnectionReuseIfNecessary() {
        // HTTP connection reuse which was buggy pre-froyo
        if (hasHttpConnectionBug()) {
            System.setProperty("http.keepAlive", "false");
        }
    }

    /**
     * Get the size in bytes of a bitmap.
     * 
     * @param bitmap
     * @return size in bytes
     */
    @SuppressLint("NewApi")
    public static int getBitmapSize(Bitmap bitmap) {
        // 判斷sdk版本是否大于蜂巢(API 12)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
            return bitmap.getByteCount();
        }
        // Pre HC-MR1
        return bitmap.getRowBytes() * bitmap.getHeight();
    }

    /**
     * Check if external storage is built-in or removable.
     *
     * @return True if external storage is removable (like an SD card), false
     *         otherwise.
     */
    @SuppressLint("NewApi")
    public static boolean isExternalStorageRemovable() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            return Environment.isExternalStorageRemovable();
        }
        return true;
    }

    /**
     * Get the external app cache directory.
     *
     * @param context
     *            The context to use
     * @return The external cache dir
     */
    @SuppressLint("NewApi")
    public static File getExternalCacheDir(Context context) {
        if (hasExternalCacheDir()) {
            return context.getExternalCacheDir();
        }

        // Before Froyo we need to construct the external cache dir ourselves
        final String cacheDir = "/Android/data/" + context.getPackageName()
                + "/cache/";
        return new File(Environment.getExternalStorageDirectory().getPath()
                + cacheDir);
    }

    /**
     * Check how much usable space is available at a given path. 計算指定目錄可用空間有多大
     * 
     * @param path
     *            The path to check
     * @return The space available in bytes
     */
    @SuppressWarnings("deprecation")
    @SuppressLint("NewApi")
    public static long getUsableSpace(File path) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            return path.getUsableSpace();
        }
        final StatFs stats = new StatFs(path.getPath());
        return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
    }

    /**
     * Get the memory class of this device (approx. per-app memory limit)
     *
     * @param context
     * @return
     */
    public static int getMemoryClass(Context context) {
        return ((ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
    }

    /**
     * Check if OS version has a http URLConnection bug. See here for more
     * information:
     * http://android-developers.blogspot.com/2011/09/androids-http-clients.html
     *
     * @return
     */
    public static boolean hasHttpConnectionBug() {
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO;
    }

    /**
     * Check if OS version has built-in external cache dir method.
     *
     * @return
     */
    public static boolean hasExternalCacheDir() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
    }

    /**
     * Check if ActionBar is available.
     *
     * @return
     */
    public static boolean hasActionBar() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
    }
}
           

第三步 二次封裝Volley

1:接口回調監聽

package com.longyue.volley;

import com.android.volley.Response;
import com.android.volley.VolleyError;


/**
 *  抽象出 成功的監聽和失敗的監聽
 *  用來回調資訊
 * @author yuan
 *
 * @param <T>
 */

public abstract class VolleyHandler<T> {


    public Response.Listener<T> reqLis;
    public Response.ErrorListener reqErr;

    public VolleyHandler() {
        // 初始化 變量
        reqLis = new reqListener();
        reqErr = new reqErrorListener();
    }

    public abstract void reqSuccess(T response);

    public abstract void reqError(String error);

    /**
     * 成功後的監聽
     * 
     * @author yuan
     *
     */
    public class reqListener implements Response.Listener<T> {

        @Override
        public void onResponse(T response) {
            // 使用抽象函數 設定 回調函數 reqSuccess
            reqSuccess(response);
        }
    }

    /**
     * 失敗後的監聽
     * 
     * @author yuan
     *
     */
    public class reqErrorListener implements Response.ErrorListener {

        @Override
        public void onErrorResponse(VolleyError error) {
            // 設定回調函數 使用 抽象方法 ReqError
            reqError(error.getMessage());
        }
    }
}
           

2 封裝 檔案上傳請求隊列

package com.longyue.volley;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;

public class MultipartRequest extends Request<String> {

    private MultipartEntity entity = new MultipartEntity();

    private final Response.Listener<String> mListener;

    private List<File> mFileParts;
    private String mFilePartName;
    private Map<String, String> mParams;
    /**
     * 單個檔案
     * @param url
     * @param errorListener
     * @param listener
     * @param filePartName
     * @param file
     * @param params
     */
    public MultipartRequest(String url, Response.ErrorListener errorListener,
            Response.Listener<String> listener, String filePartName, File file,
            Map<String, String> params) {
        super(Method.POST, url, errorListener);

        mFileParts = new ArrayList<File>();
        if (file != null) {
            mFileParts.add(file);
        }
        mFilePartName = filePartName;
        mListener = listener;
        mParams = params;
        buildMultipartEntity();
    }
    /**
     * 多個檔案,對應一個key
     * @param url
     * @param errorListener
     * @param listener
     * @param filePartName
     * @param files
     * @param params
     */
    public MultipartRequest(String url, Response.ErrorListener errorListener,
            Response.Listener<String> listener, String filePartName,
            List<File> files, Map<String, String> params) {
        super(Method.POST, url, errorListener);
        mFilePartName = filePartName;
        mListener = listener;
        mFileParts = files;
        mParams = params;
        buildMultipartEntity();
    }

    private void buildMultipartEntity() {
        if (mFileParts != null && mFileParts.size() > ) {
            for (File file : mFileParts) {
                entity.addPart(mFilePartName, new FileBody(file));
            }
        }

        try {
            if (mParams != null && mParams.size() > ) {
                for (Map.Entry<String, String> entry : mParams.entrySet()) {
                    entity.addPart(
                            entry.getKey(),
                            new StringBody(entry.getValue(), Charset
                                    .forName("UTF-8")));
                }
            }
        } catch (UnsupportedEncodingException e) {
            VolleyLog.e("UnsupportedEncodingException");
        }
    }

    @Override
    public String getBodyContentType() {
        return entity.getContentType().getValue();
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            entity.writeTo(bos);
        } catch (IOException e) {
            VolleyLog.e("IOException writing to ByteArrayOutputStream");
        }
        return bos.toByteArray();
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        if (VolleyLog.DEBUG) {
            if (response.headers != null) {
                for (Map.Entry<String, String> entry : response.headers
                        .entrySet()) {
                    VolleyLog.d(entry.getKey() + "=" + entry.getValue());
                }
            }
        }

        String parsed;
        try {
            parsed = new String(response.data,HttpHeaderParser.parseCharset(response.headers));
        } catch (UnsupportedEncodingException e) {
            parsed = new String(response.data);
        }
        return Response.success(parsed,
                HttpHeaderParser.parseCacheHeaders(response));
    }


    /*
     * (non-Javadoc)
     * 
     * @see com.android.volley.Request#getHeaders()
     */
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        VolleyLog.d("getHeaders");
        Map<String, String> headers = super.getHeaders();

        if (headers == null || headers.equals(Collections.emptyMap())) {
            headers = new HashMap<String, String>();
        }
        return headers;
    }

    @Override
    protected void deliverResponse(String response) {
        mListener.onResponse(response);
    }
}
           

3 請求方法封裝

package com.longyue.volley;

import java.io.File;
import java.util.Map;

import org.json.JSONObject;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;

import com.android.volley.AuthFailureError;
import com.android.volley.Request.Method;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import com.longyue.customvolley2.VolleyApplication;


/**
 * @author xuenan
 *
 */
public class VolleyHttpRequest{


    /** 1.
     * StringRequest GET方式 
     * @param url 位址
     * @param volleyRequest 回調函數
     */
    public static void String_request(String url,VolleyHandler<String> volleyRequest){
        Volley_StringRequest(Method.GET, url,null, volleyRequest);
    }

    /** 1.
     * StringRequset POST方式
     * @param url 位址
     * @param map 參數
     * @param volleyRequest 回調函數
     */
    public static void String_request(String url,final Map<String,String> map,VolleyHandler<String> volleyRequest){
        Volley_StringRequest(Method.POST,url,map,volleyRequest);
    }
    /**Volley_UploadImage_Request POST方式
     * @param url 位址
     * @param params 請求參數
     * @param volleyRequest 回調函數
     * @param fileName 檔案名  
     * @param file 要上傳的檔案
     */
    public static void File_Upload_request(String url,final Map<String,String> params,VolleyHandler<String> volleyRequest,String fileName,File file){
        Volley_UploadImage_Request(url, params, volleyRequest, fileName, file);
    }
    /**1.
     * 封裝 StringRequest 資料請求
     * @param method 方式
     * @param url 位址
     * @param params 參數
     * @param volleyRequest 回調對象
     */
    private static void Volley_StringRequest(int method,String url,final Map<String,String> params,VolleyHandler<String> volleyRequest){
        StringRequest stringrequest=new StringRequest(method, url,volleyRequest.reqLis,volleyRequest.reqErr){
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                return params;
            }
        };
        stringrequest.setTag("stringrequest");
        VolleyApplication.getQueue().add(stringrequest);
    }

    /**2封裝MultipartRequest 資料請求  上傳圖檔
     * @param url
     * @param params 參數
     * @param volleyRequest 回調函數
     * @param fileName 檔案名
     * @param file 檔案
     */
    private static void Volley_UploadImage_Request(String url,final Map<String,String> params,VolleyHandler<String> volleyRequest,String fileName,File file){
        MultipartRequest imageRequest=new MultipartRequest(url, volleyRequest.reqErr,volleyRequest.reqLis,fileName, file, params);
        imageRequest.setTag("imageRequest");
        VolleyApplication.getQueue().add(imageRequest);
    }
    /**2.
     * JsonObjectRequest GET 請求
     * @param url 請求位址
     * @param volleyRequest  回調函數對象
     */
    public static void JsonObject_Request(String url,VolleyHandler<JSONObject> volleyRequest){
         Volley_JsonObjectRequest(Method.GET,url,null,volleyRequest);
    }

    /**2
     * JsonObjectRequest POST 請求
     * @param url 請求位址
     * @param jsonObject 請求參數
     * @param volleyRequest 回調函數對象
     */
    public static void JsonObject_Request(String url,JSONObject jsonObject,VolleyHandler<JSONObject> volleyRequest){
        Volley_JsonObjectRequest(Method.POST,url,jsonObject,volleyRequest);
    }

    /**2.
     * 封裝 JsonObjectRequest 請求方法
     * @param method 方式
     * @param url 位址
     * @param jsonObject  參數
     * @param volleyRequest  回調函數對象
     */
    private static void Volley_JsonObjectRequest(int method,String url,JSONObject jsonObject,VolleyHandler<JSONObject> volleyRequest){
         JsonObjectRequest jsonObjectRequest=new JsonObjectRequest(method,url,jsonObject,volleyRequest.reqLis,volleyRequest.reqErr);
         jsonObjectRequest.setTag("jsonObjectRequest");
         VolleyApplication.getQueue().add(jsonObjectRequest);
    }


    /**3.
     * ImageRequest 預設大小 原圖不變
     * @param url 位址
     * @param volleyRequest 回調函數
     */
    public static void Image_request(String url,VolleyHandler<Bitmap> volleyRequest){
        Volley_ImageRequest(url, , , volleyRequest);
    }

    /**3.
     * ImageRequest 自定義的縮放
     * @param url 位址
     * @param maxWidth 最大寬度
     * @param maxHeight 最大高度
     * @param volleyRequest 回調函數
     */
    public static void Image_request(String url,int maxWidth,int maxHeight,VolleyHandler<Bitmap> volleyRequest){
        Volley_ImageRequest(url, maxWidth, maxHeight, volleyRequest);
    }


    /**3.
     * 封裝 ImageRequest 請求方法
     * @param url 位址
     * @param maxWidth 最大寬度
     * @param maxHeight 最大高度
     * @param volleyRequest 回調函數對象
     */
    private static void Volley_ImageRequest(String url,int maxWidth,int maxHeight,VolleyHandler<Bitmap> volleyRequest){
        ImageRequest imageRequest=new ImageRequest(url,volleyRequest.reqLis, maxWidth, maxHeight,Config.RGB_565,volleyRequest.reqErr);
        imageRequest.setTag("imageRequest");
        VolleyApplication.getQueue().add(imageRequest);
    }


    /**
     * 4.
     * 自定義圖檔的寬度值
     * @param url
     * @param imageListener
     * @param maxWidth
     * @param maxHidth
     */
    public static void Image_Loader(String url,ImageListener imageListener,int maxWidth,int maxHidth){
        Volley_ImageLoader(url, imageListener, maxWidth, maxHidth);
    }


    /** 4.
     * 預設值,原始比例
     * @param url 位址
     * @param imageListener 圖檔監聽
     */
    public static void Image_Loader(String url,ImageListener imageListener){
        Volley_ImageLoader(url,imageListener,,);
    }


    /** 4.
     * 封裝 ImageLoader 方法
     * @param url 位址
     * @param imageListener 圖檔監聽
     * @param maxWidth 
     * @param maxHidth
     */
    private static void Volley_ImageLoader(String url,ImageListener imageListener,int maxWidth,int maxHidth){
                // 設定 圖檔緩存 :展現 imageLoader的優勢
                // 使用 LruBitmap + ImageCache 實作
                // 執行個體化對象
        ImageLoader imageLoader = new ImageLoader(VolleyApplication.getQueue(),
                        VolleyBitmapCache.getInstance());
                // 加載圖檔 圖檔監聽 (預設圖檔,錯誤圖檔) 和 imageView
        imageLoader.get(url, imageListener,maxWidth,maxHidth);
    }
}
           

完成了這些 ,就可以愉快的享受程式設計的魅力了

Demo下載下傳

繼續閱讀