編輯:關於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); } }
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
HashMap result = new Gson().fromJson(
new String(response.data),
new TypeToken 接下來,數據請求這一塊已經說完了,我們來說下圖片這一塊,我個人喜歡使用universal-image-loader而不是volley自己提供的(個人認為使用起來universal-image-loader更便捷一些)。好啦講完了,大家可以去實戰開發了~!不懂或者遇到問題的可以留言討論~!無網絡連接~! 連接服務器失敗~! 網絡異常,請稍後再試~!
Android Studio添加aar
1、把aar復制到項目中的 libs 裡面 2、在module 裡面的build.gradle 的根目錄添加repositories{ flatDir {
Android小程序-Walker注冊頁面(四)
目標效果: 程序運行出現圖一walker的歡迎界面,從模糊變清晰,過了幾秒自動跳到圖二的導航界面,下邊有小圓點表示第幾個頁面,第四個導航頁面有一個Go按鈕,點擊跳轉到
android listView的item 顯示多種不同的布局
1.這篇博文不算什麼知識點。使用的都是的系統中已經提供給我們的方式方法。這是最近用到了,感覺很實用,特此貢獻出來。 首先需要定義,listview中需要展示的
仿今日頭條的(一)
頭部用的是TabLayout和ViewPager實現的 底部用的是FragmentTabHost和Fragment實現的先看底部的實現:底部布局: <fram