Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> ym—— Android網絡框架Volley(實戰篇)

ym—— Android網絡框架Volley(實戰篇)

編輯:關於Android編程

之前講了ym—— Android網絡框架Volley(體驗篇),大家應該了解了volley的使用,接下來我們要看看如何把volley使用到實戰項目裡面,我們先考慮下一些問題:

從上一篇來看 mQueue 只需要一個對象即可,new RequestQueue對象對資源一種浪費,我們應該在application,以及可以把取消請求的方法也在application進行統一管理,看以下代碼:

package com.chronocloud.lib.base;

import android.app.Application;
import android.text.TextUtils;

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

public class ApplicationController extends Application {

	/**
	 * Log or request TAG
	 */
	public static final String TAG = "VolleyPatterns";

	/**
	 * Global request queue for Volley
	 */
	private RequestQueue mRequestQueue;

	/**
	 * A singleton instance of the application class for easy access in other
	 * places
	 */
	private static ApplicationController sInstance;

	@Override
	public void onCreate() {
		super.onCreate();

		// initialize the singleton
		sInstance = this;
	}

	/**
	 * @return ApplicationController singleton instance
	 */
	public static synchronized ApplicationController getInstance() {
		return sInstance;
	}

	/**
	 * @return The Volley Request queue, the queue will be created if it is null
	 */
	public RequestQueue getRequestQueue() {
		// lazy initialize the request queue, the queue instance will be
		// created when it is accessed for the first time
		if (mRequestQueue == null) {
			// 1
			// 2
			synchronized (ApplicationController.class) {
				if (mRequestQueue == null) {
					mRequestQueue = Volley
							.newRequestQueue(getApplicationContext());
				}
			}
		}
		return mRequestQueue;
	}

	/**
	 * Adds the specified request to the global queue, if tag is specified then
	 * it is used else Default TAG is used.
	 * 
	 * @param req
	 * @param tag
	 */
	public  void addToRequestQueue(Request req, String tag) {
		// set the default tag if tag is empty
		req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);

		VolleyLog.d("Adding request to queue: %s", req.getUrl());

		getRequestQueue().add(req);
	}

	/**
	 * Adds the specified request to the global queue using the Default TAG.
	 * 
	 * @param req
	 * @param tag
	 */
	public  void addToRequestQueue(Request req) {
		// set the default tag if tag is empty
		req.setTag(TAG);

		getRequestQueue().add(req);
	}

	/**
	 * Cancels all pending requests by the specified TAG, it is important to
	 * specify a TAG so that the pending/ongoing requests can be cancelled.
	 * 
	 * @param tag
	 */
	public void cancelPendingRequests(Object tag) {
		if (mRequestQueue != null) {
			mRequestQueue.cancelAll(tag);
		}
	}
}
接下來就是Volley雖然給我們提供了很多不同的Request(JsonObjectRequest,JsonArrayRequest,StringRequest,ImageRequest),但是還是滿足不了我們實戰中的需求,我們實戰開發中經常用到的是xml格式,Gson解析。

接下來我們來看看,如何自定義Request

XmlRequest:

public class XMLRequest extends Request {

	private final Listener mListener;

	public XMLRequest(int method, String url, Listener listener,
			ErrorListener errorListener) {
		super(method, url, errorListener);
		mListener = listener;
	}

	public XMLRequest(String url, Listener listener, ErrorListener errorListener) {
		this(Method.GET, url, listener, errorListener);
	}

	@Override
	protected Response parseNetworkResponse(NetworkResponse response) {
		try {
			String xmlString = new String(response.data,
					HttpHeaderParser.parseCharset(response.headers));
			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			XmlPullParser xmlPullParser = factory.newPullParser();
			xmlPullParser.setInput(new StringReader(xmlString));
			return Response.success(xmlPullParser, HttpHeaderParser.parseCacheHeaders(response));
		} catch (UnsupportedEncodingException e) {
			return Response.error(new ParseError(e));
		} catch (XmlPullParserException e) {
			return Response.error(new ParseError(e));
		}
	}

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

}

GsonRequest(注意需要自行導入gson.jar):

public class GsonRequest extends Request {

	private final Listener mListener;

	private Gson mGson;

	private Class mClass;

	public GsonRequest(int method, String url, Class clazz, Listener listener,
			ErrorListener errorListener) {
		super(method, url, errorListener);
		mGson = new Gson();
		mClass = clazz;
		mListener = listener;
	}

	public GsonRequest(String url, Class clazz, Listener listener,
			ErrorListener errorListener) {
		this(Method.GET, url, clazz, listener, errorListener);
	}

	@Override
	protected Response parseNetworkResponse(NetworkResponse response) {
		try {
			String jsonString = new String(response.data,
					HttpHeaderParser.parseCharset(response.headers));
			return Response.success(mGson.fromJson(jsonString, mClass),
					HttpHeaderParser.parseCacheHeaders(response));
		} catch (UnsupportedEncodingException e) {
			return Response.error(new ParseError(e));
		}
	}

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

}
接下只差最後一步了就是封裝它的錯誤處理,使用過volley的都知道,volley的監聽錯誤提示都是NoConnectionError。。。等等,這類的錯誤提示,顯然這不是我們想給用戶呈現的錯誤提示,因為就算提示了用戶也不明白什麼意思,所以我們還要封裝一下,能讓用戶看的更清楚的理解這些錯誤提示。ym—— Android網絡框架Volley(體驗篇)我們講過每個請求都需要設置一個失敗的監聽:

	// 共用失敗回調
	private class StrErrListener implements ErrorListener {

		@Override
		public void onErrorResponse(VolleyError arg0) {
			Toast.makeText(mContext,
					VolleyErrorHelper.getMessage(arg0, mContext),
					Toast.LENGTH_LONG).show();
		}

	}
以上代碼有個VolleyError對象,我們可以從這個對象上下手:

package com.example.volley;

import java.util.HashMap;
import java.util.Map;

import android.content.Context;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkError;
import com.android.volley.NetworkResponse;
import com.android.volley.NoConnectionError;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
//正如前面代碼看到的,在創建一個請求時,需要添加一個錯誤監聽onErrorResponse。如果請求發生異常,會返回一個VolleyError實例。
//以下是Volley的異常列表:
//AuthFailureError:如果在做一個HTTP的身份驗證,可能會發生這個錯誤。
//NetworkError:Socket關閉,服務器宕機,DNS錯誤都會產生這個錯誤。
//NoConnectionError:和NetworkError類似,這個是客戶端沒有網絡連接。
//ParseError:在使用JsonObjectRequest或JsonArrayRequest時,如果接收到的JSON是畸形,會產生異常。
//SERVERERROR:服務器的響應的一個錯誤,最有可能的4xx或5xx HTTP狀態代碼。
//TimeoutError:Socket超時,服務器太忙或網絡延遲會產生這個異常。默認情況下,Volley的超時時間為2.5秒。如果得到這個錯誤可以使用RetryPolicy。

public class VolleyErrorHelper {

	/**
	 * Returns appropriate message which is to be displayed to the user against
	 * the specified error object.
	 * 
	 * @param error
	 * @param context
	 * @return
	 */
	public static String getMessage(Object error, Context context) {
		if (error instanceof TimeoutError) {
			return context.getResources().getString(
					R.string.generic_server_down);
		} else if (isServerProblem(error)) {
			return handleServerError(error, context);
		} else if (isNetworkProblem(error)) {
			return context.getResources().getString(R.string.no_internet);
		}
		return context.getResources().getString(R.string.generic_error);
	}

	/**
	 * Determines whether the error is related to network
	 * 
	 * @param error
	 * @return
	 */
	private static boolean isNetworkProblem(Object error) {
		return (error instanceof NetworkError)
				|| (error instanceof NoConnectionError);
	}

	/**
	 * Determines whether the error is related to server
	 * 
	 * @param error
	 * @return
	 */
	private static boolean isServerProblem(Object error) {
		return (error instanceof ServerError)
				|| (error instanceof AuthFailureError);
	}

	/**
	 * Handles the server error, tries to determine whether to show a stock
	 * message or to show a message retrieved from the server.
	 * 
	 * @param err
	 * @param context
	 * @return
	 */
	private static String handleServerError(Object err, Context context) {
		VolleyError error = (VolleyError) err;

		NetworkResponse response = error.networkResponse;

		if (response != null) {
			switch (response.statusCode) {
			case 404:
			case 422:
			case 401:
				try {
					// server might return error like this { "error":
					// "Some error occured" }
					// Use "Gson" to parse the result
					HashMap result = new Gson().fromJson(
							new String(response.data),
							new TypeToken>() {
							}.getType());

					if (result != null && result.containsKey("error")) {
						return result.get("error");
					}

				} catch (Exception e) {
					e.printStackTrace();
				}
				// invalid request
				return error.getMessage();

			default:
				return context.getResources().getString(
						R.string.generic_server_down);
			}
		}
		return context.getResources().getString(R.string.generic_error);
	}
}

以上代碼中引用的xml是:

	無網絡連接~!
	連接服務器失敗~!
	網絡異常,請稍後再試~!
接下來,數據請求這一塊已經說完了,我們來說下圖片這一塊,我個人喜歡使用universal-image-loader而不是volley自己提供的(個人認為使用起來universal-image-loader更便捷一些)。好啦講完了,大家可以去實戰開發了~!不懂或者遇到問題的可以留言討論~!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved