Android OkHttp + Retrofit 使用示例
OkHttp是一款HTTP客户端。它使用连接池减少请求延迟,能在传输GZIP时减少下载体积,还有缓存相同请求的回复的特点。
可以单独使用OkHttp,也可以结合Retrofit,打造一个适合自己业务需求的工具。
本文介绍OkHttp + Retrofit使用示例。从引入依赖,编写接口,到发起网络请求。
简单使用
引入依赖
引入依赖,使用Retrofit2。
implementation 'com.squareup.retrofit2:retrofit:2.1.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
然后新建一个接口(interface)CfgService,在这里面定义我们需要用到的服务。
public interface CfgService { /* 具体的方法 */ }
后面会用到一些注解。
查询 @Query
例如URL https://rustfisher.com/api/config?env=dev
,问号后面属于查询内容。
不论是GET或POST,都要用@Query
这个注解。否则会报异常。
URL填充与拼接
单纯URL填充可以用@Path
注解。
例如下面这个post请求。
@POST("api/user/{uid}/token/refresh")
Call<RefreshTokenResp> refreshToken(@Path("uid") String uid, @Query("token") String token);
GET带有查询的参数
使用GET
注解
public interface CfgService {
@GET("api/config")
Call<ServerCfgResp> getServerCfg(@Query("env") String env);
}
POST,带有查询的参数和body
使用POST
注解
public interface UserService {
@POST("user-service/login")
Call<LoginResp> login(@Query("lenovoST") String token, @Query("realm") String realm,
@Body RequestBody body);
@POST("user-service/logout")
Call<CommonEntity> logout(@Query("token") String token, @Body RequestBody body);
}
调用的时候要创建RequestBody
;先调查好后台接受的body类型。
Map<String, String> map = new HashMap<>();
map.put("system", "Android");
map.put("phoneBrand", Build.BRAND);
map.put("modelNum", Build.MODEL);
Gson gson = new Gson();
String bodyJson = gson.toJson(map);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), bodyJson);
初始化OkHttpClient
;这里信任所有的SSL证书(正式环境不建议这么做)。
private CfgService cfgService;
public void initService() {
SSLSocketFactory sslSocketFactory = null;
try {
sslSocketFactory = SSLUtils.getSSLSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (sslSocketFactory != null) {
Log.d(TAG, "sslSocketFactory != null");
builder.sslSocketFactory(sslSocketFactory);
} else {
Log.w(TAG, "sslSocketFactory == null");
}
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true; // 强制返回true
}
});
OkHttpClient lenClient = builder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ServerCfg.HOST_URL)
.client(lenClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
cfgService = retrofit.create(CfgService.class);
}
调用网络请求
mNetworkManager.getUserApi().login(mLenovoToken, ServerCfg.RID, requestBody).enqueue(new Callback<LoginResp>() {
@Override
public void onResponse(Call<LoginResp> call, final Response<LoginResp> response) {
// 服务器有回复 ...
}
@Override
public void onFailure(Call<LoginResp> call, final Throwable t) {
// 访问失败 ...
}
});
信任所有服务器的ssl
并不推荐这么做
历史原因,有的项目里对测试站会信任所有的ssl证书。
public class SSLUtils {
/**
* @return 信任所有服务器
*/
public static SSLSocketFactory getSSLSocketFactory() throws Exception {
SSLSocketFactory sslSocketFactory = null;
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{createTrustAllManager()}, new SecureRandom());
sslSocketFactory = sslContext.getSocketFactory();
return sslSocketFactory;
}
public static X509TrustManager createTrustAllManager() {
X509TrustManager tm = null;
try {
tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
//do nothing,接受任意客户端证书
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
//do nothing,接受任意服务端证书
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
} catch (Exception e) {
}
return tm;
}
}
使用io.reactivex.Observable
import的时候注意一下,使用rx2的包。
import io.reactivex.Observable; // 这个是rx2的包
// ...
/**
* 用户反馈接口
*
* @param content 用户输入的反馈内容
*/
@POST("feedbackAction")
Observable<UserFeedback> userFeedback(@Query("appVersion") String appVersion,
@Query("phoneModel") String phoneModel,
@Query("phoneOsVersion") String osVersion,
@Query("submitContent") String content);
示例 - Retrofit2,RxJava2
接下来是一个访问示例的部分代码
引入依赖
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
定义interface
import java.util.Map;
import io.reactivex.Observable;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
/**
* rustfisher.com 后台接口
* Created on 2019-5-17
*/
public interface RustDroneCommonService {
/**
* 用户反馈接口
*
* @param content 用户输入的反馈内容
*/
@FormUrlEncoded
@POST("feedbackAction")
Observable<FeedbackResp> userFeedback(@Field("appVersion") String appVersion,
@Field("phoneModel") String phoneModel,
@Field("phoneOsVersion") String osVersion,
@Field("submitContent") String content,
@FieldMap Map<String, String> map);
/**
* 获取手机验证码
*
* @param mobile 手机号
*/
@GET("verifyCode")
Observable<PhoneCodeResp> getPhoneCode(@Query("mobile") String mobile, @Query("oprType") int type);
}
调用接口
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
RustDroneDataCenter.getCenter().getCommonService().userFeedback(BuildConfig.VERSION_NAME,
Build.MODEL.replace(" ", "-"), Build.VERSION.RELEASE, fd, ext)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<FeedbackResp>() {
@Override
public void onSubscribe(Disposable d) {
// LL.dn(TAG, "onSubscribe: " + d);
}
@Override
public void onNext(FeedbackResp feedbackResp) {
LL.dn(TAG, "onNext: " + feedbackResp);
if (feedbackResp.getCode() == 0) {
popSubmitSuccessDialog();
} else {
LL.e("上传用户反馈失败");
mPbLayout.setVisibility(View.GONE);
popRetryDialog();
}
}
@Override
public void onError(Throwable e) {
LL.e("上传用户反馈失败 code: " + e);
mPbLayout.setVisibility(View.GONE);
popRetryDialog();
}
@Override
public void onComplete() {
mPbLayout.setVisibility(View.GONE);
LL.dn(TAG, "onComplete: 上传结束");
}
});
GithubOnAndroid示例
使用的是Github的开发API。示例代码地址: https://github.com/RustFisher/GithubOnAndroid
拦截器
定义拦截器
在下面的拦截器里打log,表明拦截到了请求。但不做其它处理。
// 仅仅是示例,不做任何处理
private Interceptor doNothingInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Log.d(TAG, "Interceptor1: intercept");
return chain.proceed(chain.request());
}
};
添加拦截器
要使用拦截器,需要把拦截器添加进去addInterceptor()
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout(10, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.addInterceptor(doNothingInterceptor) // 添加拦截器
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Log.d(TAG, "Interceptor2: intercept");
return chain.proceed(chain.request());
}
})
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Log.d(TAG, "NetworkInterceptor1: intercept");
return chain.proceed(chain.request());
}
})
.build();
拦截器中增加header
在拦截器中我们可以进行一些操作,比如操作chain中的request添加header。
// 添加一些公共参数
private Interceptor RustDroneInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("token", UserCenter.getToken())
.build();
return chain.proceed(request);
}
};
- 点赞
- 收藏
- 关注作者
评论(0)