现在几乎大部分的项目都在使用MVP+retrofit+rxjava,不管你承不承认,现在的趋势就是这样子,作为一个android开发,你必须适应潮流,与时俱进。主流的框架搭建,主流的开源框架使用,是必须要会的。来到新公司,我为手下的人进行了一次培训,主要是如何进行常规项目框架搭建,级如何使用rxjava+retrofit的网络框架(此处不讲MVP,因为我觉得这东西很灵活,没有统一的标准,但是我会在文章结尾,把demo放上去)。
1.添加依赖
compile 'io.reactivex.rxjava2:rxjava:2.0.7'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.okhttp3:okhttp:3.5.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
2.新建RetrofitFactory工厂
public class RetrofitFactory {
private static RetrofitFactory mRetrofitFactory;
private static NetServices mNetservices;
private RetrofitFactory(){
OkHttpClient mOkHttpClient=new OkHttpClient.Builder()
.connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
.readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
.writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
.addInterceptor(InterceptorUtil.HeaderInterceptor())
.addInterceptor(InterceptorUtil.LogInterceptor())//添加日志拦截器
.addNetworkInterceptor(new StethoInterceptor()) //添加抓包工具
.build();
Retrofit mRetrofit=new Retrofit.Builder()
.baseUrl(HttpConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())//添加gson转换器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava转换器
.client(mOkHttpClient)
.build();
mNetservices=mRetrofit.create(NetServices.class);
}
public static RetrofitFactory getInstence(){
if (mRetrofitFactory==null){
synchronized (RetrofitFactory.class) {
if (mRetrofitFactory == null)
mRetrofitFactory = new RetrofitFactory();
}
}
return mRetrofitFactory;
}
public NetServices creatService(){
return mNetservices;
}
}
3.添加拦截器工具类
public class InterceptorUtil {
public static String TAG="InterceptorUtil";
//日志拦截器
public static HttpLoggingInterceptor LogInterceptor(){
return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.w(TAG, "log: "+message );
}
}).setLevel(HttpLoggingInterceptor.Level.BODY);//设置打印数据的级别
}
public static Interceptor HeaderInterceptor(){
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request mRequest=chain.request();
//在这里你可以做一些想做的事,比如token失效时,重新获取token
//或者添加header等等
return chain.proceed(mRequest);
}
};
}
}
4.添加观察者BaseObserver
public abstract class BaseObserver<T> implements Observer<BaseEntity<T>> {
private static final String TAG = "BaseObserver";
protected Context mContext;
public BaseObserver(Context cxt) {
this.mContext = cxt;
}
public BaseObserver() {
}
@Override
public void onSubscribe(Disposable d) {
onRequestStart();
}
@Override
public void onNext(BaseEntity<T> tBaseEntity) {
onRequestEnd();
Log.d(TAG,tBaseEntity.toString());
if (tBaseEntity.getCode()==0) {
try {
onSuccees(tBaseEntity);
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
onCodeError(tBaseEntity);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onError(Throwable e) {
// Log.w(TAG, "onError: ", );这里可以打印错误信息
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() {
}
/**
* 返回成功
*
* @param t
* @throws Exception
*/
protected abstract void onSuccees(BaseEntity<T> t) throws Exception;
/**
* 返回成功了,但是code错误
*
* @param t
* @throws Exception
*/
protected void onCodeError(BaseEntity<T> t) throws Exception {
}
/**
* 返回失败
*
* @param e
* @param isNetWorkError 是否是网络错误
* @throws Exception
*/
protected abstract void onFailure(Throwable e, boolean isNetWorkError) throws Exception;
protected void onRequestStart() {
}
protected void onRequestEnd() {
closeProgressDialog();
}
public void showProgressDialog() {
// ProgressDialog.show(mContext, false, "请稍后");
}
public void closeProgressDialog() {
// ProgressDialog.cancle();
}
}
5.其他配置相关的类
public class HttpConfig {
public static int HTTP_TIME = 30;
public static String BASE_URL = "https://api.bit-space.net";
}
public interface NetServices {
@POST("/login/submit")
Observable<BaseEntity<Login>> login(@Query("phone") String phone,
@Query("password") String password);
}
7.封装返回数据的BaseEntity
public class BaseEntity<T> {
/**
* code : 1001
* msg : 账号或密码错误
* data : {"deviceId":1001,"token":"账号或密码错误"}
*/
private static int SUCCESS_CODE=0;//成功的code
private int code;
private String msg;
private T data;
public boolean isSuccess(){
return getCode()==SUCCESS_CODE;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "BaseEntity{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}
8.使用方式
RetrofitFactory.getInstence().creatService()
.login(number, password)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseObserver<Login>() {
@Override
protected void onSuccees(BaseEntity<Login> t) throws Exception {
mCallback.onLoginSuccess(t.getData());
}
@Override
protected void onFailure(Throwable e, boolean isNetWorkError) throws Exception {
mCallback.onLoginFailed(e.toString());
}
});
9.回首rxjava使用方式
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe");
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "onNext=" + value);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete");
}
});
10.总结
对比下我们封装的网络请求,还有rajava经典使用方法,其实就是一句话,就是在子线程使用okhttp获取数据,把数据通过rxjava线程切换发送给观察者,我们对观察者进行封装了一层,同时对数据进行处理。我这种封装方式很简单,也容易懂,代码比较少,支持自定义头部,支持消息体返回数据的处理,优化下扩展能力也很强,当然也有很多不足的,比如其他的下载,添加progressbar等等都没有,这个等待有缘人自己去添加。
代码地址:
https://download.csdn.net/download/qq_16177199/10789475
github地址