沒看過上篇的,建議先看上篇,傳送門:http://blog.csdn.net/black_dreamer/article/details/53068620
響應數據的格式
服務器響應的數據,結構也大都固定,比如:
{
"result": {
"total": 0,
"data": {
"uid": 9527,
"token": "xxxxxxxxxxxxx",
"username": "xxxxx"
}
},
"status": 200
}
上面的響應裏,基本上兩個字段是不變的,result字段和status字段,result裏面的字段也相對固定,可能列表數據和單條數據會有不同。
封裝響應
請求封裝的主要內容在TPostJsonBuilder.java裏,將參數拼接轉換,而響應的封裝,主要是解析服務器返回的響應數據,解析成實體類,然後方便我們取裏面的字段。
這裏我們可以先寫一個最外層的結果類,用來接收result和status兩個字段:
TOkHttpResponse.java
public class TOkHttpResponse<T> {
@SerializedName("result")
private T result;
@SerializedName("status")
private int status;
//get and set 方法,略...
}
很簡單,裏面只有兩個成員變量,一個是泛型的result,一個是status。
然後要怎麼用到這個TOkHttpResponse呢?
答案是新建TBaseCallback類繼承自Callback:
TBaseCallback.java
public abstract class TBaseCallback<T> extends Callback<TOkHttpResponse<T>> {
public TBaseCallback() {
}
@Override
public TOkHttpResponse<T> parseNetworkResponse(Response response, int id) throws Exception {
String str = response.body().string();
TOkHttpResponse<T> res = new Gson().fromJson(str,new TypeToken<TOkHttpResponse<T>>(){}.getType()) ;
return res;
}
@Override
public void onError(Call call, Exception e, int id) {
Log.e("test","e: " + e.toString()) ;
}
}
這個類裏,通過parseNetworkResponse方法,得到response.body().string(),然後轉換成TOkHttpResponse對象並返回。這樣一來,在TBaseCallback的子類的onResponse方法裏,就能得到TOkHttpResponse類型的結果了。
舉個栗子:
針對上面的result字段
"result": {
"total": 0,
"data": {
"uid": 9527,
"token": "xxxxxxxxxxxxx",
"username": "xxxxx"
}
裏面字段始終都是total和data,但是data可能是Object ,也可能是array,這裏是object,所以我們給result也建一個基本類,裏面是total和data兩個字段:
TBaseDataResult.java
public class TBaseDataResult<T> {
int total ;
T data;
//get and set 方法,略...
}
在使用的時候,只需要這麼做(headM是請求頭裏的一個字段,pri_args是參數的一部分):
TBaseApi.createPostRequest(headM, pri_args, new TBaseCallback<TBaseDataResult>() {
@Override
public void onResponse(TOkHttpResponse<TBaseDataResult> response, int i) {
TBaseDataResult result = response.getResult() ;
int total = result.getTotal() ;
Object data = result.getData() ;
}
});
這樣total和data兩個字段都可以輕鬆得到了,如果想繼續解析data,那麼可以再新建個bean對象:
TLogin.java
public class TLogin {
int uid ;
String token ;
String username ;
...
}
使用時放進去:
TBaseApi.createPostRequest(headM, pri_args, new TBaseCallback<TBaseDataResult<TLogin>>() {
@Override
public void onResponse(TOkHttpResponse<TBaseDataResult<TLogin>> response, int id) {
if (response.getStatus() == 200) {
JsonElement j = new Gson().toJsonTree(response.getResult()) ;
TBaseDataResult<TLogin> result = new Gson().fromJson(j,new TypeToken<TBaseDataResult<TLogin>>(){}.getType()) ;
TLogin data = result.getData();
int uid = data.getUid() ;
String username = data.getUsername() ;
String token = data.getToken();
}
}
@Override
public void onError(Call call, Exception e, int id) {
super.onError(call, e, id);
...
}
});
這樣無論data字段裏是什麼東西,都可以依葫蘆畫瓢創建POJO對象,然後去適配。
不過每次都用new TBaseCallback()來新建Callback也很煩,所以嘛,可以把它封裝到基類裏去,比如:
TBaseNetActivity.java
public abstract class TBaseNetActivity<T> extends TBaseActivity {
public void setContentView(...) {
...
initCallBack();
}
private void initCallBack() {
if (callback == null) {
callback = new TBaseCallback<T>() {
@Override
public void onResponse(TOkHttpResponse<T> response, int id) {
hideLoadingView();
status = response.getStatus();
if (status == 200) {
onSuccessResponse(response);
} else {
...
onFailResponse(error);
}
}
@Override
public void onError(Call call, Exception e, int id) {
super.onError(call, e, id);
...
hideLoadingView();
onFailResponse(error);
}
};
}
}
public TBaseCallback<T> getCallback() {
if (callback == null) {
initCallBack();
}
return callback ;
}
public void postRequest(String headM,Map<String,Object> pri_args) {
showLoadingView();
TBaseApi.createPostRequest(headM,pri_args,getCallback());
}
public abstract void onSuccessResponse(TOkHttpResponse<T> response);
public abstract void onFailResponse(TOkHttpError error);
}
這裏的思路就很簡單了,區分請求成功(返回碼200)和請求失敗的,只允許成功的進入onSuccessResponse方法裏,把錯誤邏輯都扔到onFailResponse裏,避免了原來在onResponse裏解析時的過多的判斷。TOkHttpError跟TOkHttpResponse類似,是封裝的錯誤返回碼
使用時創建Activity,傳入bean類,重寫父類的方法:
public class TMyActivity extends TBaseNetActivity<TBaseDataResult<TBean>> {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
//發送請求,因爲Okhttp-utils已經封裝成異步請求了,所以主線程中請求網絡是完全沒問題的
postRequest(headM,pri_args);
}
@Override
public void onSuccessResponse(TOkHttpResponse<TBaseDataResult<TBean>> response) {
//解析數據咯
}
@Override
public void onFailResponse(TOkHttpError error) {
//失敗時的異常處理
}
}
關於網絡框架的封裝,差不多就涉及這些了。
github地址:https://github.com/herdotage/Android_sample/tree/master/LOkhttpUtils