Retrofit2+Rxjava2+OKHttp3+RxAndroid 实现网络请求的demo案例

在之前的项目中一直都用着比较老的网络框架,比如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的模式去写,项目结构:
Retrofit2+Rxjava2+OKHttp3+RxAndroid 实现网络请求的demo案例_第1张图片

项目结构中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>> getBanner();

    /**
     * 最新资讯
     */
    @GET(ApiAddress.getZixunList)
    Observable>> getZixunData();

    /**
     * 获取图片验证码
     */
    @GET(ApiAddress.getVerifyCode)
    Observable getVerityCode();

    /**
     * 登录
     */
    @POST(ApiAddress.userLogin)
    Observable> userLogin(@Body Map 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 {
        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() {
            @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 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(context,MainUtil.loadLogin) {
                    @Override
                    protected void onSuccees(BaseEntry 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>(context,MainUtil.loadTxt) {
                    @Override
                    protected void onSuccees(BaseEntry> 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>(context,MainUtil.loadTxt) {
                    @Override
                    protected void onSuccees(BaseEntry> 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 implements Observer> {
    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 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) 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源码地址

你可能感兴趣的:(Android)