Android RxJava2 整合Retrofit2 与Hilt注入网络模块

1.导入依赖

Kotlin 复制代码
 //Retrofit 整合 RXjava
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
    implementation 'io.reactivex.rxjava2:rxjava:2.2.4'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
    //Retrofit
    //Retrofit 核心库
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    //响应数据自动序列化
    //JSON
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
    //String类型
    implementation("com.squareup.retrofit2:converter-scalars:2.9.0")
    //拦截器 logging
    implementation("com.squareup.okhttp3:logging-interceptor:3.14.+")


    implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))


    //Hilt
    implementation("com.google.dagger:hilt-android:2.44")
    annotationProcessor("com.google.dagger:hilt-android-compiler:2.44")

    compileOnly 'org.projectlombok:lombok:1.18.32'
    annotationProcessor 'org.projectlombok:lombok:1.18.32'

    testCompileOnly 'org.projectlombok:lombok:1.18.32'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.32'

在模块下build.gradle

加入插件

Kotlin 复制代码
plugins {
    id 'com.android.application'
    id 'dagger.hilt.android.plugin'
}

项目工程build.gradle

Kotlin 复制代码
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext {
        agp_version = '7.4.2'
    }
    repositories {
//        maven {url = "https://maven.aliyun.com/nexus/content/groups/public/"}
        maven {url = "https://maven.aliyun.com/repository/public"}
        maven { url ="https://maven.aliyun.com/repository/google/"}
        maven { url= "https://maven.aliyun.com/repository/jcenter/"}
        google()
        jcenter()
        mavenCentral()
        gradlePluginPortal()
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        classpath "com.android.tools.build:gradle:$agp_version"
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.15'
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.44'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
//        maven {url = "https://mirrors.tencent.com/nexus/repository/maven-public/"}
        maven {url = "https://maven.aliyun.com/repository/public"}
        maven { url ="https://maven.aliyun.com/repository/google/"}
        maven { url= "https://maven.aliyun.com/repository/jcenter/"}
        google()
        jcenter()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

2.Application注入Hilt注解

java 复制代码
@HiltAndroidApp
public class APP_CONTEXT extends Application

3.网络模块的注入

java 复制代码
import android.util.Log;

import com.tiger.nfc_project.activities.APP_CONTEXT;

import net.retrofit.service.ApiService;
import net.retrofit.service.StudyService;

import java.util.concurrent.TimeUnit;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
import dagger.hilt.InstallIn;
import dagger.hilt.components.SingletonComponent;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

@InstallIn(SingletonComponent.class)
@Module
public class NetWorkModule {
    private static final String Tag = "Retrofit";

    @Singleton
    @Provides
    OkHttpClient provideOkHttpClient() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Log.i(Tag, message);
            }
        }).setLevel(HttpLoggingInterceptor.Level.BODY);


        return new OkHttpClient
                .Builder()
                //连接超时
                .connectTimeout(1, TimeUnit.SECONDS)
                //读取超时
                .readTimeout(3,TimeUnit.SECONDS)
                .addInterceptor(interceptor)
                .build();

    }

    @Singleton
    @Provides
    Retrofit provideRetrofit(OkHttpClient client) {
        return new Retrofit
                .Builder()
                .baseUrl(APP_CONTEXT.CRACK_URL + "/")
                .client(client)
//                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                //添加Rxjava适配
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }

    @Singleton
    @Provides
    ApiService provideApiService(Retrofit retrofit) {
        return retrofit.create(ApiService.class);
    }


    @Singleton
    @Provides
    StudyService provideStudyService(Retrofit retrofit) {
        return retrofit.create(StudyService.class);
    }

}

4.三个统一异常处理器

java 复制代码
import android.util.Log;

import com.google.gson.JsonParseException;

import org.json.JSONException;

