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