配色: 字号:
Android -- OkHttp的简单使用和封装
2016-12-22 | 阅:  转:  |  分享 
  
Android--OkHttp的简单使用和封装

1,昨天把okHttp仔细的看了一下,以前都是调用同事封装好了的网络框架,直接使用很容易,但自己封装却不是那么简单,还好,今天就来自我救赎一把,就和大家写写从最基础的OKHttp的简单get、post的使用,再到它的封装。



2,OkHttp的简单使用



首先我们创建一个工程,并在布局文件中添加三个控件,TextView(用于展示获取到json后的信息)、Button(点击开始请求网络)、ProgressBar(网络加载提示框)



①简单的异步Get请求



第一步,创建OKHttpClient对象



第二步,创建Request请求



第三步,创建一个Call对象



第四步,将请求添加到调度中



不多说,直接上代码:



//okHttp的基本使用---get方法

Stringurl="https://api.douban.com/v2/movie/top250?start=0&count=10";

//1,创建OKHttpClient对象

OkHttpClientmOkHttpClient=newOkHttpClient();

//2,创建一个Request

Requestrequest=newRequest.Builder().url(url).build();

//3,创建一个call对象

Callcall=mOkHttpClient.newCall(request);

//4,将请求添加到调度中

call.enqueue(newCallback(){

@Override

publicvoidonFailure(Requestrequest,IOExceptione){



}



@Override

publicvoidonResponse(Responseresponse)throwsIOException{

if(response.isSuccessful()){

finalStringmessage=response.body().string();

handler.post(newRunnable(){

@Override

publicvoidrun(){

tv_message.setText(message);

progressBar.setVisibility(View.GONE);

}

});



}









注意,由于我们调用的enqueue()方法,是运行在网络线程中的,所以当我们得到json数据后想要获取更新UI的话,可以开使用handle.post()方法在run方法里面更新UI。



②简单的异步Post请求



这里的Post请求我们以最常见的注册登录来举例。post请求的步骤和get是相似的只是在创建Request的时候将服务器需要的参数传递进去.



代码如下:



Stringurl="http://192.168.1.123:8081/api/login";

//1,创建OKhttpClient对象

OkHttpClientmOkHttpClient=newOkHttpClient();

//2,创建Request

RequestBodyformBody=newFormEncodingBuilder()

.add("username","superadmin")

.add("pwd","ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413")

.build();



Requestrequest=newRequest.Builder().url(url).post(formBody).build();

//3,创建call对象并将请求对象添加到调度中

mOkHttpClient.newCall(request).enqueue(newCallback(){

@Override

publicvoidonFailure(Requestrequest,IOExceptione){



}



@Override

publicvoidonResponse(Responseresponse)throwsIOException{

Log.i("wangjitao",response.body().string());

}

});

看一下我们服务器的断点







可以看到我们服务器的确拿到了我们传递参数,再看一下我们请求后拿到的数据







ok,这样的话我们的post方法就没什么问题了



3,OkHttp的封装



由于是封装我们可以吧OKHttp和Gson给结合起来,那么我们在gradle文件添加以下的依赖



compile"com.squareup.okhttp:okhttp:2.4.0"

compile''com.squareup.okio:okio:1.5.0''

compile"com.google.code.gson:gson:2.8.0"

①CallBack的创建



首选我们知道,当接口请求成功或者失败的时候我们需要将这个信息通知给用户,那么我们就需要创建一个抽象类RequestCallBack,请求前、成功、失败、请求后这几个方法,创建OnBefore()、OnAfter()、OnError()、OnResponse()对应



/

在请求之前的方法,一般用于加载框展示



@paramrequest

/

publicvoidonBefore(Requestrequest){

}



/

在请求之后的方法,一般用于加载框隐藏

/

publicvoidonAfter(){

}



/

请求失败的时候



@paramrequest

@parame

/

publicabstractvoidonError(Requestrequest,Exceptione);



/



@paramresponse

/

publicabstractvoidonResponse(Tresponse);

由于我们每次想要的数据不一定,所以这里我们用来接收想要装成的数据格式,并通过反射得到想要的数据类型(一般是Bean、List)之类,所以RequestCallBack的整体代码如下:



packagecom.qianmo.httprequest.http;



importcom.google.gson.internal.$Gson$Types;

importcom.squareup.okhttp.Request;



importjava.lang.reflect.ParameterizedType;

importjava.lang.reflect.Type;





/

Createdbywangjitaoon15/10/16.

抽象类,用于请求成功后的回调

/

publicabstractclassResultCallback{

//这是请求数据的返回类型,包含常见的(Bean,List等)

TypemType;



publicResultCallback(){

mType=getSuperclassTypeParameter(getClass());

}



/

通过反射想要的返回类型



@paramsubclass

@return

/

staticTypegetSuperclassTypeParameter(Classsubclass){

Typesuperclass=subclass.getGenericSuperclass();

if(superclassinstanceofClass){

thrownewRuntimeException("Missingtypeparameter.");

}

ParameterizedTypeparameterized=(ParameterizedType)superclass;

return$Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);

}



/

在请求之前的方法,一般用于加载框展示



@paramrequest

/

publicvoidonBefore(Requestrequest){

}



/

在请求之后的方法,一般用于加载框隐藏

/

publicvoidonAfter(){

}



/

请求失败的时候



@paramrequest

@parame

/

publicabstractvoidonError(Requestrequest,Exceptione);



/



@paramresponse

/

publicabstractvoidonResponse(Tresponse);

}

②对Get、Post方法的简单封装



首先我们创建一个OkHttpClientManager类,由于是管理类,所以,单例加静态对象搞起



privatestaticOkHttpClientManagermInstance;



publicstaticOkHttpClientManagergetInstance(){

if(mInstance==null){

synchronized(OkHttpClientManager.class){

if(mInstance==null){

mInstance=newOkHttpClientManager();

}

}

}

returnmInstance;

}

在创建Manager对象的时候我们要把OkHttp的一些参数配置一下,顺便一提一下,由于我们我们异步get、post方法是运行在子线程中,所以这里我们添加了分发的HandlermDelivery;,重写的OkHttpClientManager构造方法如下:



privateOkHttpClientManager(){

mOkHttpClient=newOkHttpClient();

mOkHttpClient.setConnectTimeout(10,TimeUnit.SECONDS);

mOkHttpClient.setWriteTimeout(10,TimeUnit.SECONDS);

mOkHttpClient.setReadTimeout(30,TimeUnit.SECONDS);

//cookieenabled

mOkHttpClient.setCookieHandler(newCookieManager(null,CookiePolicy.ACCEPT_ORIGINAL_SERVER));

mDelivery=newHandler(Looper.getMainLooper());

mGson=newGson();

}

前面的外部调用对象封装好了,这里我们开始来封装Get或Post方法,我这里以Post方法为例子,首先分析一下,post方法会有几个参数,参数一url,参数二参数params,参数三Callback(及我们上面的RequestCallBack)参数四flag(用于取消请求操作,可为空),基础代码如下:



/

通用基础的异步的post请求

@paramurl

@paramcallback

@paramtag

/

publicvoidpostAsyn(Stringurl,Param[]params,finalResultCallbackcallback,Objecttag){

Requestrequest=buildPostFormRequest(url,params,tag);

deliveryResult(callback,request);

}

那么我们再看一下deliveryResult方法到底是干什么的





/

请求回调处理方法并传递返回值

@paramcallbackMap类型请求参数

@paramrequestRequest请求

/

privatevoiddeliveryResult(ResultCallbackcallback,Requestrequest){

if(callback==null)

callback=DEFAULT_RESULT_CALLBACK;

finalResultCallbackresCallBack=callback;

//UIthread

callback.onBefore(request);

mOkHttpClient.newCall(request).enqueue(newCallback(){

@Override

publicvoidonFailure(finalRequestrequest,finalIOExceptione){

sendFailedStringCallback(request,e,resCallBack);

}



@Override

publicvoidonResponse(finalResponseresponse){

try{

finalStringresponseMessage=response.message();

finalStringresponseBody=response.body().string();

if(response.code()==200){

if(resCallBack.mType==String.class){

sendSuccessResultCallback(responseBody,resCallBack);

}else{

Objecto=mGson.fromJson(responseBody,resCallBack.mType);

sendSuccessResultCallback(o,resCallBack);

}

}else{

Exceptionexception=newException(response.code()+":"+responseMessage);

sendFailedStringCallback(response.request(),exception,resCallBack);

}

}catch(IOExceptione){

sendFailedStringCallback(response.request(),e,resCallBack);

}catch(com.google.gson.JsonParseExceptione){//Json解析的错误

sendFailedStringCallback(response.request(),e,resCallBack);

}

}

});

}

可以看到,这个方法主要是发出请求并对请求后的数据开始回调,这样我们就基本上封装好了一个post方法了,把代码这一部分的代码贴出来看看





publicclassOkHttpClientManager{

privatestaticfinalStringTAG="com.qianmo.httprequest.http.OkHttpClientManager";



privatestaticOkHttpClientManagermInstance;

//默认的请求回调类

privatefinalResultCallbackDEFAULT_RESULT_CALLBACK=newResultCallback(){

@Override

publicvoidonError(Requestrequest,Exceptione){}



@Override

publicvoidonResponse(Stringresponse){}

};

privateOkHttpClientmOkHttpClient;

privateHandlermDelivery;

privateGsonmGson;

privateGetDelegatemGetDelegate=newGetDelegate();

privatePostDelegatemPostDelegate=newPostDelegate();

privateDownloadDelegatemDownloadDelegate=newDownloadDelegate();



privateOkHttpClientManager(){

mOkHttpClient=newOkHttpClient();

mOkHttpClient.setConnectTimeout(10,TimeUnit.SECONDS);

mOkHttpClient.setWriteTimeout(10,TimeUnit.SECONDS);

mOkHttpClient.setReadTimeout(30,TimeUnit.SECONDS);

//cookieenabled

mOkHttpClient.setCookieHandler(newCookieManager(null,CookiePolicy.ACCEPT_ORIGINAL_SERVER));

mDelivery=newHandler(Looper.getMainLooper());

mGson=newGson();

}



publicstaticOkHttpClientManagergetInstance(){

if(mInstance==null){

synchronized(OkHttpClientManager.class){

if(mInstance==null){

mInstance=newOkHttpClientManager();

}

}

}

returnmInstance;

}



/

外部可调用的Post异步请求方法

@paramurl请求url

@paramparams

@paramcallback请求完成后回调类

/

publicstaticvoidpostAsyn(Stringurl,Mapparams,finalResultCallbackcallback){

getInstance().getPostDelegate().postAsyn(url,params,callback,null);

}



/

异步的post请求

@paramurl

@paramparams

@paramcallback

@paramtag

/

publicvoidpostAsyn(Stringurl,Mapparams,finalResultCallbackcallback,Objecttag){

Param[]paramsArr=map2Params(params);

postAsyn(url,paramsArr,callback,tag);

}

/

通用基础的异步的post请求

@paramurl

@paramcallback

@paramtag

/

publicvoidpostAsyn(Stringurl,Param[]params,finalResultCallbackcallback,Objecttag){

Requestrequest=buildPostFormRequest(url,params,tag);

deliveryResult(callback,request);

}



/

请求回调处理方法并传递返回值

@paramcallbackMap类型请求参数

@paramrequestRequest请求

/

privatevoiddeliveryResult(ResultCallbackcallback,Requestrequest){

if(callback==null)

callback=DEFAULT_RESULT_CALLBACK;

finalResultCallbackresCallBack=callback;

//UIthread

callback.onBefore(request);

mOkHttpClient.newCall(request).enqueue(newCallback(){

@Override

publicvoidonFailure(finalRequestrequest,finalIOExceptione){

sendFailedStringCallback(request,e,resCallBack);

}



@Override

publicvoidonResponse(finalResponseresponse){

try{

finalStringresponseMessage=response.message();

finalStringresponseBody=response.body().string();

if(response.www.baiyuewang.netcode()==200){

if(resCallBack.mType==String.class){

sendSuccessResultCallback(responseBody,resCallBack);

}else{

Objecto=mGson.fromJson(responseBody,resCallBack.mType);

sendSuccessResultCallback(o,resCallBack);

}

}else{

Exceptionexception=newException(response.code()+":"+responseMessage);

sendFailedStringCallback(response.request(),exception,resCallBack);

}

}catch(IOExceptione){

sendFailedStringCallback(response.request(),e,resCallBack);

}catch(com.google.gson.JsonParseExceptione){//Json解析的错误

sendFailedStringCallback(response.request(),e,resCallBack);

}

}

});

}

/

处理请求成功的回调信息方法

@paramobject服务器响应信息

@paramcallback回调类

/

privatevoidsendSuccessResultCallback(finalObjectobject,finalResultCallbackcallback){

mDelivery.post(()->{

callback.onResponse(object);

callback.onAfter();

});

}

}

这样我们就把Post方法封装好了,同理Get方法,ok,现在我们可以来调用调用了,在调用之前我们可以对返回数据格式再来封装封装,一般我们后台返回的数据格式是类似如下:





{

"code":200,

"data":{},

"message":"登录成功"

}

而data中有可能是对象,也有可能是数组,所以我们用两个类来实现一下



CommonResultBean



packagecom.qianmo.httprequest.bean;



/

服务端返回通用接收实体

Createdbywangjitaoon15/10/30.

/

publicclassCommonResultBean{

privateStringcode;

privateTdata;

privateStringmessage;



publicStringgetCode(){

returncode;

}



publicvoidsetCode(Stringcode){

this.code=code;

}



publicTgetData(){

returndata;

}



publicvoidsetData(Tdata){

this.data=data;

}



publicStringgetMessage(){

returnmessage;

}



publicvoidsetMessage(Stringmessage){

this.message=message;

}

}

CommonResultListBean





packagecom.qianmo.httprequest.bean;



importjava.util.List;



/

服务端返回带有List数据的通用接收实体

Createdbywangjitaoon15/12/1.

/

publicclassCommonResultListBean{

privateStringcode;

privateListdata;

privateStringmessage;



publicStringgetCode(){

returncode;

}



publicvoidsetCode(Stringcode){

this.code=code;

}



publicListgetData(){

returndata;

}



publicvoidsetData(Listdata){

this.data=data;

}



publicStringgetMessage(){

returnmessage;

}



publicvoidsetMessage(Stringmessage){

this.message=message;

}

}

ok,现在还是以上面我们登录的接口为例子开始我们的方法调用,返回的数据格式如图所示







我们创建UserMenu.java类



1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

packagecom.qianmo.httprequest.bean;



importjava.util.List;



/

Createdbywangjitaoon2016/12/210021.

E-Mail:543441727@qq.com

用户菜单权限按钮

/

publicclassUserMenu{



/

last_login_time:2016-12-2115:40:28

member_id:1

modules:[]

phone:18900532225

real_name:超级管理员

role:{"role_id":1,"role_name":"超级管理员"}

username:superadmin

/



privateStringlast_login_time;

privateintmember_id;

privateStringphone;

privateStringreal_name;

/

role_id:1

role_name:超级管理员

/



privateRoleBeanrole;

privateStringusername;

/

module_code:100

module_id:1

module_name:首页

pid:0

type:1

value:P_index

/



privateListmodules;



publicStringgetLast_login_time(){

returnlast_login_time;

}



publicvoidsetLast_login_time(Stringlast_login_time){

this.last_login_time=last_login_time;

}



publicintgetMember_id(){

returnmember_id;

}



publicvoidsetMember_id(intmember_id){

this.member_id=member_id;

}



publicStringgetPhone(){

returnphone;

}



publicvoidsetPhone(Stringphone){

this.phone=phone;

}



publicStringgetReal_name(){

returnreal_name;

}



publicvoidsetReal_name(Stringreal_name){

this.real_name=real_name;

}



publicRoleBeangetRole(){

returnrole;

}



publicvoidsetRole(RoleBeanrole){

this.role=role;

}



publicStringgetUsername(){

returnusername;

}



publicvoidsetUsername(Stringusername){

this.username=username;

}



publicListgetModules(){

returnmodules;

}



publicvoidsetModules(Listmodules){

this.modules=modules;

}



publicstaticclassRoleBean{

privateintrole_id;

privateStringrole_name;



publicintgetRole_id(){

returnrole_id;

}



publicvoidsetRole_id(introle_id){

this.role_id=role_id;

}



publicStringgetRole_name(){

returnrole_name;

}



publicvoidsetRole_name(Stringrole_name){

this.role_name=role_name;

}

}



publicstaticclassModulesBean{

privateStringmodule_code;

privateintmodule_id;

privateStringmodule_name;

privateintpid;

privateinttype;

privateStringvalue;



publicStringgetModule_code(){

returnmodule_code;

}



publicvoidsetModule_code(Stringmodule_code){

this.module_code=module_code;

}



publicintgetModule_id(){

returnmodule_id;

}



publicvoidsetModule_id(intmodule_id){

this.module_id=module_id;

}



publicStringgetModule_name(){

returnmodule_name;

}



publicvoidsetModule_name(Stringmodule_name){

this.module_name=module_name;

}



publicintgetPid(){

returnpid;

}



publicvoidsetPid(intpid){

this.pid=pid;

}



publicintgetType(){

returntype;

}



publicvoidsetType(inttype){

this.type=type;

}



publicStringgetValue(){

returnvalue;

}



publicvoidsetValue(Stringvalue){

this.value=value;

}

}



}

所以MainActivity代码如下:





packagecom.qianmo.httprequest;



importandroid.os.Environment;

importandroid.os.Handler;

importandroid.support.v7.app.AppCompatActivity;

importandroid.os.Bundle;

importandroid.util.Log;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.Button;

importandroid.widget.ProgressBar;

importandroid.widget.TextView;



importcom.qianmo.httprequest.bean.CommonResultBean;

importcom.qianmo.httprequest.bean.UserMenu;

importcom.qianmo.httprequest.http.IRequestCallBack;

importcom.qianmo.httprequest.http.IRequestManager;

importcom.qianmo.httprequest.http.OkHttpClientManager;

importcom.qianmo.httprequest.http.RequestFactory;

importcom.qianmo.httprequest.http.ResultCallback;

importcom.squareup.okhttp.Call;

importcom.squareup.okhttp.Callback;

importcom.squareup.okhttp.FormEncodingBuilder;

importcom.squareup.okhttp.OkHttpClient;

importcom.squareup.okhttp.Request;

importcom.squareup.okhttp.RequestBody;

importcom.squareup.okhttp.Response;



importjava.io.File;

importjava.io.IOException;

importjava.util.HashMap;

importjava.util.Map;





publicclassMainActivityextendsAppCompatActivityimplementsOnClickListener{

privateHandlerhandler;

privateTextViewtv_message;

privateButtonbtn_login;

privateProgressBarprogressBar;



@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

tv_message=(TextView)findViewById(R.id.tv_message);

btn_login=(Button)findViewById(R.id.btn_login);

progressBar=(ProgressBar)findViewById(R.id.progressBar);

handler=newHandler();

btn_login.setOnClickListener(this);

}



@Override

publicvoidonClick(Viewview){

progressBar.setVisibility(View.VISIBLE);





Stringurl="http://192.168.1.123:8081/api/login";

Mapparams=newHashMap();

params.put("username","superadmin");

params.put("pwd","ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413");

OkHttpClientManager.postwww.tt951.comAsyn(url,params,

newResultCallback>(){

@Override

publicvoidonError(Requestrequest,Exceptione){



}



@Override

publicvoidonResponse(CommonResultBeanresponse){

if(response.getData()!=null){

UserMenuuserMenu=response.getData();

tv_message.setText(userMenu.getReal_name());

progressBar.setVisibility(View.GONE);

}

}

});



}

}

献花(0)
+1
(本文系thedust79首藏)