import java.net.ConnectException;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.ParseException;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * 统一异常处理
 */
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ApiException extends Exception {

    private static final String Tag = "ApiException";
    public static final int UNKNOWN_ERROR = 1000;
    public static final int PARSE_ERROR = 1001;
    public static final int NETWORK_ERROR = 1002;
    public static final int INNER_ERROR = 500;

    private Integer code;
    private String errorMsg;
    private Throwable e;

    public ApiException(String errorMsg) {
        this.code = INNER_ERROR;
        this.errorMsg = errorMsg;
    }

    public ApiException(Integer code, String message) {
        super(message);
        this.code = code;
        this.errorMsg = message;
    }

    public ApiException(Integer code, String errorMsg, Throwable cause) {
        super(errorMsg, cause);
        this.code = code;
        this.errorMsg = errorMsg;
        this.e = cause;
    }

    public static ApiException handleException(Throwable e) {
        ApiException ex;

        if (e instanceof ApiException) {
            ex = (ApiException) e;
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException
        ) {
            ex = new ApiException(PARSE_ERROR, "数据解析异常", e);

        } else if (e instanceof ConnectException
                || e instanceof UnknownHostException
                || e instanceof SocketException
        ) {
            ex = new ApiException(NETWORK_ERROR, "网络异常", e);
        } else {
            ex = new ApiException(UNKNOWN_ERROR, "未知异常", e);
        }
        return ex;
    }

    public void printException() {

        try {
            int i = code;
            if (i >= 1000) {
                //真正错误
                Log.e(Tag, errorMsg, e);
            } else {
                Log.e(Tag, "code:" + code + ";msg:" + errorMsg);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }

    }


}
java 复制代码
import io.reactivex.functions.Consumer;

/**
 * 通用处理异常回调的Consumer
 */
public abstract class ErrorConsumer implements Consumer<Throwable> {

    @Override
    public void accept(Throwable throwable) {
        ApiException ex;
        if (throwable instanceof  ApiException){
            ex =(ApiException) throwable;
        }else {
            ex = ApiException.handleException(throwable);
        }

        error(ex);
    }


    protected abstract void error(ApiException e);
}
java 复制代码
import android.util.Log;

import com.jsonutil.GsonUtils;

import net.vo.ErrorResultVo;

import io.reactivex.functions.Consumer;
import retrofit2.HttpException;

/**
 * 异常处理的标准写法
 */
public abstract class ExceptionConsumer implements Consumer<Throwable> {

    private static final String tag = "HttpException";
    private static final String tag1 = "Exception";
    @Override
    public void accept(Throwable throwable) throws Exception {

        try {
            if (throwable instanceof HttpException){
                HttpException throwable2 = (HttpException) throwable;
                String errorJson = throwable2.response().errorBody().string();
                ErrorResultVo obj = GsonUtils.toObj(errorJson, ErrorResultVo.class);
                String message = obj.getMessage();
                Log.e(tag,message);
                callback(message);
            }else {
                Log.e(tag1,"内部错误",throwable);
            }
        } catch (Exception e) {
            Log.e(tag1,"异常处理失败错误",e);
        }
    }

    public abstract void callback(String errorMsg);

}

5.响应

java 复制代码
public interface IResponse<T> {


    boolean isSuccess();


    T getData();


    Integer getCode();

    String getMsg();


}
java 复制代码
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.disposables.CompositeDisposable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 *  响应的标准写法 以后 RESTFUL风格
 * @param <T>
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseStandard<T> implements ObservableTransformer<T, T> {

    private CompositeDisposable compositeDisposable;


    @Override
    public ObservableSource<T> apply(Observable<T> upstream) {

        return upstream.doOnSubscribe(disposable -> {

            if (compositeDisposable != null) {
                //disposable主要是用来取消订阅的
                compositeDisposable.add(disposable);
            }
        }).flatMap(response -> {
            try {
                return Observable.just(response);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return Observable.error(new Exception("响应数据格式有误"));
        });
    }


    /**
     * 获取ResponseTransformer
     *
     * @param compositeDisposable
     * @param <U>
     * @return
     */
    public static <U> ResponseStandard<U> obtain(CompositeDisposable compositeDisposable) {
        return new ResponseStandard<>(compositeDisposable);
    }

    public static <U> ResponseStandard<U> obtain() {
        return new ResponseStandard<>();
    }


}
java 复制代码
import net.retrofit.exeption.ApiException;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 获取IResponse后判断请求结果,并获取data返回
 * Observable<IResponse<T>>  --> Observable<T>
 * 可以自己实现,这里只是一种思路
 * 这是有JSONObject 的写法
 * @param <T>
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseTransformer<T> implements ObservableTransformer<IResponse<T>, T> {

    private CompositeDisposable compositeDisposable;


    @Override
    public ObservableSource<T> apply(Observable<IResponse<T>> upstream) {

        return upstream.doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        if (compositeDisposable != null) {
                            //disposable主要是用来取消订阅的
                            compositeDisposable.add(disposable);
                        }
                    }
                }).onErrorResumeNext(new Function<Throwable, ObservableSource<? extends IResponse<T>>>() {
                    @Override
                    public ObservableSource<? extends IResponse<T>> apply(Throwable throwable) throws Exception {
                        //出现异常后统一处理
                        return Observable.error(ApiException.handleException(throwable));
                    }
                })
                .flatMap(new Function<IResponse<T>, ObservableSource<? extends T>>() {
                    @Override
                    public ObservableSource<? extends T> apply(IResponse<T> response) throws Exception {
                        //这段逻辑是业务请求成功后,根据接口返回的数据做一些成功失败后的规范处理
                        //这里已经高度封装,弊端就算没那么灵活
                        //可以自己去实现BaseResponse,不一定要使用IResponse这种写法
                        if (response.isSuccess()) {
                            //若响应成功
                            if (response.getData() != null) {
                                return Observable.just(response.getData());
                            } else {
                                try {
                                    //规定好,如果没有返回,那么默认泛型为字符串;
                                    String s = "成功";
                                    T t = (T) s;
                                    return Observable.just(t);

                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }

                        }
                        return Observable.error(new ApiException(response.getCode(), response.getMsg(), new Exception("出现正常请求的错误")));
                    }
                });

    }


    /**
     * 获取ResponseTransformer
     *
     * @param compositeDisposable
     * @param <U>
     * @return
     */
    public static <U> ResponseTransformer<U> obtain(CompositeDisposable compositeDisposable) {
        return new ResponseTransformer<>(compositeDisposable);
    }

    public static <U> ResponseTransformer<U> obtain() {
        return new ResponseTransformer<>();
    }


}

