volley(一)基本特點
Google I/O 2013上,Volley發佈。它是Android平臺上的網絡通信庫,能使網絡通信更快,更簡單,更健壯。
提供功能:
- JSON,圖像等的異步下載;
- 網絡請求的排序(scheduling)
- 網絡請求的優先級處理
- 緩存
- 多級別取消請求
- 和Activity和生命週期的聯動(Activity結束時同時取消所有網絡請求)
volley適合:數據量不大,通信頻繁的網絡操作,對大數據量(下載上傳文件),會很糟糕。
用戶登錄流程詳解 +volley(StringRequest)
在實習期間由於要求使用volley,所以第一次開始接觸volley,從一開始的迷茫陌生,到瘋狂的查找各種資料,通過在項目中用到的實際問題,我想做一些總結,所以寫了這篇文章。下面我將介紹我理解的用戶登錄的一套詳細流程,涉及到volley請求以及json數據的解析。
登錄流程的總結:首先通過EditText獲取到用戶名和密碼,然後再執行登錄請求 LoginToServer()裏面發送用戶名和密碼,服務器返回給我json數據(如果用到Oauth 認證這裏返回的json數據就應該是Token的一套東西,如果只是簡單的登錄,可以和服務器約定返回的內容,提取出對應的內容,包裝起來做判斷反饋給用戶登錄是否成功),我需要把這些json數據解析出來,然後再反饋給用戶“登錄成功”或者“登錄失敗”。
LoginActivity.class這裏是在登錄界面調用到 LoginToServer()這個方法,這裏我把 User_Local.class 裏面寫了基本的set,get方法,然後是裏面是全局(public static)的方法。
public void onClick(View v) {
switch (v.getId()) {
case R.id.login_button:
if (checkEdit()) {
//這裏記得一定要先get獲得數據
User_Local.setUsername(username.getText().toString());
User_Local.setPassword(password.getText().toString());
// LoginToServer();
new LoginSupport(LoginActivity.this).LoginToServer();
}
break;
這裏是User_Local.class ,首先這裏爲什麼要寫成public static,寫成這種是說這是全局變量。全局的引用方法就是類名直接引用,不用再new 一個對象。比如這裏就是引用直接就是上述的 User_Local.setUsername(username.getText().toString());。什麼時候用全局的,什麼時候不用,這個大家可以百度一下。比如在接受服務器傳過來的json數據我要再建一套類去匹配解析,這個時候就不要用全局的。
public class User_Local {
public static String username = " " ;//用戶名
public static String password =" ";//密碼
public static String getUsername() {
return username;
}
public static void setUsername(String username) {
User_Local.username = username;
}
public static String getPassword() {
return password;
}
public static void setPassword(String password) {
User_Local.password = password;
}
LoginSupport.class 這個類裏面我寫了volley的登錄請求,還有服務器返回的json數據解析(這裏使用的是Gson來解析json數據),還有反饋給用戶登錄成功失敗與否
volley請求簡單說就三步:1.添加url地址。2.new 一個請求(請求裏面有成功和失敗的接口)3.添加請求到請求隊列裏面去
這裏我只用了volley 裏面的StringRequest這個請求,這個請求向服務器發送的應該是字符串吧,我理解的是這樣的。然後至於volley的其他請求大家可以參考其他的博客和專業資料。
public void LoginToServer( ) {
String url = "http://XXXXX";//1.這裏就是你要向服務器發送請求的地址
StringRequest loginRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {//2.new 一個請求
@Override
public void onResponse(String s) {//這裏是返回正確反饋的接口(只要請求成功反饋的數據都這這裏)
//數據處理反饋(可以這這裏處理服務器返回的數據)
DealResponseFromServer(s);//json數據的解析和用戶反饋
Log.i("TAG",s);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
//volley 有專門處理error的庫,下面就是調用了其中的一些,可以方便調試的時候查找到錯誤
Log.d(TAG, "Volley returned error________________:" + volleyError);
Class klass = volleyError.getClass();
if(klass == com.android.volley.AuthFailureError.class) {
Log.d(TAG,"AuthFailureError");
Toast.makeText(context,"未授權,請重新登錄",Toast.LENGTH_LONG).show();
} else if(klass == com.android.volley.NetworkError.class) {
Log.d(TAG,"NetworkError");
Toast.makeText(context,"網絡連接錯誤,請重新登錄",Toast.LENGTH_LONG).show();
} else if(klass == com.android.volley.NoConnectionError.class) {
Log.d(TAG,"NoConnectionError");
} else if(klass == com.android.volley.ServerError.class) {
Log.d(TAG,"ServerError");
Toast.makeText(context,"服務器未知錯誤,請重新登錄",Toast.LENGTH_LONG).show();
} else if(klass == com.android.volley.TimeoutError.class) {
Log.d(TAG,"TimeoutError");
Toast.makeText(context,"連接超時,請重新登錄",Toast.LENGTH_LONG).show();
} else if(klass == com.android.volley.ParseError.class) {
Log.d(TAG,"ParseError");
} else if(klass == com.android.volley.VolleyError.class) {
Log.d(TAG,"General error");
}
Toast.makeText(context,"登錄失敗",Toast.LENGTH_LONG).show();
}
})
{
//這裏是添加請求頭的地方重寫了getHeaders() 方法(發送設麼請求頭要根據自己實際開發需要設定)
@Override
public Map<String, String> getHeaders() {
HashMap<String, String> header = new HashMap<String, String>();
header.put("Accept","application/json");
header.put("Content-Type","application/x-www-form-urlencoded");
return header;
}
//這裏是發送參數的地方,重寫了 getParams() 方法(傳什麼參數給服務器也是實際你自己修改)
@Override
protected Map<String, String> getParams() {
HashMap<String, String> map = new HashMap<String, String>();
//如果出現空指針異常或者是登錄失敗,先檢查這裏有木有傳進來你要發送的用戶名和密碼。
//所以在執行get數據方法之前一定要先存數據(set方法)
map.put("username", User_Local.getUsername());
map.put("password", User_Local.getPassword());
return map;
}
};
//設置超時重新請求
loginRequest.setRetryPolicy(new DefaultRetryPolicy(5000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
//設置標籤,方便在stop(){}裏面取消對應的volley 請求
loginRequest.setTag("POST");
//3.把請求添加到全局請求隊列裏面
MyApplication.getHttpQueue().add(loginRequest);
}
//建立一個全局請求隊列
public class MyApplication extends Application {
public static RequestQueue requestQueue;//
@Override
public void onCreate() {
super.onCreate();
requestQueue = Volley.newRequestQueue(getApplicationContext());
}
public static RequestQueue getHttpQueue(){
return requestQueue;
}
}
Gson解析json數據的精華就是:
gson.fromJson(就是把json數據解析成普通數據)和gson.toJson(把普通數據轉化成json類型的數據格式)
要注意的是,這裏解析到服務器的數據必須有一套模型和服務器裏面的各種數據類型匹配,也就是你需要根據傳過來的json數據建一個類來把解析的數據保存起來。
//解析服務器返回的json字符串反饋給用戶
public void DealResponseFromServer(String s) {
Gson gson = new Gson();//第一步,實例化
User_Service user_service = gson.fromJson(s, User_Service.class);//第二步,解析數據
if (s!=null) {//這裏的s就是上面成功回調接口裏面的參數
//這裏我保存了從服務器返回的token的信息,至於token就涉及到oauth2.0的內容了,不懂得可以百度,
//當然這裏可以保持你需要保存的服務器返回的數據
PreferenceUtils.setPrefString(context,User_Service.userKey, "access_token", user_service.getAccess_token());//保存令牌(這裏我用的是自己寫的一套SharedPreferences的工具類來保存token)
PreferenceUtils.setPrefString(context,User_Service.userKey, "refresh_token", user_service.getRefresh_token());//保存刷新令牌
Toast.makeText(context, "登錄成功", Toast.LENGTH_SHORT).show();//反饋給用戶登錄成功
}
}
這個就是用於接收服務器返回的json數據類型所建立的類,專門用於解析json數據的。這裏的變量就不用設置成全局的變量。
這裏面的關係我捋一下,1.從服務器解析的json數據保存到本地數據庫裏面2.然後本地需要調用數據的時候,再去數據庫裏面去取。
//用於接收解析服務器返回數據所給的數據
public class User_Service {
public static final String userKey = "user_service";//用於保存服務器端傳回的數據文件
private String access_token;//令牌
private String refresh_token;//刷新令牌
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getRefresh_token() {
return refresh_token;
}