阅读 207

简单封装rxjava2+retrofit2+mvp

## 前言-- 关于每部分的介绍,网上搜索一大堆,在这就不具体进行阐述了,我们直接上干货吧;

本文主要是将xjava2+retrofit请求框架与mvp模式相结合进行简单的封装;

好了,开始吧!

具体实现--

1、在 build.gradle 中添加依赖

    implementation 'com.squareup.okhttp3:okhttp:3.10.0'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
    implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
    implementation 'io.reactivex.rxjava2:rxjava:2.1.14'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    implementation 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
复制代码

2、Mvp模式搭建

(1)对BasePresenter的封装

public abstract class BasePresenter<T> {
    private CompositeDisposable disposables;// 管理Destroy取消订阅者者
    T view;
/**
 * 获取view实例
 * @param view
 */
    void onAttach(T view){
        this.view = view;
    }
  /**
     * 添加订阅
     * @param disposable
     */
    public boolean addRx(Disposable disposable) {
        if (disposables == null) {
            disposables = new CompositeDisposable();
        }
        disposables.add(disposable);
        return true;
    }

    /**
     * 解绑view
     */
    void onDetch(){
        this.view = null;
        if (disposables != null) {
            disposables.dispose();
            disposables = null;
        }
    }
}
复制代码

(2)对BaseView的封装(分为了加载前,加载失败,加载后,加载成功)

public abstract interface BaseView {

    /**
     * 加载数据成功
     * @param data
     */
    void loadSuccess(Object data);

    /**
     * 加载数据前
     * @param message
     */
    void loadBefore(int message);

    /**
     * 加载数据后
     */
    void loadAfter();

    /**
     * 加载失败
     * @param message
     */
    void loadFailed(String message);
}
复制代码

(3)对BaseAct进行封装