6.ApiService

java 复制代码
import net.vo.JSONResult;

import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Path;

public interface ApiService {



    /**
     * 
     *
     * @param 
     * @param 
     * @return
     */
    @GET(PREFIX + "/authorize/user/{bb}/dev/{aa}")
    Observable<JSONResult<Boolean>>  cc(@Path("bb") String bb, @Path("aa") String aa);






}

7.结果返回

java 复制代码
/**
 * @ClassName JSONResult
 * @Description 自定义响应数据格(接口)
 *              200:表示成功
 *              500:表示错误
 *              501:bean验证错误
 *              502:拦截器拦截用户taken出错
 *              503:不具备角色功能
 *              505:异常抛出信息
 * @Author liuhongjian
 * @Date 2020/3/11 16:03
 * @Version 1.0
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JSONResult<T> implements IResponse<T> {

    public static final Integer SUCCESS =200;
    /**
     * 响应码
     */
    private Integer status;

    /**
     * 响应信息
     */
    private String msg;

    /**
     * 响应的数据
     */
    private T data;

    /**
     *
     */
    private String ok;


    @Override
    public boolean isSuccess() {
        return SUCCESS.equals(status);
    }

    @Override
    public Integer getCode() {
        return status;
    }
}
java 复制代码
import java.io.Serializable;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ErrorResultVo implements Serializable {
    private static final long serialVersionUID = -7634852916785258705L;

    private String code;
    private String message;
}

8. RxJAVA 执行异步

java 复制代码
 Observable<String[]> firstOperation = Observable.fromCallable(() -> {
              
                        return infos;
           
            });


          
            Observable<Boolean> secondOperation = firstOperation
                    
                    .flatMap(infos ->{
                       return true;
                    });


        
            Observable<Boolean> thirdOperation = secondOperation.flatMap(isAllowWrite ->{
               
                return    Observable.fromCallable(() -> {
                   
                    return true;
                });
            });


            Disposable disposable =  thirdOperation
                    .subscribeOn(Schedulers.io())
                    .subscribe(result -> {
                       
                    }, new ErrorConsumer() {
                        @Override
                        protected void error(ApiException e) {
                            //异常统一处理 子线程
                            e.printException();
                            //异常
                            handler.sendEmptyMessage(NOT_SUPPORT_TAG);
                        }
                    });



            /**
             * 对资源对象统一管理
             */
            compositeDisposable.add(disposable);
        }catch (Exception e){
            Log.e(Tag,"代理授权出现异常",e);
        }

9.rxjava基本操作

java 复制代码
Observable.just("Hello")
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            // 在主线程中操作,例如更新 UI
            textView.setText(s);
        }
    });

10.GSON使用

java 复制代码
public class GsonUtils {
  public static final Gson gson = new GsonBuilder().serializeNulls().setDateFormat("yyyy-MM-dd hh:mm:ss").create();
    public static String getJson(Object o){
        return gson.toJson(o);
    }

    public static <T> T toObj(String o,Class<T> tClass){
        return gson.fromJson(o,tClass);
    }

}
相关推荐
Estar.Lee1 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
找藉口是失败者的习惯2 小时前
从传统到未来:Android XML布局 与 Jetpack Compose的全面对比
android·xml
Jinkey3 小时前
FlutterBasic - GetBuilder、Obx、GetX<Controller>、GetxController 有啥区别
android·flutter·ios
大白要努力!5 小时前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟6 小时前
Android音频采集
android·音视频
小白也想学C7 小时前
Android 功耗分析(底层篇)
android·功耗
曙曙学编程7 小时前
初级数据结构——树
android·java·数据结构
闲暇部落9 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
诸神黄昏EX11 小时前
Android 分区相关介绍
android
大白要努力!12 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle