版权声明:本文为博主原创文章 && 转载请著名出处https://blog.csdn.net/cs_lwb https://blog.csdn.net/cs_lwb/article/details/82016997
Android Rxjava+Retrofit封装
扫描二维码关注公众号,回复:
3300302 查看本文章
https://www.jianshu.com/p/ff619fea7e22
https://blog.csdn.net/impure/article/details/79658098 文件下载
https://gitee.com/blcs/LwbUtils
一、简介
Rxjava与RxAndroid就不在这里介绍,为了更方便,使用较少的代码来实现网络请求。这里对目前比较流行的Retrofit网络框架进行封装。
二、封装步骤
(1)在build文件中加入相关依赖
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.1.0'
(2)请求接口服务类
import java.util.List;
import java.util.Map;
import demo.lwb.com.myutils.bean.Demo;
import io.reactivex.Observable;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Response;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.HeaderMap;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import retrofit2.http.Streaming;
import retrofit2.http.Url;
/**
* retrofit2 Api接口 Demo
*/
public interface ApiService {
/**
* TODO Get请求
*/
//第一种方式:GET不带参数
@GET("demo1.txt")
Observable<Response<BaseResponse<Demo>>> getUser();//中间的BaseResponse 是自己根据后台数据封装的规范 可以进行修改
@GET
Observable<Response<Demo>> getUser(@Url String url); //正常情况 添加ResPonse可以根据Response.Code来判断错误类型
@GET
Observable<Demo> getUser1(@Url String url); //简洁方式 直接获取所需数据
//第二种方式:GET带参数
@GET("api/data/{type}/{count}/{page}")
Observable<Response<Demo>> getUser(@Path("type") String type, @Path("count") int count, @Path("page") int page);
//第三种方式:GET带请求参数:https://api.github.com/users/whatever?client_id=xxxx&client_secret=yyyy
@GET("users/whatever")
Observable<Response<Demo>> getUser(@Query("client_id") String id, @Query("client_secret") String secret);
@GET("users/whatever")
Observable<Response<Demo>> getUser(@QueryMap Map<String, String> info);
/**
* TODO POST请求
*/
//第一种方式:@Body
@Headers("Accept:application/json")
@POST("login")
Observable<Response<Demo>> postUser(@Body RequestBody body);
//第二种方式:@Field
@Headers("Accept:application/json")
@POST("auth/login")
@FormUrlEncoded
Observable<retrofit2.Response<Demo>> postUser(@Field("username") String username, @Field("password") String password);
//多个参数
Observable<Response<Demo>> postUser(@FieldMap Map<String, String> map);
/**
* TODO DELETE
*/
@DELETE("member_follow_member/{id}")
Observable<Response<Demo>> delete(@Header("Authorization") String auth, @Path("id") int id);
/**
* TODO PUT
*/
@PUT("member")
Observable<Response<Demo>> put(@HeaderMap Map<String, String> headers,
@Query("nickname") String nickname);
/**
* TODO 文件上传
*/
@Multipart
@POST("upload")
Observable<ResponseBody> upload(@Part("description") RequestBody description,@Part MultipartBody.Part file);
//亲测可用
@Multipart
@POST("member/avatar")
Observable<Response<Demo>> uploadImage(@HeaderMap Map<String, String> headers, @Part MultipartBody.Part file);
/**
* 多文件上传
* @param params
* @param description
* @return
*/
@Multipart
@POST("register")
Observable<ResponseBody> upload(@PartMap Map<String, RequestBody> params, @Part("description") RequestBody description);
//Observable<ResponseBody> upload(@Part() List<MultipartBody.Part> parts);
@Multipart
@POST("member/avatar")
Observable<Response<Demo>> uploadImage1(@HeaderMap Map<String, String> headers, @Part List<MultipartBody.Part> file);
/**
* 来自https://blog.csdn.net/impure/article/details/79658098
* @Streaming 这个注解必须添加,否则文件全部写入内存,文件过大会造成内存溢出
*/
@Streaming
@GET
Observable<ResponseBody> download(@Header("RANGE") String start, @Url String url);
}
(3)返回结果bean类与统一响应封装
public class Demo {
private String id;
private String appid;
private String name;
private String showtype;
private String showurl;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getShowtype() {
return showtype;
}
public void setShowtype(String showtype) {
this.showtype = showtype;
}
public String getShowurl() {
return showurl;
}
public void setShowurl(String showurl) {
this.showurl = showurl;
}
}
/**
* 统一响应
* @param <T>
*/
public class BaseResponse<T> {
private int res_code;
private int err_code;
private String err_msg;
private T Demo;
public int getRes_code() {
return res_code;
}
public void setRes_code(int res_code) {
this.res_code = res_code;
}
public int getErr_code() {
return err_code;
}
public void setErr_code(int err_code) {
this.err_code = err_code;
}
public String getErr_msg() {
return err_msg;
}
public void setErr_msg(String err_msg) {
this.err_msg = err_msg;
}
public T getDemo() {
return Demo;
}
public void setDemo(T Demo) {
this.Demo = Demo;
}
}
(4)Retrofit封装
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Retrofit封装
*/
public class RetrofitUtils {
public final static String BaseUrl= "http://oavnqjdk1.bkt.clouddn.com/";
private static final int DEFAULT_TIME=10;
private static RetrofitUtils mInstance;
/**
* 单例模式
*/
public static RetrofitUtils getInstance() {
if (mInstance == null) {
synchronized (RetrofitUtils.class) {
if (mInstance == null) {
mInstance = new RetrofitUtils();
}
}
}
return mInstance;
}
/**
* 初始化必要对象和参数
* @param url 基础baseUrl
* @return
*/
public Retrofit getRetrofit(String url) {
// 初始化okhttp
OkHttpClient client = new OkHttpClient().newBuilder()
.readTimeout(DEFAULT_TIME, TimeUnit.SECONDS)//设置读取超时时间
.connectTimeout(DEFAULT_TIME, TimeUnit.SECONDS)//设置请求超时时间
.writeTimeout(DEFAULT_TIME,TimeUnit.SECONDS)//设置写入超时时间
.addInterceptor(new LogInterceptor())//添加打印拦截器
.retryOnConnectionFailure(true)//设置出现错误进行重新连接。
.build();
// 初始化Retrofit
return new Retrofit.Builder()
.client(client)
.baseUrl(url)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
//返回一个泛型类
public static <T>T getService(Class<T> service){
return getInstance().getRetrofit(BaseUrl).create(service);
}
public static ApiService getApiService(){
return getInstance().getRetrofit(BaseUrl).create(ApiService.class);
}
}
(5)Log拦截器代码
import android.util.Log;
import java.io.IOException;
import java.util.Locale;
import okhttp3.Interceptor;
import okhttp3.Request;
/**
* Log拦截器代码
*/
public class LogInterceptor implements Interceptor{
private String TAG = "okhttp";
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Log.w(TAG,"request:" + request.toString());
long t1 = System.nanoTime();
okhttp3.Response response = chain.proceed(chain.request());
long t2 = System.nanoTime();
Log.w(TAG,String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
okhttp3.MediaType mediaType = response.body().contentType();
String content = response.body().string();
Log.w(TAG, "response body:" + content);
return response.newBuilder()
.body(okhttp3.ResponseBody.create(mediaType, content))
.build();
}
}
(6)Observer基础封装
import android.util.Log;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import retrofit2.Response;
/**
* 数据返回统一处理 参考https://www.jianshu.com/p/ff619fea7e22
* @param <T>
*/
public abstract class BaseObserver<T> implements Observer<Response<BaseResponse<T>>> {
private static final String TAG = "BaseObserver";
@Override
public void onNext(Response<BaseResponse<T>> tResponse) {
Log.e(TAG,"code:==="+tResponse.code());
Log.e(TAG,"errorBody===:"+tResponse.errorBody());
Log.e(TAG,"Body===:"+tResponse.body());
BaseResponse<T> body = tResponse.body();
if(body.getRes_code()==1){
onSuccess(body.getDemo());
}else{
onFailure(new Exception(body.getErr_msg()), body.getErr_msg());
}
}
@Override
public void onError(Throwable e) {
onFailure(e,RxExceptionUtil.exceptionHandler(e));
}
@Override
public void onComplete() {
}
@Override
public void onSubscribe(Disposable d) {
}
public abstract void onSuccess(T result);
public abstract void onFailure(Throwable e,String errorMsg);
}
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import org.json.JSONException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.text.ParseException;
/**
* 异常处理
*/
public class RxExceptionUtil {
public static String exceptionHandler(Throwable e){
String errorMsg = "未知错误";
if (e instanceof UnknownHostException) {
errorMsg = "网络不可用";
} else if (e instanceof SocketTimeoutException) {
errorMsg = "请求网络超时";
} else if (e instanceof HttpException) {
HttpException httpException = (HttpException) e;
errorMsg = convertStatusCode(httpException);
} else if (e instanceof ParseException || e instanceof JSONException
|| e instanceof JSONException) {
errorMsg = "数据解析错误";
}
return errorMsg;
}
private static String convertStatusCode(HttpException httpException) {
String msg;
if (httpException.code() >= 500 && httpException.code() < 600) {
msg = "服务器处理请求出错";
} else if (httpException.code() >= 400 && httpException.code() < 500) {
msg = "服务器无法处理请求";
} else if (httpException.code() >= 300 && httpException.code() < 400) {
msg = "请求被重定向到其他页面";
} else {
msg = httpException.message();
}
return msg;
}
}
(7)Observer加入加载框
/**
* Observer加入加载框
* @param <T>
*/
public abstract class MyObserver<T> extends BaseObserver<T> {
private boolean mShowDialog;
private ProgressDialog dialog;
private Context mContext;
private Disposable d;
public MyObserver(Context context, Boolean showDialog) {
mContext = context;
mShowDialog = showDialog;
}
public MyObserver(Context context) {
this(context,true);
}
@Override
public void onSubscribe(Disposable d) {
this.d = d;
if (!isConnected(mContext)) {
if (d.isDisposed()) {
d.dispose();
}
} else {
if (dialog == null && mShowDialog == true) {
dialog = new ProgressDialog(mContext);
dialog.setMessage("正在加载中");
dialog.show();
}
}
}
@Override
public void onError(Throwable e) {
if (d.isDisposed()) {
d.dispose();
}
hidDialog();
super.onError(e);
}
@Override
public void onComplete() {
if (d.isDisposed()) {
d.dispose();
}
hidDialog();
super.onComplete();
}
public void hidDialog() {
if (dialog != null && mShowDialog == true)
dialog.dismiss();
dialog = null;
}
/**
* 是否有网络连接,不管是wifi还是数据流量
*
* @param context
* @return
*/
public static boolean isConnected(Context context)
{
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info == null)
{
return false;
}
boolean available = info.isAvailable();
return available;
}
}
(8)调度类封装
import android.content.Context;
import com.trello.rxlifecycle2.android.ActivityEvent;
import com.trello.rxlifecycle2.components.RxActivity;
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
import com.trello.rxlifecycle2.components.support.RxFragment;
import com.trello.rxlifecycle2.components.support.RxFragmentActivity;
import io.reactivex.FlowableTransformer;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* 调度类
*/
public class RxHelper {
public static <T> ObservableTransformer<T, T> observableIO2Main(final Context context) {
return upstream -> {
Observable<T> observable = upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
return composeContext(context, observable);
};
}
public static <T> ObservableTransformer<T, T> observableIO2Main(final RxFragment fragment) {
return upstream -> upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).compose(fragment.<T>bindToLifecycle());
}
public static <T> FlowableTransformer<T, T> flowableIO2Main() {
return upstream -> upstream
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
private static <T> ObservableSource<T> composeContext(Context context, Observable<T> observable) {
if(context instanceof RxActivity) {
return observable.compose(((RxActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
} else if(context instanceof RxFragmentActivity){
return observable.compose(((RxFragmentActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
}else if(context instanceof RxAppCompatActivity){
return observable.compose(((RxAppCompatActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
}else {
return observable;
}
}
}
(9)项目请求再次封装 归纳类
import com.trello.rxlifecycle2.components.support.RxFragment;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.reactivex.Observer;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Response;
/**
* 项目请求再次封装 归纳类
*/
public class RequestUtils {
/**
* Get 请求demo
* @param context
* @param observer
*/
public static void getDemo(RxFragment context,MyObserver<Demo> observer){
RetrofitUtils.getApiService()
.getUser().compose(RxHelper.observableIO2Main(context))
.subscribe(observer);
}
/**
* Post 请求demo
* @param context
* @param consumer
*/
public static void postDemo(RxFragment context, String name, String password, Observer<Response<Demo>> consumer){
RetrofitUtils.getApiService()
.postUser(name,password).compose(RxHelper.observableIO2Main(context))
.subscribe(consumer);
}
/**
* Put 请求demo
* @param context
* @param consumer
*/
public static void putDemo(RxFragment context, String access_token,Observer<Response<Demo>> consumer){
Map<String, String> headers = new HashMap<String, String>();
headers.put("Accept","application/json");
headers.put("Authorization",access_token);
RetrofitUtils.getApiService()
.put(headers,"",1,"18","123","厦门").compose(RxHelper.observableIO2Main(context))
.subscribe(consumer);
}
/**
* Delete 请求demo
* @param context
* @param consumer
*/
public static void deleteDemo(RxFragment context, String access_token,Observer<Response<Demo>> consumer){
RetrofitUtils.getApiService()
.delete(access_token,1).compose(RxHelper.observableIO2Main(context))
.subscribe(consumer);
}
/**
* 上传图片
* @param context
* @param observer
*/
public static void upImagView(RxFragment context, String access_token,String str, Observer<Response<Demo>> observer){
File file = new File(str);
// File file = new File(imgPath);
Map<String,String> header = new HashMap<String, String>();
header.put("Accept","application/json");
header.put("Authorization",access_token);
// File file =new File(filePath);
RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
// RequestBody requestFile =
// RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body =
MultipartBody.Part.createFormData("file", file.getName(), reqFile);
RetrofitUtils.getApiService().uploadImage(header,body).compose(RxHelper.observableIO2Main(context))
.subscribe(observer);
}
/**
* 上传多张图片
* @param files
*/
public static void upLoadImg(RxFragment context,String access_token,List<File> files, Observer<Response<Demo>> observer1){
Map<String,String> header = new HashMap<String, String>();
header.put("Accept","application/json");
header.put("Authorization",access_token);
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);//表单类型
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/*"), file);
builder.addFormDataPart("file", file.getName(), photoRequestBody);
}
List<MultipartBody.Part> parts = builder.build().parts();
RetrofitUtils.getApiService().uploadImage1(header,parts).compose(RxHelper.observableIO2Main(context))
.subscribe(observer1);
}
}
三、基本使用
(1)Get请求
RequestUtils.getDemo(this, new MyObserver<Demo>(getActivity()) {
@Override
public void onSuccess(Demo result) {
tvGet.setText(result.toString());
}
@Override
public void onFailure(Throwable e, String errorMsg) {
LogUtils.e(errorMsg);
}
});
(2)Post请求
(没有使用MyObserver,需要根据后台返回的数据来封装适合自己的Obsever)
RequestUtils.postDemo(this, "aaa", "sss", new Observer<Response<Demo>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Response<Demo> loginBeanResponse) {
Log.e(TAG, "onNext: "+ loginBeanResponse.code());
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});