public abstract class BaseAct<V extends BaseView,T extends BasePresenter<V>>
            extends AppCompatActivity {

    private T presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId(savedInstanceState));
        presenter = getPresenter();
        initView();
    }

    /**
     * 返回layout资源文件
     * @param savedInstanceState
     * @return
     */
    public abstract int getLayoutId(@Nullable Bundle savedInstanceState);

    /**
     * 初始化
     */
    public void initView(){
        ButterKnife.bind(this);
    }

    /**
     * 获取presenter
     * @return
     */
    public abstract T getPresenter();

    @Override
    protected void onResume() {
        super.onResume();
        if(null != presenter){
            presenter.onAttach((V)this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(null != presenter){
            presenter.onDetch();
        }
    }

}
复制代码

2、😊请求框架封装

(1)ApiService请求接口类

顺便在测试一个接口,我就用的百度的一个识别图片中文字的接口,如果需要具体了解的,自己去百度开发者平台看吧!!

public interface ApiService {
    /**
     * 获取百度api的 access token
     * @param grantType 固定参数为client_credentials
     * @param clientId 应用的API Key
     * @param clientSecret 应用的Secret Key
     * @return observable对象用于rxjava,从AccessTokenBean中可以获得服务器返回的access token
     */
    @POST("oauth/2.0/token")
    Observable<AccessTokenBean> getAccessToken(@Query("grant_type") String grantType, @Query("client_id") String clientId, @Query("client_secret") String clientSecret);

    /**
     * 通过图片,获取图片内的文字信息
     * @param accessToken 通过API Key和Secret Key获取的access_token
     * @param image 图像数据base64编码后进行urlencode后的String
     * @return  observable对象用于rxjava,从RecognitionResultBean中可以获得图片文字识别的信息
     */
    @POST("rest/2.0/ocr/v1/general_basic")
    @FormUrlEncoded
    Observable<RecognitionResultBean> getRecognitionResultByImage(@Field("access_token") String accessToken, @Field("image") String image);
}
复制代码

(2)RetrofitClient类创建

保证Retrofit在类中只有一个实例,避免请求体的多次创建。

public class RetrofitClient {

    private static RetrofitClient instance;
    private OkHttpClient client;
    private Context context;
    private Retrofit retrofit;
    private ApiService apiService;

    private RetrofitClient(Context context){
        this.context = context;
    }

    /**
     * 初始化
     * @param context
     * @return
     */
    public static RetrofitClient getInstance(Context context){
        if (instance == null){
            instance = new RetrofitClient(context);
        }
        return instance;
    }

    /**
     * 初始化OkHttpClient
     * @return
     */
    private OkHttpClient provideOkHttpClient(){
        if (client == null){
            client = new OkHttpClient.Builder()
                    .connectTimeout(10,TimeUnit.SECONDS)
                    .readTimeout(10,TimeUnit.SECONDS)
                    .build();
        }
        return client;
    }

    /**
     * 初始化Retrofit
     * @return
     */
    private Retrofit provideRetrofit(){
        if (retrofit == null){
            retrofit = new Retrofit.Builder()
                    //.baseUrl("https://api.douban.com/v2/")
                    .baseUrl("https://aip.baidubce.com/")
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(provideOkHttpClient())
                    .build();
        }
        return retrofit;
    }

    public ApiService provideApiService(){
        if (apiService == null){
            apiService = provideRetrofit().create(ApiService.class);
        }
        return apiService;
    }

}
复制代码

(3)RxSchedulerHepler类创建

对请求线程切换进行封装

public class RxSchedulerHepler {
    public static <T> ObservableTransformer<T,T> io_main(){
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply(io.reactivex.Observable<T> upstream) {
                return  upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
}
复制代码

3、开始使用===

(1)新建PicturePresenter类,继承BasePresenter

以下是具体实现,此类中方法可以通过在activity进行调用

public class PicturePresenter extends BasePresenter<BaseView> {
    private BaseView newView;
    private Context context;
    private static final String CLIENT_CREDENTIALS = "client_credentials";
    private static final String API_KEY = "TEqrH3q466ljIIHPQVLsfnem";
    private static final String SECRET_KEY = "jCPvzEGRqvBXAGd9aPqCgBLR8iGfeRTW";
    private String ACCESS_TOKEN = "";

    public PicturePresenter(BaseView view,Context context){
        this.newView = view;
        this.context = context;
    }

    @Override
    public boolean addRx(Disposable disposable) {
        return super.addRx(disposable);
    }

    public void getToken(){

        RetrofitClient.getInstance(context)
                .provideApiService()
                .getAccessToken(CLIENT_CREDENTIALS,API_KEY,SECRET_KEY)
                .compose(RxSchedulerHepler.<AccessTokenBean>io_main())
                .subscribe(new Observer<AccessTokenBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(AccessTokenBean accessTokenBean) {
                        ACCESS_TOKEN = accessTokenBean.getAccess_token();
                        Log.e("Access token-----",ACCESS_TOKEN);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}
复制代码

(2)MainActivity的具体实现

public class MainActivity extends BaseAct<BaseView, PicturePresenter> implements BaseView {

    @BindView(R.id.bt_token)
    Button btToken;
    private PicturePresenter picturePresenter;

    @Override
    public int getLayoutId(@Nullable Bundle savedInstanceState) {
        return R.layout.activity_main;
    }

    @Override
    public PicturePresenter getPresenter() {
        picturePresenter = new PicturePresenter(this, this);
        return picturePresenter;
    }

    @Override
    public void initView() {
        super.initView();
    }

    @Override
    public void loadSuccess(Object data) {
        Log.e("Access token-----", (String) data);
    }

    @Override
    public void loadBefore(int message) {

    }

    @Override
    public void loadAfter() {

    }

    @Override
    public void loadFailed(String message) {

    }

    @OnClick(R.id.bt_token)
    public void onViewClicked() {
        picturePresenter.getToken();
    }
}
复制代码

基本实现就ok了,现在给大家看一下运行效果吧!

若有问题,请大家及时指正😊😊

github地址:https://github.com/luoye123/mvpDemo