接着Retrofit2.0基础使用(一),一般都是rxjava和retrofit最配吆,,,不过我见过的一般的项目都是retrofit2.0的项目,没有应用rxjava,最多就是项目基于mvp模式,外加dagger2就算是最高大上的了,所以研究rxjava2.0时候,有点绕路,自己研究了一下午,研究了一个皮毛,快速开发总算能用了。
为什么不说rxjava1.0的,有新的框架,谁还研究老框架啊,哈哈。研究及研究一下最热的框架,方能跟的上潮(zhaung)流(x)啊!
集成步骤基于Retrofit2.0基础使用(一)
使用步骤
一、在主工程可以引用的build.gradle中新增依赖
//Rxjava 权限rxpermissions 使用到
api 'io.reactivex.rxjava2:rxjava:2.2.5'
api 'io.reactivex.rxjava2:rxandroid:2.1.0'
api 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
// rxLifecycle
api 'com.trello.rxlifecycle2:rxlifecycle-android:2.0.1'
api 'com.trello.rxlifecycle2:rxlifecycle-components:2.0.1'
说明:1.考虑网络加载中acitivity和fragment会退出的情况,而且同时存在多个请求的情况下,防止内存泄漏(甚至崩溃情况),需要在ondestroy中取消订阅事件,
2.不想在baseAct或者baseFrt中定义一个map添加observe(或者Disposable),那样占用内存、而且逻辑判断复杂,还有是不是无网络请求的和有网络请求的分开呢,,
3.听说过lifecy组件,没有使用过,开源的rxlifecycle2完全满足业务需求,不过rxlifecycle3集成报错,暂时使用主流稳定的的rxlifecycle2
二、单例的Retrofit和Okhttp管理类
变化不大,只需要在buildRetrofit方法中得 new Retrofit.Builder()后面添加一句
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
三、创建 Callback的过滤类,为了适应各种网络状态和事件的统一处理,比如处理统一的错误状态、单点登录等等
逻辑变化不大,就是更改了集成的父类名字,多了两个暂时不需要的方法(较真的话,可以使用,只是我暂时用不到)
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import retrofit2.HttpException;
/**
* @author hahaliu
* @date 2019/1/15 0015
* @annotate
*/
public abstract class RxCallBack<M extends BobyBean> implements Observer<M> {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
if (e instanceof HttpException) {
HttpException httpException = (HttpException) e;
int code = httpException.code();
onFailed(code, "服务器升级中,请稍后重试");
//Http状态码提示
if (code >= 400 && code < 500) {
LogUtils.e("请求错误");
} else if (code >= 500) {
LogUtils.e("服务器错误");
}
} else {
onFailed(-100, "服务器升级中,请稍后重试");
}
}
@Override
public void onNext(M baseModel) {
handleStatusCode(baseModel);
}
/**
* 后台statuscode状态码处理,状态码类型封装在StatusCodeEnum中
*
* @param baseModel
*/
private void handleStatusCode(M baseModel) {
if (baseModel == null) {
onFailed(-100, "服务器升级中,请稍后重试");
} else {
int statusCode = baseModel.code;
switch (statusCode) {
case 0:
onSucceed(baseModel);
break;
default:
onFailed(statusCode, baseModel.msg);
break;
}
}
}
public abstract void onSucceed(M response);
public abstract void onFailed(int errorCode, String msg);
}
其中 其中错误状态没有变化,bean类和logUtils自行脑补
四、请求声明
import java.util.Map;
import io.reactivex.Observable;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Query;
import retrofit2.http.Url;
/**
* @author hahaliu
* @date 2019/1/8 0008
* @annotate
*/
public interface RemoteRealService {
/**
* 登录
* @param username
* @param password
* @param clientType
* @return
*/
@POST("login")
Observable<BobyBean<UserBean>> login(@Query("username") String username, @Query("password") String password, @Query("clientType") String clientType);
/**
* 单个文件上传
* @param tableName
* @param file
* @return
*/
@Multipart
@POST("fjwj/fileUpload")
Call<BobyBean<FileBean>> fjwj_fileUpload_only_retrofit(@Part("tableName") RequestBody tableName, @Part MultipartBody.Part file);
/**
* 多文件上传
* @param tableName
* @param params
* @return
*/
@Multipart
@POST("fjwj/fileUpload")
Observable<BobyBean<FileBean>> fjwj_fileUpload_retrofit(@Part("tableName") RequestBody tableName, @PartMap Map<String, RequestBody> params);
/**
* 文件下载
* @param url
* @return
*/
@GET
Observable<ResponseBody> loadFile(@Url String url);
}
Call换为Observable而已
import com.trello.rxlifecycle2.LifecycleProvider;
import com.trello.rxlifecycle2.android.ActivityEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
/**
* @author hahaliu
* @ClassName Http
* @Description 所有接口统一
* @date 2018-09-20
*/
public class Http implements IRemoteService {
/**
* 统一设置Observable
*
* @param observable
* @param <T>
* @return
*/
public static <T> Observable<T> observe(Observable<T> observable) {
return observable
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
/**
* rxjava +retrofit 请求方式
*
* @param username
* @param password
* @param callback
*/
public static void doLogin(LifecycleProvider activity, String username, String password, final RxCallBack<BobyBean<UserBean>> callback) {
RemoteRealService service = HttpsClientUtil.newInstance().create(RemoteRealService.class);
Observable<BobyBean<UserBean>> observable = observe(service.login(username, password, "app"));
observable
.compose(activity.<BobyBean<UserBean>>bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(callback);
}
/**
* 单文件上传 retrofit
*
* @param tableName
* @param file
* @param callback
*/
public static void fjwj_fileUpload_only_retrofit(LifecycleProvider activity,String tableName, File file, RxCallBack<BobyBean<FileBean>> callback) {
RemoteRealService service = HttpsClientUtil.newInstance().create(RemoteRealService.class);
RequestBody tableBoay = RequestBody.create(MediaType.parse("text/plain"), tableName);
RequestBody photoRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
MultipartBody.Part photo = MultipartBody.Part.createFormData("file", file.getName(), photoRequestBody);
Observable<BobyBean<FileBean>> observable = service.fjwj_fileUpload_only_retrofit(tableBoay, photo);
observable
.compose(activity.<BobyBean<FileBean>>bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(callback);
}
/**
* 多文件统一上传 retrofit
*
* @param tableName
* @param files
* @param callback
*/
public static void fjwj_fileUpload_retrofit(LifecycleProvider activity, String tableName, List<File> files, RxCallBack<BobyBean<FileBean>> callback) {
RemoteRealService service = HttpsClientUtil.newInstance().create(RemoteRealService.class);
RequestBody tableBoay = RequestBody.create(MediaType.parse("text/plain"), tableName);
Map<String, RequestBody> params = new HashMap<>();
for (File file : files) {
RequestBody photoRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
params.put("file\"; filename=\"" + file.getName(), photoRequestBody);
}
Observable<BobyBean<FileBean>> observable = observe(service.fjwj_fileUpload_retrofit(tableBoay, params));
observable
.compose(activity.<BobyBean<FileBean>>bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(callback);
}
/**
* 文件下载
*
* @param context
* @param url
* @param fileDes 文件夹存储的命名
* @param position 回调状态--本方法中为文件列表的下表
* @param listener 自定义的回调监听 方法onItemClickListener的两个int类型参数 type事件类型 position回调状态
*/
public static void loadFile(final LifecycleProvider provider, final Context context, String url, final String fileDes, final int position, final BaseRecyclerBottomSpaceAdapter.OnItemCommonClickListener listener) {
RemoteRealService service = HttpsClientUtil.newInstance().create(RemoteRealService.class);
Observable<ResponseBody> call = observe(service.loadFile(url));
call.compose(provider.<ResponseBody>bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(new Observer<ResponseBody>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseBody responseBody) {
if (responseBody != null) {
boolean writeToDisk = Http.writeFileToSDCard(context, fileDes, responseBody);
if (writeToDisk) {
AppConfig.openFile(context, new File(AppConfig.getAppCacheFilePath(context), fileDes));
listener.onItemClickListener(1, position);
} else {
listener.onItemClickListener(-1, -1);
}
} else {
listener.onItemClickListener(-1, -1);
}
}
@Override
public void onError(Throwable e) {
listener.onItemClickListener(-1, -1);
}
@Override
public void onComplete() {
}
});
}
/**
* 下载文件
*
* @param context
* @param fileDes 文件路径
* @param body
* @return
*/
private static boolean writeFileToSDCard(Context context, String fileDes, ResponseBody body) {
try {
File futureStudioIconFile = new File(AppConfig.getAppCacheFilePath(context), fileDes);
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d("", "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
}
注意:1.baseActivity和baseFragment分别继承RxAppCompatActivity、RxFragment
2..compose(activity.<BobyBean<FileBean>>bindUntilEvent(ActivityEvent.DESTROY))参数值写死了,如果有act和fra两种情况,应该使用参数传递形势赋值。
参考资料:https://www.jianshu.com/p/0ad99e598dba
rxjava是个好东西,rxJava2.0还需要很多坑要填,所以日后就是项目的标配了,先记录一下入门大法:
https://www.jianshu.com/p/464fa025229e