美文网首页NetAndroid开发者俱乐部Android
Retrofit基本用法和流程分析

Retrofit基本用法和流程分析

作者: 小鱼爱记录 | 来源:发表于2016-08-02 20:31 被阅读12660次
    来自[Retrofit分析-漂亮的解耦套路(视频版)](http://www.stay4it.com/course/22/info)

    1.Retrofit基本用法

    1.初始化

            webInterface = new Retrofit.Builder()
                    .baseUrl(hostname)
                    .client(client)//这个client是OkHttpClient,以后和Okhttp的基本用法和流程分析中细说
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create(new Gson()))
                    .build()
                    .create(WebInterface.class);
    

    2.定义网络接口

    public interface WebInterface {
    
        @POST("/***/index")
        Observable<HomeResponse> getHomeIndex(@Body BaseRequest request);//首页
    
        @FormUrlEncoded
        @POST("/***/freecall")
        Observable<BaseResponse> freeCall(@Field("phone") String phone);//免费电话
    
    }
    

    3.在Activity中调用

            dataWork = WebHelper.getWebInterface()
                    .getHomeIndex(request)
                    .compose(new WebTransformer<>(this))
                    .subscribe(new WebSubscriber<IndexResponse>() {
                        @Override
                        public void onSuccess(IndexResponse response) {
                            parseData(response);
                        }
                    });
    

    注意要在onDestroy中解绑:

        @Override
        public void onDestroy() {
            super.onDestroy();
            if (dataWork != null) {
                dataWork.isUnsubscribed();
            }
        }
    

    4.在WebTransformer中添加进度条和线程切换

    public class WebTransformer<T> implements Observable.Transformer<T, T> {
        Context context;
        boolean hasDialog = true;
    
        public WebTransformer(Context context) {
            this.context = context;
        }
    
        public WebTransformer(Context context, boolean hasDialog) {
            this.context = context;
            this.hasDialog = hasDialog;
        }
    
        @Override
        public Observable<T> call(Observable<T> observable) {
            return observable.subscribeOn(Schedulers.io())
                    .doOnSubscribe(new Action0() {
                        @Override
                        public void call() {
                            if (hasDialog) {
                                DialogHelper.showDialog(context);
                            }
                        }
                    })
                    .subscribeOn(AndroidSchedulers.mainThread())
                    .observeOn(AndroidSchedulers.mainThread());
        }
    }
    

    5.在WebSubscriber中添加统一的错误处理

    public abstract class WebSubscriber<T> extends Subscriber<T> {
    
        @Override
        public void onCompleted() {
        }
    
        @Override
        public void onNext(T t) {
            DialogHelper.hideDialog();
            //居然还有的返回值不是继承BaseResponse,我想杀了后台,别拦我
            if (t instanceof BaseResponse) {
                BaseResponse baseResponse = (BaseResponse) t;
                //不要问我为什么这么多code,我也不知道后台怎么想的
                if (baseResponse.getCode() != 0 || baseResponse.getResultCode() != 0 || baseResponse.getReplyCode() != 0) {
                    String tip = "";
                    //不要问我为什么这么多message,我也不知道后台怎么想的
                    if (!TextUtils.isEmpty(baseResponse.getMessage())) {
                        tip = baseResponse.getMessage();
                    } else {
                        tip = baseResponse.getRemark();
                    }
                    ToastHelper.show(tip);
                    onFailed(t);
                } else {
                    onSuccess(t);
                }
            } else {
                onSuccess(t);
            }
        }
    
        @Override
        public void onError(Throwable e) {
            DialogHelper.hideDialog();
            if (e instanceof HttpException) {
                ToastHelper.show("网络异常");
                HttpException exception = (HttpException) e;
                if (exception.code() == 404) {
                    //没登陆的时候居然返回404,我想杀了后台,别拦我
                    SkipManager.gotoLogin();
                }
            }
        }
    
        //需要个性化的错误处理时,重写它
        protected void onFailed(T t) {
    
        }
    
        //正确的回调
        public abstract void onSuccess(T t);
    
    }
    

    2.Retrofit的优点

    Q1.什么是网络框架?
    业务层-->网络调度层-->网络执行层

    这里:
    Retrofit是网络调度层
    类似volley, retrofit, android-async-http
    做具体业务请求、线程切换、数据转换

    OkHttp是网络执行层
    类似HttpClient, HttpUrlConnection
    做底层网络请求

    Q2.为什么用Retrofit?
    因为Retrofit有:
    CallAdapter-请求适配器
    可以实现多种请求响应形式:同步方式、异步回调方式、RxJava方式
    Converter-数据转换器
    可以自己定义responseBodyConverter和requestBodyConverter,实现加密功能和各种奇葩格式的解析

    3.Retrofit流程分析

    以下分析基于compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
    1.先看我们初始化时的Retrofit.create()方法


    这里用到了动态代理,忘记了的话,可以先看我的博客:Java-动态代理

    2.通过loadMethodHandler(),创建了MethodHandler


    3.进去看下MethodHandler.create()


    4.在MethodHandler.create()方法中,创建了CallAdapter


    5.在MethodHandler.create()方法中,创建了responseConverter和requestFactory,在parse()中解析了注解信息


    6.回到Retrofit类,看invoke()方法,



    adapte()方法只是一个抽象方法


    7.CallAdapter有多种实现,为简单起见,只看ExecutorCallAdapterFactory中对adapter的实现


    Paste_Image.png

    8.在ExecutorCallbackCall.enqueue()方法中,


    9.delegate.enqueue()是一个抽象方法


    实现在OkhttpCall.queue()中,方法太长,截图没截完


    继续看OkhttpCall.enqueue()方法,这里就是具体执行网络请求的地方,将Okhttp.Callback转换成了一个Retrofit.Callback
    为什么有两种Callback?因为一个是网络执行层的Callback,一个是网络调度层的Callback


    10.这里是如何创建Request的呢?看rawCall的创建方法,通过requestFactory将args转成Request,通过callFactory将request转成Okhttp3.Call
    为什么有两种Call?因为一个是网络执行层的Call,一个是网络调度层的Call


    11.好了,发起网络请求搞定,然后网络响应值是如何解析的呢?
    看onRespone回调中的parseResponse()


    12.点进蓝色的responseConverter.convert(catchingBody)



    又是接口,实现在这:


    好了,流程分析已经大致搞定了,不过这里通过requestBodyConverter用注解创建Requestbody的过程,还是没找到调用的地方,以后再来找下。

    参考目录


    1. Retrofit分析-漂亮的解耦套路
    2. OkHttp, Retrofit, Volley应该选择哪一个?

    相关文章

      网友评论

      本文标题:Retrofit基本用法和流程分析

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