游戏社区App (二):网络请求框架的封装

网络请求框架的封装

目前主流的网络请求框架有: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 (三):客户端与服务端的加密处理 和 登录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值