目前主流的网络请求框架有:Volley、OkHttp、Retrofit
Volley是Google官方出的一套小而巧的异步请求库。Volley框架封装的扩展性很强,但它不支持post大数据,不适合上传文件。它基本为频繁的、数据量小的网络请求而生。
OkHttp是Square公司开源的针对Java和Android程序,封装的一个高性能http请求库。
Retrofit同为Square公司出品,默认基于OkHttp封装的RESTful网络请求框架。
Retrofit本身并没有进行网络请求操作,真正的网络请求操作是依赖于Retrofit内部使用的Okhttp实现。
这里使用 Retrofit 网络请求框架,并对其进行一个简单的封装。
网络请求框架的封装
使用建造者模式,封装后可以在需要网络请求的地方便捷地进行请求。
示例:
RestClient.builder()
.url("https://www.baidu.com/")
.success(new ISuccess() {
@Override
public void onSuccess(String response) {
//请求成功
}
})
.failure(new IFailure() {
@Override
public void onFailure(String msg) {
//请求失败
}
})
.error(new IError() {
@Override
public void onError(int code, String msg) {
//请求错误
}
})
.build()
.post();
首先引入网络请求的依赖。
其中Loader用作网络请求时的等待动画,使用的是GitHub上的AVLoadingIndicatorView,它有多种等待动画样式,
//网络请求依赖
api 'com.squareup.okio:okio:1.14.0'
api 'com.squareup.okhttp3:okhttp:3.10.0'
api 'com.squareup.retrofit2:retrofit:2.3.0'
api 'com.squareup.retrofit2:converter-scalars:2.3.0'
//Loader的依赖
api 'com.wang.avi:library:2.1.3'
然后进行RestClient封装
1.先建立Retrofit请求必须要的接口文件RestService
public interface RestService {
@GET
Call<String> get(@Url String url, @QueryMap Map<String, Object> params);
@FormUrlEncoded
@POST
Call<String> post(@Url String url, @FieldMap Map<String, Object> params);
@POST
Call<String> postRaw(@Url String url, @Body RequestBody body);
@FormUrlEncoded
@PUT
Call<String> put(@Url String url, @FieldMap Map<String, Object> params);
@PUT
Call<String> putRaw(@Url String url, @Body RequestBody body);
@DELETE
Call<String> delete(@Url String url, @QueryMap Map<String, Object> params);
//@Streaming 避免内存溢出,download默认是全部下载到内存再保存到本地的,添加Streaming让其边下载到内存 边保存本地
@Streaming
@GET
Call<ResponseBody> download(@Url String url, @QueryMap Map<String, Object> params);
@POST
Call<String> upload(@Url String url, @Part MultipartBody.Part file);
}
2.再新建HttpMethod的枚举类
public enum HttpMethod {
GET,
POST,
POST_RAW,
PUT,
PUT_RAW,
DELETE,
UPLOAD
}
3.新建RestCreator类,将RetrofitService的接口实例化,然后用来进行网络请求。
public class RestCreator{
private static final class ParamsHolder{
private static final WeakHashMap<String, Object> PARAMS = new WeakHashMap<>();
}
public static WeakHashMap<String, Object> getParams(){
return ParamsHolder.PARAMS;
}
// 对外释放RestService的实例
public static RestService getRestService(){
return RestServiceHolder.REST_SRVICE;
}
private static final class RetrofitHolder{
private static final String BASE_URL = Latte.getConfiguration(ConfigType.API_HOST);
private static final Retrofit RETROFIT_CLIENT = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(OKHttpHolder.OK_HTTP_CLIENT)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
}
private static final class OKHttpHolder {
private static final int TIME_OUT = 60;
private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient.Builder()
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
.build();
}
private static final class RestServiceHolder{
private static final RestService REST_SERVICE =
RetrofitHolder.RETROFIT_HOLDER.create(RestService.class);
}}
4.新建RequestCallbacks处理网络请求的回调,实现Callback的接口
public class RequestCallbacks implements Callback<String>{
private final IRequest REQUEST;
private final ISuccess SUCCESS;
private final IFailure FAILURE;
private final IError ERROR;
private final LoaderStyle LOADER_STYLE;
public RequestCallbacks(IRequest request, ISuccess success, IFailure failure, IError error, LoaderStyle loaderStyle){
this.REQUEST = request;
this.SUCCESS = success;
this.FAILURE = failure;
this.ERROR = error;
this.LOADER_STYLE = loaderStyle;
}
@Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful()) {
if (call.isExecuted()) {
if (SUCCESS != null) {
SUCCESS.onSuccess(response.body());
}
}
} else {
if (ERROR != null) {
ERROR.onError(response.code(), response.message());
}
}
stopLoader();
}
@Override
public void onFailure(Call<String> call, Throwable t) {
if (FAILURE != null) {
FAILURE.onFailure();
}
if (REQUEST != null) {
REQUEST.onRequestEnd();
}
stopLoader();
}
private void stopLoader() {
if (LOADER_STYLE != null) {
LatteLoader.stopLoading();
}
}
}
5.新建RestClient,将传入的数据进行组装,然后使用实例化的RestService对象进行网络请求。
public class RestClient {
private final String URL;
private static final WeakHashMap<String, Object> PARAMS = RestCreator.getParams();
private final IRequest REQUEST;
private final String DOWNLOAD_DIR;
private final String EXTENSION;
private final String NAME;
private final ISuccess SUCCESS;
private final IFailure FAILURE;
private final IError ERROR;
private final RequestBody BODY;
private final LoaderStyle LOADER_STYLE;
private final File FILE;
private final Context CONTEXT;
public RestClient(String url,
Map<String, Object> params,
String downloadDir,
String extension,
String name,
IRequest request,
ISuccess success,
IFailure failure,
IError error,
RequestBody body,
File file,
Context context,
LoaderStyle loaderStyle) {
this.URL = url;
PARAMS.putAll(params);
this.DOWNLOAD_DIR=downloadDir;
this.EXTENSION=extension;
this.NAME=name;
this.REQUEST = request;
this.SUCCESS = success;
this.FAILURE = failure;
this.ERROR = error;
this.BODY = body;
this.FILE=file;
this.CONTEXT=context;
this.LOADER_STYLE=loaderStyle;
}
public static RestClientBuilder builder(){
return new RestClientBuilder();
}
private void request(HttpMethod method){
final RestService service = RestCreator.getRestService();
Call<String> call = null;
if(REQUEST!=null){
REQUEST.onRequestStart();
}
if(LOADER_STYLE!=null){
LatteLoader.showLoading(CONTEXT,LOADER_STYLE);
}
//retrofit网络框架请求方法
switch (method){
case GET:
call=service.get(URL,PARAMS);
break;
case POST:
call=service.post(URL,PARAMS);
break;
case POST_RAW:
call=service.postRaw(URL,BODY);
case PUT:
call=service.put(URL,PARAMS);
break;
case PUT_RAW:
call=service.putRaw(URL,BODY);
break;
case DELETE:
call=service.delete(URL,PARAMS);
break;
case UPLOAD:
final RequestBody requestBody =RequestBody.create(MediaType.parse(MultipartBody.FORM.toString()),FILE);
final MultipartBody.Part body=MultipartBody.Part.createFormData("file",FILE.getName(),requestBody);
call=RestCreator.getRestService().upload(URL,body);
break;
default:
break;
}
if(call!=null){
call.enqueue(getRequestCallback());
}
}
private Callback<String> getRequestCallback(){
return new RequestCallbacks(REQUEST,SUCCESS,FAILURE,ERROR,LOADER_STYLE);
}
public final void get(){
request(HttpMethod.GET);
}
public final void post(){
if(BODY==null){
request(HttpMethod.POST);
}else{
if(!PARAMS.isEmpty()){
throw new RuntimeException("params must be null!");
}
request(HttpMethod.POST_RAW);
}
}
public final void put(){
if(BODY==null){
request(HttpMethod.PUT);
}else{
if(!PARAMS.isEmpty()){
throw new RuntimeException("params must be null!");
}
request(HttpMethod.PUT_RAW);
}
}
public final void delete(){
request(HttpMethod.DELETE);
}
public final void upload(){
request(HttpMethod.UPLOAD);
}
public final void download(){
new DownloadHandler(URL,REQUEST,DOWNLOAD_DIR,EXTENSION,NAME,SUCCESS,FAILURE,ERROR).handleDownload();
}
}
6.因为RestClient采用的是建造者模式,所以还需要新建RestClientBuilder
public class RestClientBuilder {
private String mUrl =null;
private static final WeakHashMap<String, Object> PARAMS = RestCreator.getParams();
private IRequest mIRequest =null;
private ISuccess mISuccess =null;
private IFailure mIFailure =null;
private IError mIError =null;
private RequestBody mBody =null;
private File mFile=null;
private String mDownloadDir=null;
private String mExtension=null;
private String mName=null;
private Context mContext =null;
private LoaderStyle mLoaderStyle =null;
RestClientBuilder(){
}
public final RestClientBuilder url(String url){
this.mUrl=url;
return this;
}
public final RestClientBuilder params(WeakHashMap<String, Object> params){
PARAMS.putAll(params);
return this;
}
public final RestClientBuilder params(String key, Object value){
PARAMS.put(key,value);
return this;
}
public final RestClientBuilder file(File file){
this.mFile=file;
return this;
}
public final RestClientBuilder file(String file){
this.mFile=new File(file);
return this;
}
public final RestClientBuilder name(String name){
this.mName=name;
return this;
}
public final RestClientBuilder dir(String dir){
this.mDownloadDir=dir;
return this;
}
public final RestClientBuilder extension(String extension){
this.mExtension=extension;
return this;
}
public final RestClientBuilder raw(String raw){
this.mBody=RequestBody.create(MediaType.parse("application/json;charset=UTF-8"),raw);
return this;
}
public final RestClientBuilder onRequest(IRequest iRequest){
this.mIRequest=iRequest;
return this;
}
public final RestClientBuilder success(ISuccess iSuccess){
this.mISuccess=iSuccess;
return this;
}
public final RestClientBuilder failure(IFailure iFailure){
this.mIFailure=iFailure;
return this;
}
public final RestClientBuilder error(IError iError){
this.mIError=iError;
return this;
}
//loader设置
public final RestClientBuilder loader(Context context, LoaderStyle style){
this.mContext=context;
this.mLoaderStyle=style;
return this;
}
public final RestClientBuilder loader(Context context){
this.mContext=context;
this.mLoaderStyle=LoaderStyle.BallClipRotatePulseIndicator;
return this;
}
public final RestClientBuilder loader(Context context, int type){
this.mContext=context;
switch (type){
case 0:
this.mLoaderStyle=LoaderStyle.BallClipRotatePulseIndicator;
break;
case 1:
this.mLoaderStyle=LoaderStyle.BallPulseIndicator;
break;
default:
this.mLoaderStyle=LoaderStyle.BallGridPulseIndicator;
break;
}
return this;
}
public final RestClient build(){
return new RestClient(mUrl,PARAMS,mDownloadDir,mExtension,mName,mIRequest,mISuccess,mIFailure,mIError,mBody,mFile,mContext,mLoaderStyle);
}
}
至此网络请求框架的封装就算完成了。
上一篇: 游戏社区App (一):基本框架
下一篇:游戏社区App (三):客户端与服务端的加密处理 和 登录