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);
    }

}
相关推荐
500了3 小时前
Kotlin基本知识
android·开发语言·kotlin
人工智能的苟富贵4 小时前
Android Debug Bridge(ADB)完全指南
android·adb
小雨cc5566ru9 小时前
uniapp+Android面向网络学习的时间管理工具软件 微信小程序
android·微信小程序·uni-app
bianshaopeng10 小时前
android 原生加载pdf
android·pdf
hhzz10 小时前
Linux Shell编程快速入门以及案例(Linux一键批量启动、停止、重启Jar包Shell脚本)
android·linux·jar
火红的小辣椒11 小时前
XSS基础
android·web安全
勿问东西13 小时前
【Android】设备操作
android
五味香13 小时前
C++学习,信号处理
android·c语言·开发语言·c++·学习·算法·信号处理
图王大胜15 小时前
Android Framework AMS(01)AMS启动及相关初始化1-4
android·framework·ams·systemserver
工程师老罗17 小时前
Android Button “No speakable text present” 问题解决
android