Android網路框架Volley(實戰篇)
阿新 • • 發佈:2019-01-04
之前講了ym—— Android網路框架Volley(體驗篇),大家應該瞭解了volley的使用,接下來我們要看看如何把volley使用到實戰專案裡面,我們先考慮下一些問題:
GsonRequest(注意需要自行匯入gson.jar): [java] view plaincopyprint?
以上程式碼中引用的xml是: [html] view plaincopyprint?
從上一篇來看 mQueue 只需要一個物件即可,new RequestQueue物件對資源一種浪費,我們應該在application,以及可以把取消請求的方法也在application進行統一管理,看以下程式碼:
[java] view plaincopyprint?- package com.chronocloud.lib.base;
- import android.app.Application;
- import
- import com.android.volley.Request;
- import com.android.volley.RequestQueue;
- import com.android.volley.VolleyLog;
- import com.android.volley.toolbox.Volley;
- publicclass ApplicationController extends Application {
- /**
- * Log or request TAG
- */
- publicstaticfinal
- /**
- * Global request queue for Volley
- */
- private RequestQueue mRequestQueue;
- /**
- * A singleton instance of the application class for easy access in other
- * places
- */
- privatestatic ApplicationController sInstance;
- @Override
- public
- super.onCreate();
- // initialize the singleton
- sInstance = this;
- }
- /**
- * @return ApplicationController singleton instance
- */
- publicstaticsynchronized 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 <T> void addToRequestQueue(Request<T> 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 <T> void addToRequestQueue(Request<T> 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
- */
- publicvoid cancelPendingRequests(Object tag) {
- if (mRequestQueue != null) {
- mRequestQueue.cancelAll(tag);
- }
- }
- }
接下來我們來看看,如何自定義Request
XmlRequest:
[java] view plaincopyprint?- publicclass XMLRequest extends Request<XmlPullParser> {
- privatefinal Listener<XmlPullParser> mListener;
- public XMLRequest(int method, String url, Listener<XmlPullParser> listener,
- ErrorListener errorListener) {
- super(method, url, errorListener);
- mListener = listener;
- }
- public XMLRequest(String url, Listener<XmlPullParser> listener, ErrorListener errorListener) {
- this(Method.GET, url, listener, errorListener);
- }
- @Override
- protected Response<XmlPullParser> 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
- protectedvoid deliverResponse(XmlPullParser response) {
- mListener.onResponse(response);
- }
- }
GsonRequest(注意需要自行匯入gson.jar): [java] view plaincopyprint?
- publicclass GsonRequest<T> extends Request<T> {
- privatefinal Listener<T> mListener;
- private Gson mGson;
- private Class<T> mClass;
- public GsonRequest(int method, String url, Class<T> clazz, Listener<T> listener,
- ErrorListener errorListener) {
- super(method, url, errorListener);
- mGson = new Gson();
- mClass = clazz;
- mListener = listener;
- }
- public GsonRequest(String url, Class<T> clazz, Listener<T> listener,
- ErrorListener errorListener) {
- this(Method.GET, url, clazz, listener, errorListener);
- }
- @Override
- protected Response<T> 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
- protectedvoid deliverResponse(T response) {
- mListener.onResponse(response);
- }
- }
- // 共用失敗回撥
- privateclass StrErrListener implements ErrorListener {
- @Override
- publicvoid onErrorResponse(VolleyError arg0) {
- Toast.makeText(mContext,
- VolleyErrorHelper.getMessage(arg0, mContext),
- Toast.LENGTH_LONG).show();
- }
- }
- 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。
- publicclass VolleyErrorHelper {
- /**
- * Returns appropriate message which is to be displayed to the user against
- * the specified error object.
- *
- * @param error
- * @param context
- * @return
- */
- publicstatic String getMessage(Object error, Context context) {
- if (error instanceof TimeoutError) {
- return context.getResources().getString(
- R.string.generic_server_down);
- } elseif (isServerProblem(error)) {
- return handleServerError(error, context);
- } elseif (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
- */
- privatestaticboolean isNetworkProblem(Object error) {
- return (error instanceof NetworkError)
- || (error instanceof NoConnectionError);
- }
- /**
- * Determines whether the error is related to server
- *
- * @param error
- * @return
- */
- privatestaticboolean 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
- */
- privatestatic String handleServerError(Object err, Context context) {
- VolleyError error = (VolleyError) err;
- NetworkResponse response = error.networkResponse;
- if (response != null) {
- switch (response.statusCode) {
- case404:
- case422:
- case401:
- try {
- // server might return error like this { "error":
- // "Some error occured" }
- // Use "Gson" to parse the result
- HashMap<String, String> result = new Gson().fromJson(
- new String(response.data),
- new TypeToken<Map<String, String>>() {
- }.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是: [html] view plaincopyprint?
- <stringname="no_internet">無網路連線~!</string>
- <stringname="generic_server_down">連線伺服器失敗~!</string>
- <stringname="generic_error">網路異常,請稍後再試~!</string>