Nowadays, the combination of RxJava and Retrofit is probably quite common, and I have been using it all the time in my work. During the use process, we will encapsulate and use it. There are also many packaged projects on GitHub that can be used directly. In fact, the secondary packaging of open source frameworks is sometimes more or less different in the process of encapsulation for different business logics. It is recommended to encapsulate and use it yourself. This not only improves one's understanding of the original framework, but also improves one's packaging capabilities. If you need to change it during work, it will be easier to get started. Okay, let’s not say much nonsense, here is a simple sample for your reference.
Add dependencies
compile '.retrofit2:retrofit:2.3.0'
compile '.rxjava2:rxjava:'
implementation '.rxjava2:rxandroid:2.0.2'
implementation '.okhttp3:logging-interceptor:3.10.0'
compile '.retrofit2:converter-gson:2.3.0'
compile '.retrofit2:adapter-rxjava2:2.3.0'
I don’t want to say much about adding dependencies. I think everyone knows it, but when I first came into contact with this knowledge, I wonder if anyone thinks where some dependencies were found and added when reading online articles? For example:.retrofit2:converter-gson:2.3.0
We want to add oneGsonConverter
dependency. Will people who are new to this knowledge and do not often visit GitHub? Regardless of whether it is possible or not, I was really confused when I first came into contact with it. Here is a reminder for those who have been confused that we can view the corresponding dependencies by opening the subfile of the project on GitHub. For example, in the Retrofit project on GitHub:retrofit/retrofit-converters/gson/
You can view the corresponding pathGsonConverter
dependency.
Encapsulation Retrofit (singleton mode)
public class HttpRequest { public static final long CONNECTTIME = 30000; public static final String BASE_URL = "/"; private ApiService apiService; public HttpRequest() { //Add a log interceptor HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new () { @Override public void log(String message) { ("TAG", "==========" + message); } }).setLevel(); //Get OkHttpClient OkHttpClient client = new () .connectTimeout(CONNECTTIME, ) .readTimeout(CONNECTTIME,) .writeTimeout(CONNECTTIME,) .addInterceptor(interceptor) .addNetworkInterceptor(new HttpHeaderInterceptor()) .build(); //Initialize Retrofit Retrofit retrofit = new () .baseUrl(BASE_URL) .addConverterFactory(()) .addCallAdapterFactory(()) .client(client) .build(); apiService = (); } // Create a single case private static class SingletonHolder { private static final HttpRequest INSTANCE = new HttpRequest(); } public static ApiService getApi(){ return ; } }
Here we can see that two interceptors have been added: log interceptor and network request header interceptor. We all know that for Retrofit we can directly passGsonConverter
Convert it to entity class, but sometimes we want to get its json data for viewing. At this time, we can do it by adding a log interceptor, but we must set it up.setLevel
Method: Set different attributes to print the data. As for adding the header interceptor, I think everyone should know that the headers required for the interface are the same in normal work, so we need to add them uniformly:
public class HttpHeaderInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = (); Request build = () // .addHeader("","") Add header .build(); return (build); } }
Encapsulation entity class
{ "code": 1, "msg": "The operation is successful", "data": {······} }
Usually the json data we get from the server is like the above, and some returned fields have fixed formats, such as: code and msg. Some are uncertain, such as: data. At this time, we need to process it twice, and we can write a base class:
public class BaseBean<T> { private int code; private String msg; private T data; public int getCode() { return code; } public void setCode(int code) { = code; } public String getMsg() { return msg; } public void setMsg(String msg) { = msg; } public T getData() { return data; } public void setData(T data) { = data; } }
Use generics to represent data in uncertain formats. Here is a test using an interface to obtain data from all provinces across the country:
public interface ApiService { //Get the province list @GET("common/areas") Flowable<BaseBean<List<Province>>> province(); }
After the entity class is encapsulated, we can perform a test:
() .province() .subscribeOn(()) .observeOn(()) .subscribe(new Subscriber<BaseBean<List<Province>>>() { @Override public void onSubscribe(Subscription s) { } @Override public void onNext(BaseBean<List<Province>> listBaseBean) { } @Override public void onError(Throwable t) { } @Override public void onComplete() { } }); }
Through the above code, it is not difficult to see that this is the effect after being encapsulated, but we will find that we have to add scheduler and rewrite such requests every time.Subscriber
How many ways? Wouldn't that be very cumbersome? Yes, next we will encapsulate these.
Use the compose operator
public class SchedulersHelper implements FlowableTransformer{ @Override public Publisher apply(Flowable upstream) { return (()) .observeOn(()); } }
Use the compose operator to directly operate on the current Flowable, so we can naturally add the operation of switching threads here. Next is Subscriber encapsulation.
Encapsulated Subscriber
public abstract class MySubscriber<T> implements Subscriber<T>{ @Override public void onSubscribe(Subscription s) { (Long.MAX_VALUE); showLoading(); } @Override public void onNext(T t) { // Code is 1, which means that the server returns successful data if (((BaseBean)t).getCode() == 1) { //After successful, return data data for processing onSuccess((T) ((BaseBean) t).getData()); }else { //The processing server returns the error code } } @Override public void onComplete() { finishLoading(); } @Override public void onError(Throwable t) { finishLoading(); // Handle network exceptions ("TAG","=========" + t); } protected abstract void onSuccess(T t); protected abstract void showLoading(); protected abstract void finishLoading(); }
As shown above, we judge whether the code returned by the server is successful and pass the data data out. We can handle both the error code returned by the server and the network request error here. Then we go to test the interface.
test
().province() .compose(new SchedulersHelper()) .subscribe(new MySubscriber() { @Override protected void onSuccess(Object o) { } @Override protected void showLoading() { } @Override protected void finishLoading() { } });
You can see that the operation process has become very simple, forshowLoading()
andfinishLoading()
We don’t need to put these two methods here. This is something I can easily test and write them in.
Finish
This is a very simple encapsulation process without using too much complex logic. It is relatively easy to understand, and the packaging may not be very perfect. You can use it as a reference and use your own understanding to better encapsulate it. I have written a simple MVP base class before, and I put it in the previous project. It forms a simple and easy to understand and easy to use: RxJava + Retrofit + MVP demo, which is placed on GitHub, you can check it outRxRetrofitMvp. If you think it is helpful to you, please give me a star, hahaha!
This is the end of this article about the detailed explanation of the use of Android RxJava and Retrofit. For more related content on Android RxJava and Retrofit, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!