編輯:關於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接下來就是Volley雖然給我們提供了很多不同的Request(JsonObjectRequest,JsonArrayRequest,StringRequest,ImageRequest),但是還是滿足不了我們實戰中的需求,我們實戰開發中經常用到的是xml格式,Gson解析。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); } } }
接下來我們來看看,如何自定義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); } }
public class GsonRequest接下只差最後一步了就是封裝它的錯誤處理,使用過volley的都知道,volley的監聽錯誤提示都是NoConnectionError。。。等等,這類的錯誤提示,顯然這不是我們想給用戶呈現的錯誤提示,因為就算提示了用戶也不明白什麼意思,所以我們還要封裝一下,能讓用戶看的更清楚的理解這些錯誤提示。ym—— Android網絡框架Volley(體驗篇)我們講過每個請求都需要設置一個失敗的監聽: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); } }
// 共用失敗回調 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 HashMapresult = new Gson().fromJson( new String(response.data), new TypeToken
接下來,數據請求這一塊已經說完了,我們來說下圖片這一塊,我個人喜歡使用universal-image-loader而不是volley自己提供的(個人認為使用起來universal-image-loader更便捷一些)。好啦講完了,大家可以去實戰開發了~!不懂或者遇到問題的可以留言討論~!無網絡連接~! 連接服務器失敗~! 網絡異常,請稍後再試~!
1、把aar復制到項目中的 libs 裡面 2、在module 裡面的build.gradle 的根目錄添加repositories{ flatDir {
目標效果: 程序運行出現圖一walker的歡迎界面,從模糊變清晰,過了幾秒自動跳到圖二的導航界面,下邊有小圓點表示第幾個頁面,第四個導航頁面有一個Go按鈕,點擊跳轉到
1.這篇博文不算什麼知識點。使用的都是的系統中已經提供給我們的方式方法。這是最近用到了,感覺很實用,特此貢獻出來。 首先需要定義,listview中需要展示的
頭部用的是TabLayout和ViewPager實現的 底部用的是FragmentTabHost和Fragment實現的先看底部的實現:底部布局: <fram