• 在之前的项目中一直都用着比较老的网络框架,比如volly,okgo,okhttp等等,平时写demo 的时候偶尔也会用到新的框架拿来练练手,这两天写了一个关于retrofit2的案例,分享出来。 大牛们恐怕已经写到烂的了,有不足...

    在之前的项目中一直都用着比较老的网络框架,比如volly,okgo,okhttp等等,平时写demo 的时候偶尔也会用到新的框架拿来练练手,这两天写了一个关于retrofit2的案例,分享出来。

    大牛们恐怕已经写到烂的了,有不足请多多指教。

    demo开始前,先导入retrofit、rxjava相关的jar
    project中的build.gradle中添加:

        // Retrofit库
        compile 'com.squareup.retrofit2:retrofit:2.3.0'
        compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
        // gson解析,可以自行替换
        compile 'com.squareup.retrofit2:converter-gson:2.3.0'
        compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
        // 日志的拦截器,也可以自行选择
        compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
        compile 'io.reactivex.rxjava2:rxjava:2.0.1'
        compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    

    由于retrofit底层是okhttp实现的,所以导入retrofit的时候已经自动帮你导入了OKHttp3的jar包。

    工程利用MVP的模式去写,项目结构:
    项目结构

    项目结构中dialog包下有一个ProgressHUD.java类,这个是用来请求网络时加载的对话框,使用简单方便,加入包:

    	//加载对话框
        compile 'com.kaopiz:kprogresshud:+'
    

    OK,先封装一个retrofit的请求入口,代码如下:

    package com.allen.retrofit2_rxjava2.utils;
    
    import com.allen.retrofit2_rxjava2.ApiAddress;
    import com.allen.retrofit2_rxjava2.app.MyApp;
    import com.allen.retrofit2_rxjava2.network.AllApi;
    
    import retrofit2.Retrofit;
    import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
    import retrofit2.converter.gson.GsonConverterFactory;
    
    /**
     * @author: Allen.
     * @date: 2018/7/25
     * @description: retrofit请求工具类
     */
    
    public class RetrofitUtil {
        /**
         * 超时时间
         */
        private static volatile RetrofitUtil mInstance;
        private AllApi allApi;
    
        /**
         * 单例封装
         *
         * @return
         */
        public static RetrofitUtil getInstance() {
            if (mInstance == null) {
                synchronized (RetrofitUtil.class) {
                    if (mInstance == null) {
                        mInstance = new RetrofitUtil();
                    }
                }
            }
            return mInstance;
        }
    
        /**
         * 初始化Retrofit
         */
        public AllApi initRetrofit() {
                Retrofit mRetrofit = new Retrofit.Builder()
                        .client(MyApp.initOKHttp())
                        // 设置请求的域名
                        .baseUrl(ApiAddress.api)
                        // 设置解析转换工厂
                        .addConverterFactory(GsonConverterFactory.create())
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .build();
            return mRetrofit.create(AllApi.class);
        }
    }
    
    

    在Application中初始OKHttpClient 对象,因为有时候每次请求接口的时候都重新去new一个client,在后台接口中可能会导致多个session去请求,导致session失效一直无法请求成功。
    MyApp.java

    package com.allen.retrofit2_rxjava2.app;
    
    import android.app.Application;
    
    import com.allen.retrofit2_rxjava2.network.CookieReadInterceptor;
    import com.allen.retrofit2_rxjava2.network.CookiesSaveInterceptor;
    import com.allen.retrofit2_rxjava2.utils.InterceptorUtil;
    
    import java.util.concurrent.TimeUnit;
    
    import okhttp3.OkHttpClient;
    
    /**
     * @author: Allen.
     * @date: 2018/7/25
     * @description: application
     */
    
    public class MyApp extends Application {
        public static MyApp myApp;
        public static final int TIMEOUT = 60;
        private static OkHttpClient mOkHttpClient;
    
        @Override
        public void onCreate() {
            super.onCreate();
            myApp = this;
        }
    
        /**
         * 全局httpclient
         *
         * @return
         */
        public static OkHttpClient initOKHttp() {
            if (mOkHttpClient == null) {
                mOkHttpClient = new OkHttpClient.Builder()
                        .connectTimeout(TIMEOUT, TimeUnit.SECONDS)//设置连接超时时间
                        .readTimeout(TIMEOUT, TimeUnit.SECONDS)//设置读取超时时间
                        .writeTimeout(TIMEOUT, TimeUnit.SECONDS)//设置写入超时时间
                        .addInterceptor(InterceptorUtil.LogInterceptor())//添加日志拦截器
                        //cookie
                        .addInterceptor(new CookieReadInterceptor())
                        .addInterceptor(new CookiesSaveInterceptor())
                        .build();
            }
            return mOkHttpClient;
        }
    
    }
    
    

    这里说明一下,方便理解后面的代码,.addInterceptor(InterceptorUtil.LogInterceptor())//添加日志拦截器 是请求的日志拦截器,当请求一个api,传的参数,提交方式*(POST or GET…),请求头等信息都会打印出来。

     //cookie
     .addInterceptor(new CookieReadInterceptor())
     .addInterceptor(new CookiesSaveInterceptor())
    

    ####这个拦截器是请求图片验证码的时候,把该请求头的cookie 读取之后保存起来,下次请求登录接口时 header 带上该cookie,不然会一直提示验证码错误,这是个坑,要注意。

    写api接口,AllApi.java:

    package com.allen.retrofit2_rxjava2.network;
    
    import com.allen.retrofit2_rxjava2.ApiAddress;
    import com.allen.retrofit2_rxjava2.base.BaseEntry;
    import com.allen.retrofit2_rxjava2.bean.Banner;
    import com.allen.retrofit2_rxjava2.bean.Login;
    import com.allen.retrofit2_rxjava2.bean.ZiXunAll;
    
    import java.util.List;
    import java.util.Map;
    
    import io.reactivex.Observable;
    import okhttp3.ResponseBody;
    import retrofit2.http.Body;
    import retrofit2.http.GET;
    import retrofit2.http.POST;
    
    /**
     * @author: Allen.
     * @date: 2018/7/25
     * @description:
     */
    
    public interface AllApi {
    
        /**
         * 获取banner
         */
        @GET(ApiAddress.getBannerList)
        Observable<BaseEntry<List<Banner>>> getBanner();
    
        /**
         * 最新资讯
         */
        @GET(ApiAddress.getZixunList)
        Observable<BaseEntry<List<ZiXunAll>>> getZixunData();
    
        /**
         * 获取图片验证码
         */
        @GET(ApiAddress.getVerifyCode)
        Observable<ResponseBody> getVerityCode();
    
        /**
         * 登录
         */
        @POST(ApiAddress.userLogin)
        Observable<BaseEntry<Login>> userLogin(@Body Map<String,String> maps);
    }
    
    

    实体bean 就不贴出来了,最后大家可以去下载demo。
    简单写MainActivity中的module接口

    package com.allen.retrofit2_rxjava2.module;
    
    import android.graphics.Bitmap;
    
    import com.allen.retrofit2_rxjava2.base.BasePresenter;
    import com.allen.retrofit2_rxjava2.base.BaseView;
    
    /**
     * @author: Allen.
     * @date: 2018/7/25
     * @description:
     */
    
    public interface MainContract {
        interface View extends BaseView<presenter> {
            void setContent(String content);  //设置内容
    
            void setCode(Bitmap value);  //设置验证码
        }
    
        interface presenter extends BasePresenter{
            void getCode(); //获取验证码
    
            void userLogin(String user,String pwd,String code); //登录
    
            void getBannerData();  //banner
    
            void getLiveData();   //资讯信息
        }
    }
    
    

    Presenter去实现业务如下:

    package com.allen.retrofit2_rxjava2.presenter;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    
    import com.allen.retrofit2_rxjava2.base.BaseEntry;
    import com.allen.retrofit2_rxjava2.base.BaseObserver;
    import com.allen.retrofit2_rxjava2.bean.Banner;
    import com.allen.retrofit2_rxjava2.bean.Login;
    import com.allen.retrofit2_rxjava2.bean.ZiXunAll;
    import com.allen.retrofit2_rxjava2.module.MainContract;
    import com.allen.retrofit2_rxjava2.utils.MainUtil;
    import com.allen.retrofit2_rxjava2.utils.RetrofitUtil;
    
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import io.reactivex.Observer;
    import io.reactivex.android.schedulers.AndroidSchedulers;
    import io.reactivex.disposables.Disposable;
    import io.reactivex.schedulers.Schedulers;
    import okhttp3.ResponseBody;
    
    
    /**
     * @author: Allen.
     * @date: 2018/7/25
     * @description:
     */
    
    public class MainPresenter implements MainContract.presenter {
    
        private Context context;
        private MainContract.View view;
    
        public MainPresenter(Context context, MainContract.View view) {
            this.context = context;
            this.view = view;
        }
    
        /**
         * 图片验证码
         */
        @Override
        public void getCode() {
            RetrofitUtil.getInstance().initRetrofit().getVerityCode().subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<ResponseBody>() {
                @Override
                public void onSubscribe(Disposable d) {
                }
    
                @Override
                public void onNext(ResponseBody value) {
                    InputStream is=value.byteStream();
                    Bitmap bitmap = BitmapFactory.decodeStream(is);
                    view.setCode(bitmap);
                }
    
                @Override
                public void onError(Throwable e) {
                    view.setContent("失败了----->"+e.getMessage());
                }
    
                @Override
                public void onComplete() {
                }
            });
        }
    
        /**
         * 登录
         * @param user
         * @param pwd
         * @param code
         */
        @Override
        public void userLogin(String user, String pwd, String code) {
            Map<String,String> map=new HashMap<>();
            map.put("userName",user);
            map.put("userPwd",pwd);
            map.put("verifyCode",code);
            RetrofitUtil.getInstance().initRetrofit().userLogin(map)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new BaseObserver<Login>(context,MainUtil.loadLogin) {
                        @Override
                        protected void onSuccees(BaseEntry<Login> t) throws Exception {
                           if(t.isSuccess()){
                               view.setContent("Hello---->"+t.getData().getName());
                           }else {
                               view.setContent("----->"+t.getMessage());
                           }
                        }
    
                        @Override
                        protected void onFailure(Throwable e, boolean isNetWorkError) throws Exception {
                            view.setContent("失败了----->"+e.getMessage());
                        }
                    });
        }
    
        /**
         * 获取banner
         */
        @Override
        public void getBannerData() {
            RetrofitUtil.getInstance().initRetrofit().getBanner()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new BaseObserver<List<Banner>>(context,MainUtil.loadTxt) {
                        @Override
                        protected void onSuccees(BaseEntry<List<Banner>> t) throws Exception {
                            MainUtil.printLogger(t.getData().get(0).getTitle());
                            view.setContent(t.getData().get(0).getContent());
                        }
    
    
                        @Override
                        protected void onFailure(Throwable e, boolean isNetWorkError) throws Exception {
                            view.setContent("失败了----->"+e.getMessage());
                        }
                    });
        }
    
        /**
         * 获取资讯
         */
        @Override
        public void getLiveData() {
            RetrofitUtil.getInstance().initRetrofit().getZixunData()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new BaseObserver<List<ZiXunAll>>(context,MainUtil.loadTxt) {
                        @Override
                        protected void onSuccees(BaseEntry<List<ZiXunAll>> t) throws Exception {
                            view.setContent("标题:" + t.getData().get(0).getTitle());
                        }
    
                        @Override
                        protected void onFailure(Throwable e, boolean isNetWorkError) throws Exception {
                            view.setContent("失败了----->"+e.getMessage());
                        }
                    });
        }
    }
    
    

    BaseObserver是自定义的,实现Observer,只要请求成功,失败接口就行,代码:

    package com.allen.retrofit2_rxjava2.base;
    
    import android.accounts.NetworkErrorException;
    import android.content.Context;
    
    import com.allen.retrofit2_rxjava2.dialog.ProgressHUD;
    import com.kaopiz.kprogresshud.KProgressHUD;
    
    import java.net.ConnectException;
    import java.net.UnknownHostException;
    import java.util.concurrent.TimeoutException;
    
    import io.reactivex.Observer;
    import io.reactivex.disposables.Disposable;
    
    /**
     * @author: Allen.
     * @date: 2018/7/25
     * @description: 自定义Observer
     */
    
    public abstract class BaseObserver<T> implements Observer<BaseEntry<T>> {
        protected Context mContext;
        private KProgressHUD progressHUD;
        private String labelTxt;
    
        public BaseObserver(Context cxt, String text) {
            this.mContext = cxt;
            this.labelTxt = text;
            progressHUD = ProgressHUD.show(mContext);
        }
    
        //开始
        @Override
        public void onSubscribe(Disposable d) {
            onRequestStart();
        }
    
        //获取数据
        @Override
        public void onNext(BaseEntry<T> tBaseEntity) {
            try {
                onSuccees(tBaseEntity);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        //失败
        @Override
        public void onError(Throwable e) {
            onRequestEnd();
            try {
                if (e instanceof ConnectException
                        || e instanceof TimeoutException
                        || e instanceof NetworkErrorException
                        || e instanceof UnknownHostException) {
                    onFailure(e, true);  //网络错误
                } else {
                    onFailure(e, false);
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    
        //结束
        @Override
        public void onComplete() {
            onRequestEnd();//请求结束
        }
    
        /**
         * 返回成功
         *
         * @param t
         * @throws Exception
         */
        protected abstract void onSuccees(BaseEntry<T> t) throws Exception;
    
    
        /**
         * 返回失败
         *
         * @param e
         * @param isNetWorkError 是否是网络错误
         * @throws Exception
         */
        protected abstract void onFailure(Throwable e, boolean isNetWorkError) throws Exception;
    
        protected void onRequestStart() {
            if (progressHUD != null) {
                progressHUD.setLabel(labelTxt);
            }
        }
    
        protected void onRequestEnd() {
            if (progressHUD != null) {
                progressHUD.dismiss();
                progressHUD = null;
            }
        }
    
    }
    
    

    然后再贴出MainActivity的代码:

    package com.allen.retrofit2_rxjava2;
    
    import android.graphics.Bitmap;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.text.TextUtils;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import com.allen.retrofit2_rxjava2.module.MainContract;
    import com.allen.retrofit2_rxjava2.presenter.MainPresenter;
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    import butterknife.OnClick;
    
    public class MainActivity extends AppCompatActivity implements MainContract.View {
        private MainPresenter presenter;
    
        @BindView(R.id.btn_login)
        Button btn_login;
    
        @BindView(R.id.btn_banner)
        Button btn_banner;
    
        @BindView(R.id.btn_zixun)
        Button btn_zixun;
    
        @BindView(R.id.et_code)
        EditText et_code;
    
        @BindView(R.id.iv_code)
        ImageView iv_code;
    
        @BindView(R.id.tv_content)
        TextView tv_content;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
            presenter = new MainPresenter(this, this);
            presenter.getCode(); //获取图片验证码
        }
    
        @OnClick({R.id.btn_login, R.id.btn_banner, R.id.btn_zixun, R.id.iv_code})
        public void clickBtn(View view) {
            String code = et_code.getText().toString().trim();
            switch (view.getId()) {
                case R.id.btn_login:
                    presenter.userLogin("allen234", "allen234", code);
                    break;
                case R.id.btn_banner:
                    presenter.getBannerData();
                    break;
                case R.id.btn_zixun:
                    presenter.getLiveData();
                    break;
                case R.id.iv_code:
                    presenter.getCode();
                    break;
            }
        }
    
    
        @Override
        public void setContent(String content) {
            if (!TextUtils.isEmpty(content)) {
                tv_content.setText(content);
            }
        }
    
        @Override
        public void setCode(Bitmap value) {
            //通过imageview,设置图片
            iv_code.setImageBitmap(value);
        }
    }
    
    

    demo源码地址

    展开全文
  • 目前使用较为广泛的网络请求框架 MVP+Retrofit2+okhttp3+Rxjava2,我于2017年也加入了使用行列,在网上找了许多案例,实际项目开发中解决了一些所谓的坑,总结了些内容与大家共享一下。 1.什么是MVP? 在图中有三...

    一.介绍

    目前使用较为广泛的网络请求框架 MVP+Retrofit2+okhttp3+Rxjava2,我于2017年也加入了使用行列,在网上找了许多案例,实际项目开发中解决了一些所谓的坑,总结了些内容与大家共享一下。

    1.什么是MVP?

    在图中有三个模块view(界面),presenter(控制层),model(数据源)。他们在这个项目中中担任什么角色呢?

    2. MVP运行的过程

    • Model: 数据层,负责与网络层和数据库层的逻辑交互。
    • View: UI层,显示数据, 并向Presenter报告用户行为。
    • Presenter: 从Model拿数据,应用到UI层,管理UI的状态,响应用户的行为。
    •  用户在view层告诉presenter我要数据
    • presenter告诉model我要数据
    • model访问网络得到了数据再通知presenter给你我取到的数据
    • presenter 处理好数据 再把数据传递给view
    • 最后view将拿到的数据显示出来给用户观看

    3.MVP和MVC的区别

     

         MVC首先就是理解比较容易,技术含量不高,这对开发和维护来说成本较低也易于维护与修改。表现层与业务层分离各司其职,对开发来说很有利,但是MVC的每个构件在使用之前都需要经过彻底的测试,代码难以复用。

         在MVP里,Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现,而且Presenter与具体的view是没有一点关联的,而是通过定义好的接口进行交互,从而使得在变更View的同时可以保持Presenter不变,可以复用。

           在MVP模式里,View只应该有简单的Set/Get方法,用户输入和设置显示的内容,除此不应该有更多的内容,绝不允许直接访问Model,这就是与MVC最大的不同之处。

    二.框架的搭建

    1.搭建框架的依赖

    采用Retrofit2+Rxjava2+Rxandroid+okhttp3 搭建网络请求框架

    implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'

    2.创建工具类:RetrofitUtils、OkHttp3Utils

    RetrofitUtils和OkHttp3Utils的特性:

    1. 使用okhttp3作为请求接口;
    2. 以观察者模式创建实例;
    3. 使用gson作为数据转换器;
    4. 添加各种拦截器,如日志拦截,请求头拦截,请求参数拦截等等
    5. 开启数据缓存,无网络时可从缓存读取数据;
    6. 辅助类静态方法获取OkHttp3Utils实例。

    详细代码如下:

    RetrofitUtils工具类封装

    封装可以设置多个BaseUrl,应对项目对接多业务方的需求

    public abstract class RetrofitUtils {
        private Retrofit mRetrofit = null;
        private Retrofit mRetrofit2 = null;
        private OkHttpClient mOkHttpClient;
    
        /**
         * 获取Retrofit对象
         *
         * @return
         */
        public Retrofit getRetrofit() {
            if (null == mRetrofit) {
                if (null == mOkHttpClient) {
                    OkHttp3Utils okHttp3Utils = new OkHttp3Utils();
                    mOkHttpClient = okHttp3Utils.getOkHttpClient();
                }
                mRetrofit = new Retrofit.Builder()
                        .baseUrl(BaseUrlUtil.BaseServiceUrl)
                        .addConverterFactory(new NullOnEmptyConverterFactory())
                        .addConverterFactory(GsonConverterFactory.create())
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .client(mOkHttpClient)
                        .build();
            }
            return mRetrofit;
        }
    
        /**
         * 获取Retrofit对象
         *这个主要是为了应对多个BaseUrl而准备的
         * @return
         */
        public Retrofit getRetrofit2() {
            if (null == mRetrofit2) {
                if (null == mOkHttpClient) {
                    OkHttp3Utils okHttp3Utils = new OkHttp3Utils();
                    mOkHttpClient = okHttp3Utils.getOkHttpClient();
                }
                mRetrofit2 = new Retrofit.Builder()
                        .baseUrl(BaseUrlUtil.BaseServiceUrl2)
                        .addConverterFactory(new NullOnEmptyConverterFactory())
                        .addConverterFactory(GsonConverterFactory.create())
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .client(mOkHttpClient)
                        .build();
            }
            return mRetrofit2;
        }
    
    
        public class NullOnEmptyConverterFactory extends Converter.Factory {
            @Override
            public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
                final Converter<ResponseBody, ?> delegate = retrofit.nextResponseBodyConverter(this, type, annotations);
                return new Converter<ResponseBody, Object>() {
                    @Override
                    public Object convert(ResponseBody body) throws IOException {
                        if (body.contentLength() == 0) return null;
                        return delegate.convert(body);
                    }
                };
            }
        }
    
    }

     OkHttp3Utils工具类封装

    自定义拦截器,可以按照自己的需求设置请求头的参数,同时对cookies做了自动化管理,对cookers管理更方便

    public class OkHttp3Utils {
        private OkHttpClient mOkHttpClient;
        Activity activity = AppManager.topActivity();
        private Handler updateHandler = new Handler() {
            @Override
            public void dispatchMessage(Message msg) {
                super.dispatchMessage(msg);
                if (msg.what == 401) {
                    //401 token失效
                    if (activity != null && !activity.isDestroyed()) {
                        try {
                            PreferenceHelper.write(PreferenceHelper.DEFAULT_FILE_NAME, AppConfig.PREFER_TOKEN_TAG, "");
                            DialogView dialogView = new DialogView(activity, 180, 180, R.layout.my_dialog, R.style.dialog) {
                                @Override
                                public void isdismiss(int tag) {
                                    if (tag == DialogView.CANCEL_BUTTON_CLICK) {
    
                                    }
                                }
                            };
                            dialogView.showdialog2("温馨提示", "登录失效,请重新登录", "去登录", "");
                        } catch (Exception es) {
                            es.printStackTrace();
                        }
                    }
                } else if (msg.what == 300) {
                    Toast.makeText(activity, "暂无网络", Toast.LENGTH_SHORT).show();
                }
            }
        };
    
        //设置缓存目录
        private File cacheDirectory = new File(MyApplication.getInstance().getApplicationContext().getCacheDir().getAbsolutePath(), "MyCache");
        private Cache cache = new Cache(cacheDirectory, 10 * 1024 * 1024);
    
        /**
         * 获取OkHttpClient对象
         *
         * @return
         */
        public OkHttpClient getOkHttpClient() {
    
            if (null == mOkHttpClient) {
    
                //同样okhttp3后也使用build设计模式
                mOkHttpClient = new OkHttpClient.Builder()
                        //添加拦截器
                        .addInterceptor(new MyIntercepter())
                        //设置一个自动管理cookies的管理器
                        .cookieJar(new CookiesManager())
                        //添加网络连接器
    //                    .addNetworkInterceptor(new CookiesInterceptor(MyApplication.getInstance().getApplicationContext()))
                        //设置请求读写的超时时间
                        .connectTimeout(30, TimeUnit.SECONDS)
                        .writeTimeout(30, TimeUnit.SECONDS)
                        .readTimeout(30, TimeUnit.SECONDS)
                        .cache(cache)//设置缓存
                        .retryOnConnectionFailure(true)//自动重试
                        .build();
            }
            return mOkHttpClient;
        }
    
        /**
         * 拦截器
         */
        private class MyIntercepter implements Interceptor {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
    
                if (!isNetworkReachable(MyApplication.instance.getApplicationContext())) {
                    updateHandler.sendEmptyMessage(300);
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)//无网络时只从缓存中读取
                            .build();
                }
                Request.Builder RequestBuilder = request.newBuilder();
                Request build;
    
                build = RequestBuilder
                        .removeHeader("User-Agent")
                        .addHeader("User-Agent", getUserAgent())
                        .addHeader("Authorization", "")
                        .build();
    
                Response response = chain.proceed(build);
                int code = response.code();
                //对个别链接地址做处理
                HttpUrl url = response.request().url();
                System.out.println("我的网址"+url);
                updateHandler.sendEmptyMessage(code);
                if (code == 401) {
                    //跳转到登录页面
                    updateHandler.sendEmptyMessage(401);
                } else if (code == 402) {
                    //跳转到开户审核中界面
                    updateHandler.sendEmptyMessage(402);
                } else if (code == 403) {
                    //跳转到开户界面
                    updateHandler.sendEmptyMessage(403);
                }
                return response;
            }
        }
    
        private static String getUserAgent() {
            String userAgent = "";
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                try {
                    userAgent = WebSettings.getDefaultUserAgent(MyApplication.getInstance().getApplicationContext());
                } catch (Exception e) {
                    userAgent = System.getProperty("http.agent");
                }
            } else {
                userAgent = System.getProperty("http.agent");
            }
            StringBuffer sb = new StringBuffer();
            for (int i = 0, length = userAgent.length(); i < length; i++) {
                char c = userAgent.charAt(i);
                if (c <= '\u001f' || c >= '\u007f') {
                    sb.append(String.format("\\u%04x", (int) c));
                } else {
                    sb.append(c);
                }
            }
            return sb.toString();
        }
    
        /**
         * 自动管理Cookies
         */
        private class CookiesManager implements CookieJar {
            private final PersistentCookieStore cookieStore = new PersistentCookieStore(MyApplication.getInstance().getApplicationContext());
    
            @Override
            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                if (cookies != null && cookies.size() > 0) {
                    for (Cookie item : cookies) {
                        cookieStore.add(url, item);
                    }
                }
            }
    
            @Override
            public List<Cookie> loadForRequest(HttpUrl url) {
                List<Cookie> cookies = cookieStore.get(url);
                return cookies;
            }
        }
    
        /**
         * 判断网络是否可用
         *
         * @param context Context对象
         */
        @RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE)
        public Boolean isNetworkReachable(Context context) {
            ConnectivityManager cm = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo current = cm.getActiveNetworkInfo();
            if (current == null) {
                return false;
            }
            return (current.isAvailable());
        }
    }

     线程切换操作的封装

    public class BaseNetWork extends RetrofitUtils{
    
        /**https://github.com/r17171709/Retrofit2Demo
         * 插入观察者
         * @param observable
         * @param observer
         * @param <T>
         */
        public  <T> void setSubscribe(Observable<T> observable, Observer<T> observer) {
            observable.subscribeOn(Schedulers.io())
                    .subscribeOn(Schedulers.newThread())//子线程访问网络
                    .observeOn(AndroidSchedulers.mainThread())//回调到主线程
                    .subscribe(observer);
        }
    }

    下面就是实体接口的调用

    public class UserNetWork extends BaseNetWork {
    
        protected final NetService service = getRetrofit().create(NetService.class);
    
        private interface NetService {
    
            //获取首页轮播图
            @GET("api/AppPubilc/get_lunbotu")
            Observable<LunBoTuEntity> toGetLunBoTuEntity();
    
        }
    
        //首页轮播图
        public void toGetLunBoTuEntity(Observer<LunBoTuEntity> observer) {
            setSubscribe(service.toGetLunBoTuEntity(), observer);
        }
    
    }

    以上就是Retrofit2+Rxjava2+Rxandroid+okhttp3的高度封装的网络框架,自定义拦截器可以拦截请求地址,动态添加请求头里的参数,同时对网络请求响应code码做相应的操作。面对一个项目对接多个业务方,存在多个BaseUrl,该网络框架封装了可以设置多个BaseUrl的。

    那么Retrofit2网络框架的网络框架搭建完了,下面来看一下MVP架构的设计吧,不要走开!

    下面是项目的整体架构图

    创建BaseView基类,用于添加自定义回调,根据需求可做扩展,此处只封装了些最为常用的方法

    public interface BaseView {
    
        void showLoadingDialog(String msg);
    
        void dismissLoadingDialog();
        /**
         * 显示错误信息
         *
         * @param msg
         */
        void showError(String msg);
        /**
         * 错误码
         */
        void onErrorCode(BaseModel model);
    }

     创建Presenter基类,提供M层和V层通讯桥梁

    public interface BasePresenter {
        //默认初始化
        void start();
    
        //Activity关闭把view对象置为空
        void detach();
    
        //将网络请求的每一个disposable添加进入CompositeDisposable,再退出时候一并注销
        void addDisposable(Disposable subscription);
    
        //注销所有请求
        void unDisposable();
    
    }

    创建一个PresenterImpl,用于统一处理网络请求的生命周期,在activity退出时统一注销观察者模式,解绑观察者的情况下调用unDisposable()统一解绑,防止Rx造成的内存泄漏。

    /**
     * 总控制层
     * @param <V>
     */
    public abstract class BasePresenterImpl<V extends BaseView> implements BasePresenter {
        protected V view;
        public BasePresenterImpl(V view) {
            this.view = view;
            start();
        }
    
        @Override
        public void detach() {
            this.view = null;
            unDisposable();
        }
    
        @Override
        public void start() {
    
        }
    
    
        //将所有正在处理的Subscription都添加到CompositeSubscription中。统一退出的时候注销观察
        private CompositeDisposable mCompositeDisposable;
    
        /**
         * 将Disposable添加
         *
         * @param subscription
         */
        @Override
        public void addDisposable(Disposable subscription) {
            //csb 如果解绑了的话添加 sb 需要新的实例否则绑定时无效的
            if (mCompositeDisposable == null || mCompositeDisposable.isDisposed()) {
                mCompositeDisposable = new CompositeDisposable();
            }
            mCompositeDisposable.add(subscription);
        }
    
        /**
         * 在界面退出等需要解绑观察者的情况下调用此方法统一解绑,防止Rx造成的内存泄漏
         */
        @Override
        public void unDisposable() {
            if (mCompositeDisposable != null) {
                mCompositeDisposable.dispose();
            }
        }
    
    }
    

    创建实体类基类,统一处理后台接口返回的数据,做统一处理

    public class TradeSimpleResult implements Serializable{
    
      /**
       * Success : false
       * StatusCode : 500
       * Message : 处理失败
       * ErrorInfo : {"ErrorMessage":"请输入真实的身份证姓名信息","ErrorCode":"-1"}
       */
    
      private boolean Success;
      private int StatusCode;
      private String Message;
      private ErrorInfoBean ErrorInfo;
    
      public boolean isSuccess() {
        return Success;
      }
    
      public void setSuccess(boolean Success) {
        this.Success = Success;
      }
    
      public int getStatusCode() {
        return StatusCode;
      }
    
      public void setStatusCode(int StatusCode) {
        this.StatusCode = StatusCode;
      }
    
      public String getMessage() {
        return Message;
      }
    
      public void setMessage(String Message) {
        this.Message = Message;
      }
    
      public ErrorInfoBean getErrorInfo() {
        return ErrorInfo;
      }
    
      public void setErrorInfo(ErrorInfoBean ErrorInfo) {
        this.ErrorInfo = ErrorInfo;
      }
    
      public static class ErrorInfoBean {
        /**
         * ErrorMessage : 请输入真实的身份证姓名信息
         * ErrorCode : -1
         */
    
        private String ErrorMessage;
        private String ErrorCode;
    
        public String getErrorMessage() {
          return ErrorMessage;
        }
    
        public void setErrorMessage(String ErrorMessage) {
          this.ErrorMessage = ErrorMessage;
        }
    
        public String getErrorCode() {
          return ErrorCode;
        }
    
        public void setErrorCode(String ErrorCode) {
          this.ErrorCode = ErrorCode;
        }
      }
    }

    好了,以上就是MVP架构的搭建以及接口返回数据的统一处理。代码比较多,但是前后逻辑是很连贯的。那么下面就来做一个实际的接口请求看看效果。

    public class MainActivity extends LifecycleBaseActivity<TestContact.presenter> implements TestContact.view {
    
        private TextView textView;
        private HashMap<Object, Object> map;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            map = new HashMap<>();
            initView();
            initData();
    
        }
    
        private void initData() {
            presenter.getData(map, "first");
        }
    
        private void initView() {
            textView = (TextView) findViewById(R.id.main_text);
        }
    
        /**
         * 初始化presenter
         *
         * @return 对应的presenter
         */
        @Override
        public TestContact.presenter initPresenter() {
            return new TestPresenter(this, MainActivity.this);
        }
    
        /**
         * 设置数据
         * 刷新界面
         *
         * @param lunBoTuEntity 数据源
         */
        @Override
        public void setData(LunBoTuEntity lunBoTuEntity, String tag) {
            if ("LunBoTu".equals(tag)) {
                String imageUrl = lunBoTuEntity.getResult().getList().get(0).getImageUrl();
                System.out.println("图片地址:" + imageUrl);
            }
        }
    
        @Override
        public void ErrorData(Throwable e) {
    
        }
    
        @Override
        public void showLoadingDialog(String msg) {
            textView.setText(msg);
        }
    
        @Override
        public void dismissLoadingDialog() {
    
        }
    
    }
    

    以上的LifecycleBaseActivity 和 LifecycleBaseFragment大家可以在下面的链接地址里面去看,这个是Goolge官方架构AAC(Android Architecture Component)的生命周期管理框架,Lifecycle类持有Activity 或 Fragment等组件的生命周期信息,并且允许其他对象观察这些信息。Lifecycle内部使用了两个枚举来跟踪其关联组件的生命周期状态:Event和State。祥见下面分析。可以通过调用Lifecycle类的 addObserver() 方法来添加观察者,如下

      getLifecycle().addObserver(new TestLifeCycle());

    我在LifecycleBaseActivity做了部分处理,使用起来更加的便捷、易懂。

    现在Retrofit2+Rxjava2+Rxandroid+okhttp3+Lifecycle 的MVP网络框架,结合了Google官方AAC框架,实现APP生命周期的管理整体架构就做好了,文章里涉及带网络框架、MVP架构和生命周期的管理,那么一套完整的App框架就搭建好了。

    2019.05.09功能新增:

    1.新增token过期自动刷新token,刷新后再请求一次接口的功能

    github地址: https://github.com/zengweitao/Treasure

    简书地址:https://www.jianshu.com/p/ac0eeadb6151

    源码下载地址

    展开全文
  • 今天要说的干货是:以Kotlin,在MVP模式下(OKHttp和 Retrofit+RxJava)网络请求两种实现方式的一个小案例,希望对大家有所帮助,效果图:     Retrofit是Square公司开发的一款针对Android网络请求的一个当前很...

    今天要说的干货是:以Kotlin,在MVP模式下(OKHttp和 Retrofit+RxJava)网络请求两种实现方式的一个小案例,希望对大家有所帮助,效果图:

              

     
    Retrofit是Square公司开发的一款针对Android网络请求的一个当前很流行的网络请求库。可参考博客看详细介绍:Android开发之Retrofit+RxJava的使用

    完成以上功能需引入:

     

        compile "com.android.support:appcompat-v7:$support_version"
        compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
        compile "org.jetbrains.anko:anko-common:$anko_version"
        compile 'com.zhy:okhttputils:2.6.2'
        compile 'com.alibaba:fastjson:1.1.54.android'
        compile 'com.squareup.retrofit2:retrofit:2.1.0'
        compile 'com.squareup.retrofit2:converter-gson:2.1.0'
        compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
        compile 'io.reactivex:rxandroid:1.2.1'
        compile 'io.reactivex:rxjava:1.1.6'

    先来看看 Activity

    MvpOkHttpActivity.Java

    class MvpOkHttpActivity : BaseActivity<IView,PresenterEmlpe>(),IView {
    
        override fun setMainLayout(): Int {
            return R.layout.activity_mvp_ok_http
        }
    
        override fun createPresenter(): PresenterEmlpe {
            return PresenterEmlpe()
        }
    
        override fun initView() {
            text.text="加载中......"
        }
    
        override fun initBeforeData() {
          btn.setOnClickListener {
              p!!.onRequest(Api.showRequestData("15","5"))
          }
        }
    
        override fun onLoadContributorStart() {
            toast("加载中......")
        }
    
        override fun onLoadContributorComplete(data: String) {
            Log.i("data",data)
            toast(data)
            //解析数据
            val entityTitle = JSON.parseObject(data, EntityTitle::class.java)
            if (entityTitle.data != null){
                text.text=entityTitle!!.data!!.get(0).title
            }
    
        }
    
        override fun onNetWrok() {
            toast("网络未连接")
        }
    
        override fun onError(error: String) {
            toast(error)
        }
    
    }

    可见代码是相当比较少的,以MVP模式来完成的,主要有Model,Presenter,View

     

    Model:

    class ModelEmlpe : IMode{
    
        override fun onRequest(url: String, map: Map<String, String>,callBackListenter: IMode.CallBackListenter) {
    
            OkHttpUtils.post().url(url).params(map).build().execute(object : StringCallback() {
                override fun onError(call: okhttp3.Call, e: Exception, id: Int) {
                    callBackListenter.onError("加载数据失败")
                }
    
                override fun onResponse(response: String, id: Int) {
                    callBackListenter.onDataCallBackListenter(response)
                }
            })
        }
    }

    Presenter

    class PresenterEmlpe : BasePresenter<IView>(){
    
        var model: IMode? = null
        init {
            model = ModelEmlpe()
        }
        fun onRequest(map: Map<String,String>){
            var iView = getView()
            if (model != null && iView != null) {
    
                //验证网络  无网络不加载
                if (false){
                    iView.onNetWrok()
                    return
                }
                iView.onLoadContributorStart()//初始化
                model!!.onRequest(Api.url, map, object : IMode.CallBackListenter {
    
                    override fun onDataCallBackListenter(data: String) {
                       iView.onLoadContributorComplete(data)
    
                    }
                    override fun onError(error: String) {
                        iView.onError(error)
                    }
    
                })
            }
    
        }
    
        override fun detachView() {
            super.detachView()
            if (model != null){
                model = null
            }
        }
    
    
    }

    当然解析数据也可以不用在Activity中完成,可以在我们的Presenter或Model中完成也是可以的,

     

    我们的RxJava+Retrofit 提供了请求时就直接解析的功能,这点也可以好好运用。

     

    两种请求方式的Activity,Presenter和View 其实是差不多的,就是Model层 实现的方式不一样而已。

     

    由于代码太多,就不一一贴出来了,源码直接下载即可

     源码点击下载


    展开全文
  • Okhttp和retrofit是同一个开发公司开发的,而且retrofit就是依赖或者说就是为了Okhttp开发的,所以在项目中要想使用retrofit就必须同时引入Okhttp和retrofit两个库; rxjava前两个没有必然的联系,它是一个异步...

    三者关系:

    Okhttp和retrofit是同一个开发公司开发的,而且retrofit就是依赖或者说就是为了Okhttp开发的,所以在项目中要想使用retrofit就必须同时引入Okhttp和retrofit两个库;

    rxjava和前两个没有必然的联系,它是一个异步框架最大的优势就是他的异步和链式调用可以是代码层次清晰,因为以上两个优势所以受到欢迎;

    因此在Android项目中会把他们三个组合在一起优势互补达到一个更好的效果(代码的可读性,网络方法的优化,代码效率的优化等等)。

    写代码:

    1.引入:

    implementation("com.squareup.okhttp3:okhttp:3.12.0")
    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    implementation "io.reactivex.rxjava2:rxjava:2.2.3"

    版本号最好根据你的需要换成最新的;

    记得添加网络权限;

    2.Retrofit的添加:

    首先定义一个类RetrofitInstance,在这个类中添加方法内容如下

    OkHttpClient.Builder builder = new OkHttpClient.Builder()
            .addInterceptor(new RequestInterceptors())
            .addInterceptor(new ResponseInterceptors())
            .connectTimeout(Constant.NET_CONNECT_TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(Constant.NET_READ_TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(Constant.NET_WRITE_TIMEOUT, TimeUnit.SECONDS);
    OkHttpClient client = builder.build();
    
    Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
    retrofitBuilder.baseUrl(BuildConfig.BASE_URL)
            .client(client)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
            .addConverterFactory(GsonConverterFactory.create())
            .addConverterFactory(StringConverterFactory.create());
    retrofit = retrofitBuilder.build();

    Retrofit是依赖OKhttp的所以要先初始化一个OKhttp的对象,其中addInterceptor()是添加拦截对象,在拦截对象中可以对访问和返回数据进行处理(其实可以在一个对象中完成但是为了逻辑更清晰所以分在了两个对象中,之后会介绍拦截);

    设定几个时间限制,其中connectTimeout指的是链接超时的限制我们用的最多,readTimeout和writeTimeout分别是读取和写入超时,这个超时不是说读或写的时间过长,这两个值是说在读和写的过程中中断了的中断超时时间,以writeTimeout为例,在写入一个2M的数据时在写道1M的时候中断了,那最长等待时间就是writeTimeout,超过了这个设定的最长等待时间就算是超时了;

    baseUrl是连接时的基础链接,调取接口的时候会自动把接口的路径和接口名字拼到这个链接后面;
    client就是把okhttp绑定到retrofit上了;

    addCallAdapterFactory绑定适配器,这里绑定了rxjava;

    addConverterFactory实现对服务器返回数据的解析,converter需要自定义,GsonConverterFactory可以

    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'通过引入来解析json的数据,同时我在这里自定义了一个String的converter,自定义converter很简单 class xxx implements Converter<ResponseBody, String> 就可以;

    然后通过单例模式得到方法所在的对象来获取retrofit的对象;

    3.调用

    调用需要定义一个接口类,在这个接口类中定义接口方法;

    public interface InterfaceClass{
    
        @POST("xx/xxx/interfaceName")
        Observable<返回数据的接收对象> interfaceName();
    }

    这样我们就可以调用了,调用的方式是通过RetrofitInstance的单例模式获取retrofit,如语句一:

    语句一:RetrofitInstance.retrofit.creat(InterfaceClass.class).interfaceName

    其实还可以把上面这个语句简化但是这里为了说的明白一点这样了

    这样语句一返回的就是一个Observable对象可以用rxjava来处理返回的数据了

    RetrofitInstance.retrofit.creat(InterfaceClass.class).interfaceName.map().compose()等等

    rxjava就不多说了,推荐一个https://www.jianshu.com/p/0cd258eecf60

    这是最终我的引用

    implementation 'com.squareup.okhttp3:okhttp:3.12.0'
    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    implementation 'io.reactivex.rxjava2:rxjava:2.2.3'
    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
    api 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
    api 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

    版本号记得修改

    展开全文
  • Rxjava+retrofit2+OKHttp+GSON实践网络请求1 添加配置文件//retrofit compile 'com.squareup.retrofit2:retrofit:2.1.0' //Gson converter compile 'com.squareup.retrofit2:converter-gson:2.1.0' //RxJava2 ...

    Rxjava+retrofit2+OKHttp+GSON实践(新浪微博API调用实例)


    网络请求

    建议学习了以下知识才看这篇文章:
    OKHTTP3请参考:http://blog.csdn.net/weixin_37577039/article/details/78546444
    retrofit2 请参考:http://blog.csdn.net/weixin_37577039/article/details/78546591
    JSON解析:http://blog.csdn.net/weixin_37577039/article/details/78546482
    新浪微博JSON解析实践:http://blog.csdn.net/weixin_37577039/article/details/78619940
    Rxjava2请参考:http://blog.csdn.net/weixin_37577039/article/details/78555208


    1 添加配置文件,添加权限
    包一定要导对,这里是个坑

         //retrofit2
        compile 'com.squareup.retrofit2:retrofit:2.3.0'
        //Gson converter
        compile 'com.squareup.retrofit2:converter-gson:2.3.0'
        //RxJava2 Adapter
        compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
        //rxjava2
        compile 'io.reactivex.rxjava2:rxjava:2.1.5'
        //rxandroid2
        compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
        //okhttp
        compile 'com.squareup.okhttp3:okhttp:3.9.0'
        compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
        // 新浪微博SDK
        compile 'com.sina.weibo.sdk:core:4.1.0:openDefaultRelease@aar'

    有时候某个Sync不通过就try again试下


    AndroidManifest.xml中

    <uses-permission android:name="android.permission.INTERNET"/>

    当获得了AccessToken后,去调用API接口了 这里就要用Rxjava进行异步操作,上游执行网络请求,下游进行数据处理,UI更新


    这里将Observable为< ResponseBody>参数的
    其他参数为BEAN类的其实也一样
    将ResponseBody部分改为BEAN类即可

    @Override
    public void onNext(XXBean xxBean) {
    // 替换了那个call.enqueue方法 直接在这里进行获取
    Log.i("myAccessToken", xxBean.getXXX() );// 即可以得到BEAN类中对应的数据
    }
    //call对象声明
    private io.reactivex.Observable<AccessTokenBean> call_1;
    
    

    2 定义接口
    (retrofit2 负责部分,原retrofit2改call为Observable)

    public interface HttpService {
    //调用API
    @GET("2/statuses/home_timeline.json?")
    Observable<ResponseBody> getAPI(@Query("access_token") String accessToken, @Query("count") int count);
    
    }

    3 接着创建一个Retrofit客户端
    (retrofit2和okhttp3 原retrofit2增加了.addCallAdapterFactory)

    private Context mContext;
     public void createRetrofit(String accessToken,Context context){
            mContext=context;
            //OKHttp进行超时设置,拦截器等设置
            OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
            builder.readTimeout(10, TimeUnit.SECONDS);
            builder.connectTimeout(9, TimeUnit.SECONDS);
            if (BuildConfig.DEBUG) {
                HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                builder.addInterceptor(interceptor);
            }
     // 创建gson实例
        Gson gson = new GsonBuilder()
        //配置你的Gson
        .setDateFormat("yyyy-MM-dd hh:mm:ss")
        .create();
    //创建Retrofit实例
        Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(baseUrl)
        .client(builder.build())
        .addConverterFactory(GsonConverterFactory.create(gson))
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build();
    
    

    4 发送请求

    //先声明
    private Observable<ResponseBody> call_1;
    
    //用retrofit创建HttpService对象
            final HttpService httpService = retrofit.create(HttpService.class);
             // 接口调用
            call_1= httpService.getAPI(accessToken,COUNT);
            //!!!这里是一个坑!!!
            //这里可能会报错 说retrofit.call不能转化为io.reactivex.observable类型 按ALT+ENTER去选择最后一个,return httpService为io.reactivex.observable格式的(大概这个意思)就OK了
    
            // RXJAVA实现
            call_1.subscribeOn(Schedulers.io()) //在IO线程进行网络请求
                    .observeOn(AndroidSchedulers.mainThread())  //回到主线程去处理请求结果
                    .subscribe(new Observer<ResponseBody>() {
                        @Override
    // 连接成功了就会执行
      public void onSubscribe(Disposable d) {
          Log.i("subscribe is ok","subscribe is ok" );
      }
      @Override
      public void onNext(ResponseBody responseBody) {
          Toast.makeText(mContext, "调用API成功", Toast.LENGTH_SHORT).show();
          try {
              str=responseBody.string();
          } catch (IOException e) {
              e.printStackTrace();
          }
          Log.i("str",str);
          //开始解析
          try {
              // 将返回的JSONString格式赋予JSONObject
              JSONObject jsonObject = new JSONObject(str);
              // 第一层为statuses 并且statuses为数组形式 因此将其设置为JSONArray形式
              JSONArray statusesArr = jsonObject.getJSONArray("statuses");
              // 循环地去获得多条微博
              // 这里的index+1代表的是第n条status(微博),因此index=0 为第一条 以此类推
              for (int i = 0; i < COUNT; i++) {
                  // 第一条 下标从0开始
                  JSONObject statusesObj = statusesArr.getJSONObject(i);
                  // statuses中的第一层,即总的第二层
                  // 该条微博的创建时间
                  created_at[i] = statusesObj.getString("created_at");
                  Log.i("created_at", created_at[i]);
                  //该条微博的来源
                  source[i] = statusesObj.getString("source");
                  Log.i("source", source[i]);
                  //该条微博的转发数
                  reposts_count[i] = statusesObj.getString("reposts_count");
                  Log.i("reposts_count", reposts_count[i]);
                  //该条微博的评论数
                  comments_count[i] = statusesObj.getString("comments_count");
                  Log.i("comments_count", comments_count[i]);
                  //该条微博的点赞数
                  attitudes_count[i] = statusesObj.getString("attitudes_count");
                  Log.i("attitudes_count", attitudes_count[i]);
                  //该条微博的微博text内容
                  text[i] = statusesObj.getString("text");
                  Log.i("text", text[i]);
                  // 总的第三层
                  // 获取user的值
                  String user = statusesObj.getString("user");
                  //user转化为JSONObject
                  JSONObject userObj = new JSONObject(user); // 将其转化为JSONObject
                  //微博主名
                  screen_name[i] = userObj.getString("screen_name"); // 使用getXX方法获取数据
                  Log.i("screen_name", screen_name[i]);
                  //微博主照片的地址
                  profile_image_url[i] = userObj.getString("profile_image_url"); // 使用getXX方法获取数据
                  Log.i("profile_image_url", profile_image_url[i]);
              }
              // 若成功传入最后一个微博 指定一个变量 而不是只是一个数值 因为网络请求要花时间
              if(profile_image_url[COUNT-1]!=null){
                  //若有值
                  canIntent=true;
                  // 非Activity中跳转 满足MVVM吗  不满足要改~~~~~~
                  Intent intent = new Intent(mContext, MainActivity.class);
                  mContext.startActivity(intent);
              }else{
                  canIntent=false;
              }
          } catch(JSONException e){
              e.printStackTrace();
          }
      }
      @Override
      public void onError(Throwable e) {
          Log.i("API调用失败","API调用失败");
          Toast.makeText(mContext, "API调用失败", Toast.LENGTH_SHORT).show();
      }
      //上游不写complete  成功返回也会自动执行
      @Override
      public void onComplete() {
          Log.i("API调用成功","API调用成功");
          Toast.makeText(mContext, "API调用成功", Toast.LENGTH_SHORT).show();
      }
    });
    

    思考:
    当方法A先执行,但是方法A要去调用监听,他的回调数据还没回调,这时会执行下面的B方法,但是B方法又需要A的回调数据,此时涉及到方法的异步调用问题
    可以用RXJava解决这个问题
    原理:在回调方法中,用RXJAVA去进行上下游的异步操作

    如新浪微博通过OAuth授权方式获取accessToken,回调这个accessToken需要时间,则可以在回调的方法中,Rxjava上游去接受回调,处理回调数据,然后处理完了,再去发送数据给下游,下游有了数据再去利用该数据调用新的请求
    (不够好?用FlatMap?见Rxjava(三)系列)
    代码示例见Github的SinaWeiBoDemo的LoginActivity中:


    很多业务中,需要上一个请求成功了,得到数据并处理了,才进行下一个请求,这里涉及了请求先后顺序的问题
    请参考下一篇博客:
    Rxjava2(三):http://blog.csdn.net/weixin_37577039/article/details/78622443


    但是当请求未完成或刚完成,Activity销毁了,则不应该更新主线程UI了,因此在Activity中将这个Disposable 保存起来, 当Activity退出时, 切断它即可
    果有多个Disposable
    RxJava中已经内置了一个容器CompositeDisposable, 每当我们得到一个Disposable时就调用CompositeDisposable.add()将它添加到容器中, 在退出的时候, 调用CompositeDisposable.clear() 即可切断所有的水管

    Disposable使用参考 RXjava(一):
    http://blog.csdn.net/weixin_37577039/article/details/78555208


    参考链接:http://www.jianshu.com/p/8818b98c44e2

    展开全文
  • 1. Kotlin+OkHttp3+Retrofit2+RxJava Kotlin基于Android,结合Retrofit2+Rxjava2+Okhttp3+Rxlifecycle针对网络核心库封装 https://www.jianshu.com/p/bb215f16f774 用Kotlin编写的MVP+RxJava+Retrofit黄历demo ...
  • 简单实现RxJava2+Okhttp+Retrofit2的网络请求框架封装本人近期在看网络请求框架封装时,看到网上呼声最高的是此类,轻便有简介,近日闲来无事,就为各位农友写了个案例,抠脚来的不喜勿喷哦。简单实现RxJava2...
  • 系列文章推荐: Android 必须知道的网络请求框架库,你不可错过的框架介绍篇 Android Retrofit 2.0(一)初次见面请多多关照 Android Retrofit 2.0(三)从源码分析原理    相关资料 ...
  • Retrofit2.0通俗易懂的学习姿势,Retrofit2.0 + OkHttp3 + Gson + RxJava Retrofit,因为其简单与出色的性能,也是受到很多人的青睐,但是他以往的通信框架还是有点区别,不过放心,因为他本身还是挺简单的,...
  • 使用Kotlin Anko Layout实现UI , MVP架构(Glide,Retrofit,OkHttp,RxJava)实现业务开发Android运用程序。
  • Retrofit,因为其简单与出色的性能,也是受到很多人的青睐,但是他以往的通信框架还是有点区别,不过放心,因为他本身还是挺简单的,所有我相信你看完这篇文章,对基本的请求是没什么问题的,其实现在网上这样的...
  • 今天要说的干货是:以Kotlin,在MVP模式下(OKHttp和 Retrofit+RxJava)网络请求两种实现方式的一个小案例,希望对大家有所帮助,效果图: Retrofit是Square公司开发的一款针对Android网络请求的一个当前很流行...
  • Kotlin编程开发之扩展插件+Android MVP案例(RxJava+Retrofit+OkHttp+Glide)
  • 在Andrroid开发中,网络请求十分常用,而在Android网络请求库中,Retrofit是当下最热的一个网络请求库 Retrofit之所以作为现在最流行的网络请求库,其中一个主要原因是:支持RxJava。Rxjava由于其基于事件流的...
  • Android 使用Retrofit2.0+OkHttp3.0实现缓存处理+Cookie持久化第三方库 目录 1.Retrofit+OkHttp的缓存机制 2.缓存实现方式 3.Cookie持久化的第三方库使用方法 4.用Retrofit写一个网络请求 5.关于...
  • 使用MVP框架搭建,分包明确,V层M层解耦,通过接口完成V层P层以及P层M层通信,解决内存泄漏问题 Retrofit做网络请求,封装网络请求工具类,使用单例模式,添加日志拦截器打印网络请求内容 集成Rxjava库,集成...
1 2 3 4 5 ... 14
收藏数 273
精华内容 109