美文网首页iOS逆向
Android战纪之网络请求框架封装(Retrofit的封装)

Android战纪之网络请求框架封装(Retrofit的封装)

作者: warmingood | 来源:发表于2018-03-30 13:36 被阅读0次

    网络请求框架封装(OkHttp3+Retrofit+loading的封装)

    • 本文主要将Retrofit网络请求和loading进行封装,之后只需很少的代码就能实现网络请求he


    • 封装后进行post请求的效果展示(在任意需要网络请求的地方)
    RestClient.builder()
            .url("/sign_in")
            .loader(getContext())
            .params("account", mEmail.getText().toString())
            .params("password", mPassword.getText().toString())
            .success(new ISuccess(){
                @Override
                public void onSuccess(){
                    //请求成功的处理逻辑
                }
            })
            .error(new IError(){
                @Override
                public void onError(){
                    //请求错误的处理逻辑
                }
            })
            .failure(new IFailure(){
                @override
                public void onFailure(){
                    //请求失败的处理逻辑
                }
            }
            .build()
            .post();
    

    • 引入依赖
      //网络请求依赖
      api 'com.squareup.okio:okio:1.13.0'
      api 'com.squareup.okhttp3:okhttp:3.8.1'
      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'
    
    • 网络框架结构

      网络请求框架结构
    • loading封装结构

      loading
    • Loader的封装

    • 1.新建LoaderStyle枚举类即定义loading展示的样式,可以在github上拿到,这里只拉了一部分。

    public enum LoaderStyle{
        BallPulseIndicator,
        BallGridPulseIndicator,
        BallClipRotateIndicator,
        BallClipRotatePulseIndicator,
        SquareSpinIndicator,
        BallClipRotateMultipleIndicator,
        BallPulseRiseIndicator,
        BallRotateIndicator,
        CubeTransitionIndicator,
        BallZigZagIndicator
    }
    
    • 2.新建LoaderCreator类,通过映射,拿到需要的样式图标。
    public final class LoaderCreator{
        // 优化,新建一个map集合,存储已经映射过的Loading
        private static final WeakHashMap<String, Indicator> LOADING_MAP = new WeakHashMap<>();
    
        static AVLoadingIndicatorView create(String type, Context context){
            final AVLoadingIndicatorView avLoadingIndicatorView = new AVLoadingIndicatorView(context);
            if (LOADING_MAP.get(type) == null){
                final Indicator indicator = getIndicator(type);
                LOADING_MAP.put(type, indicator);
            }
    
            avLoadingIndicatorView.setIndicator(LOADING_MAP.get(type));
            return avLoadingIndicatorView;
        }
        
        // 得到该type类型的Indicator
        private static Indicator getIndicator(String name){
            if (name == null||name.isEmpty()){
                return null;
            }
            final StringBuilder drawableClassName = new StringBuilder();
            if (!name.contains(".")){
                final String defaultPackageName = AVLoadingIndicatorView.class.getPackage().getName();
                drawableClassName.append(defaultPackageName)
                        .append(".indicators")
                        .append(".");
            }
            drawableClassName.append(name);
            try {
                final Class<?> drawableClass = Class.forName(drawableClassName.toString());
                return (Indicator) drawableClass.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    
    • 3.新建MyLoader,通过映射得到的图标,显示到屏幕上。
    public class MyLoader{
        private static final int LOADER_SIZE_SCALE=8;
    
        private static final int LOADER_OFFSET_SCALE=10;
    
        private static final ArrayList<AppCompatDialog> LOADERS=new ArrayList<>();
    
        private static final String DEFAULT_LOADER=LoaderStyle.BallSpinFadeLoaderIndicator.name();
    
        public static void showLoading(Context context,Enum<LoaderStyle> styleEnum){
            showLoading(context,styleEnum.name());
        }
    
        public static void showLoading(Context context,String type){
            final AppCompatDialog dialog=new AppCompatDialog(context, R.style.dialog);
    
            final AVLoadingIndicatorView avLoadingIndicatorView=LoaderCreator.create(type,context);
            dialog.setContentView(avLoadingIndicatorView);
    
            int deviceWidth= DimenUtil.getScreenWidth();
            int deviceHeight=DimenUtil.getScreenHeight();
    
            final Window dialogWindow=dialog.getWindow();
    
            if (dialogWindow!=null){
                WindowManager.LayoutParams lp=dialogWindow.getAttributes();
                lp.width=deviceWidth/LOADER_SIZE_SCALE;
                lp.height=deviceHeight/LOADER_SIZE_SCALE;
                lp.height=lp.height+deviceHeight/LOADER_OFFSET_SCALE;
                lp.gravity= Gravity.CENTER;
            }
            LOADERS.add(dialog);
            dialog.show();
        }
    
        public static void showLoading(Context context){
            showLoading(context,DEFAULT_LOADER);
        }
    
        public static void stopLoading(){
            for (AppCompatDialog dialog:LOADERS){
                if (dialog!=null){
                    if (dialog!=null){
                        dialog.cancel();
                    }
                }
            }
        }
    }
    
    • 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
        @GET
        Call<ResponseBody> download(@Url String url, @QueryMap Map<String, Object> params);
    
        @Multipart
        @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 = "http://www.baidu.com/"
            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.根据获取到的参数数据,组装之后进行网络请求(使用建造者模式进行数据的组装)先建立callback的回调接口
    public interface ISuccess {
        void onSuccess(String response);
    }
    
    public interface IError {
        void onError(int Code, String msg);
    }
    
    public interface IFailure {
        void onFailure();
    }
    
    public interface IRequest {
        void onRequestStart();
        void onRequestEnd();
    }
    
    • 5.新建RequestCallbacks实现Callback<String>的接口,即处理网络请求的回调
    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();
            }
        }
    }
    
    • 6.新建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,
                          IRequest request,
                          String download_dir,
                          String extension,
                          String name,
                          ISuccess success,
                          IFailure failure,
                          IError error,
                          RequestBody body,
                          LoaderStyle loaderStyle,
                          File file,
                          Context context) {
            this.URL = url;
            PARAMS.putAll(params);
            this.REQUEST = request;
            this.DOWNLOAD_DIR = download_dir;
            this.EXTENSION = extension;
            this.NAME = name;
            this.SUCCESS = success;
            this.FAILURE = failure;
            this.ERROR = error;
            this.BODY = body;
            this.LOADER_STYLE = loaderStyle;
            this.FILE = file;
            this.CONTEXT = context;
        }
        
        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);
            }
            
            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);
                    break;
                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());
            }
            RestCreator.getParams().clear();
        }
        
        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);
        }
    }
    
    • 7.新建RestClientBuilder,就是RestClient的建造者类
    public class RestClientBuilder {
    
        private String mUrl = null;
        private static final Map<String, Object> PARAMS = RestCreator.getParams();
        private IRequest mIRequest = null;
        private String mDownloadDir = null;
        private String mExtension = null;
        private String mName = null;
        private ISuccess mISuccess = null;
        private IFailure mIFailure = null;
        private IError mIError = null;
        private RequestBody mBody = null;
        private LoaderStyle mLoaderStyle = null;
        private File mFile = null;
        private Context mContext = 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 raw(String raw) {
            this.mBody = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), raw);
            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 name(String name) {
            this.mName = name;
            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;
        }
    
        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.BallSpinFadeLoaderIndicator;
            return this;
        }
    
        public final RestClient build() {
            return new RestClient(mUrl, PARAMS, mIRequest, mDownloadDir, mExtension, mName, mISuccess, mIFailure, mIError, mBody, mLoaderStyle, mFile, mContext);
        }
    
    }
    
    • 8.小结
      至此网络框架告一段落,其中的download没有写全,调用方式就是开头写的那样。

    相关文章

      网友评论

        本文标题:Android战纪之网络请求框架封装(Retrofit的封装)

        本文链接:https://www.haomeiwen.com/subject/giqicftx.html