Record of Retrofit+MVP framework encapsulation
Posted by jredwilli on Sat, 02 May 2020 08:14:47 +0200
The most popular combination of network requests, retrofit2+okhttp+rxjava+mvp
This is the sealed record
First, it is divided into modules, such as login
First, the use of encapsulation
package com.fragmentapp.login.presenter;
import android.util.Log;
import com.fragmentapp.base.BasePresenter;
import com.fragmentapp.http.BaseObserver;
import com.fragmentapp.http.BaseResponses;
import com.fragmentapp.login.bean.LoginDataBean;
import com.fragmentapp.login.imple.ILoginModel;
import com.fragmentapp.login.imple.ILoginView;
import com.fragmentapp.login.model.LoginModel;
/**
* Created by liuzhen on 2017/11/3.
*/
public class LoginPresenter extends BasePresenter {
private ILoginView view;
private ILoginModel model;
public LoginPresenter(ILoginView view){
this.view = view;
model = new LoginModel();
}
public void login(String username,String pwd){
model.login(observer,username,pwd);
}
BaseObserver<BaseResponses<LoginDataBean>> observer = new BaseObserver<BaseResponses<LoginDataBean>>(){
@Override
public void onNextResponse(BaseResponses<LoginDataBean> loginDataBean) {
Log.e("token",loginDataBean.getData().getHCACCESSTOKEN()+"");
view.success(loginDataBean.getData());
}
@Override
public void onErrorResponse(BaseResponses<LoginDataBean> loginDataBean) {
view.error();
}
@Override
public void onNetWorkError(String val) {
view.error();
}
};
}
Presenter
Through the interface of the p layer, the model accesses the network request, and then returns the result callback to the view layer to refresh
Here, a base Observer class is customized to avoid multiple delivery interfaces
The model is responsible for calling the network request
package com.fragmentapp.login.model;
import com.fragmentapp.http.BaseObserver;
import com.fragmentapp.http.BaseResponses;
import com.fragmentapp.http.RetrofitHelper;
import com.fragmentapp.login.bean.LoginDataBean;
import com.fragmentapp.login.imple.ILoginModel;
import java.util.HashMap;
import java.util.Map;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created by liuzhen on 2017/11/7.
*/
public class LoginModel implements ILoginModel {
@Override
public void login(final BaseObserver<BaseResponses<LoginDataBean>> observer,String username,String pwd) {
Map<String, String> map = new HashMap<>();
map.put("account[username]", username);
map.put("account[password]", pwd);
RetrofitHelper.getInstance().getService()
.login(map)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
}
}
There are only two interfaces for the callback of view layer, which can be added according to your own needs
package com.fragmentapp.login.imple;
import com.fragmentapp.login.bean.LoginDataBean;
/**
* Created by liuzhen on 2017/11/6.
*/
public interface ILoginView {
void success(LoginDataBean dataBean);
void error();
}
After accessing the network, directly process the result of callback in activity to refresh the interface, etc
Here, the access url of retrofit is to add a header tag to dynamically access and replace the baseurl
package com.fragmentapp.http;
import android.util.Log;
import com.fragmentapp.BuildConfig;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by liuzhen on 2017/11/3.
*/
public class RetrofitHelper {
private static final String BASE_URL_USER = "http://testapi.hanmaker.com";
private static final String BASE_URL_PAY = "https://www.222.com/";
private static final long TIME_OUT = 5000;
private RetrofitHelper(){}
private static class SingleHolder {
private static final RetrofitHelper INSTANCE = new RetrofitHelper();
}
public static final RetrofitHelper getInstance() {
return SingleHolder.INSTANCE;
}
private static final long DEFAULT_TIMEOUT = 15L;
final static Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.serializeNulls()// call serializeNulls Methods, changing gson The default behavior of the object, null Value will be output
.create();
//addInterceptor:Set application interceptor, which can be used to set public parameters, header information, log interception, etc
//addNetworkInterceptor:Network interceptor, which can be used to retry or rewrite
//setLevel NONE(No record) BASIC(request/Response line) HEADER(request/Response line + head) BODY(request/Response line + head + body)
//cookieJar:Stay in the same conversation
//TimeUnit.SECONDS Seconds as units
private static OkHttpClient okHttpClient = new OkHttpClient.Builder()
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.retryOnConnectionFailure(true)//Error reconnection
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
//Obtain request
Request request = chain.request();
if (BuildConfig.DEBUG) {
// Log.e("request",request.toString());
}
//Obtain request Created by builder
Request.Builder builder = request.newBuilder();
//from request Get from headers,By the given key url_name
List<String> headerValues = request.headers("url_name");
if (headerValues != null && headerValues.size() > 0) {
//If you have this header,First, configure the header Delete, so header For use only app and okhttp Use between
builder.removeHeader("url_name");
//Match to get new BaseUrl
String headerValue = headerValues.get(0);
HttpUrl newBaseUrl = null;
if ("user".equals(headerValue)) {
newBaseUrl = HttpUrl.parse(BASE_URL_USER);
} else if ("pay".equals(headerValue)) {
newBaseUrl = HttpUrl.parse(BASE_URL_PAY);
} else{
newBaseUrl = HttpUrl.parse(BASE_URL_USER);
}
//from request Get the original HttpUrl Example oldHttpUrl
HttpUrl oldHttpUrl = request.url();
//Rebuild new HttpUrl,Modify what needs to be modified url Part
HttpUrl newFullUrl = oldHttpUrl
.newBuilder()
.scheme(newBaseUrl.scheme())//Set up network protocol
.host(newBaseUrl.host())//Change host name
.port(newBaseUrl.port())//Replace port
.build();
//Rebuild this request,adopt builder.url(newFullUrl).build();
//Then return to a response This completes the modification
return chain.proceed(builder.url(newFullUrl).build());
} else {
return chain.proceed(request);
}
}
})
.build();
private static Retrofit retrofit = null;
private static <T> T createApi(Class<T> clazz) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL_USER)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
return retrofit.create(clazz);
}
private RetrofitService service = null;
public RetrofitService getService(){
if (service == null)
service = createApi(RetrofitService.class);
return service;
}
}
Then the interface parameters are added in the way of map. I feel that I have to change the service class every time
Then the observable applies a layer of types. Here, it is mainly the background data format, which can be removed
package com.fragmentapp.http;
/**
* Created by liuzhen on 2017/11/3.
*/
public class BaseResponses<T> {
private String info;
private int status;
private T data;
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Then there is the observer class of base, which calls back the user-defined interface according to its own business, so there is no need to overload so many methods every time
package com.fragmentapp.http;
import android.os.Looper;
import android.util.Log;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
/**
* Created by liuzhen on 2017/11/3.
*/
public abstract class BaseObserver<T extends BaseResponses> implements Observer<T> {
String TAG = getClass().getSimpleName();
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG, "onSubscribe");
}
@Override
public void onNext(T t) {
Log.e(TAG, "onNext"+t);
if (t.getStatus() == 200) {
onNextResponse(t);
} else {
Log.e(TAG, "ErrorStatus:" + t.getStatus() + "ErrorInfo" + t.getInfo());
onErrorResponse(t);
}
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError" + e.toString());
onNetWorkError("onError Network timeout, please try again--"+e.getMessage());
if (Looper.myLooper() == null) {
Looper.prepare();
Log.e(TAG,"onError Network timeout, please try again");
Looper.loop();
}
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete");
}
/**Return success*/
public abstract void onNextResponse(T t);
/**Interface failure information*/
public abstract void onErrorResponse(T t);
/**network error*/
public abstract void onNetWorkError(String val);
}
There's nothing to say about this
GitHub: https://github.com/1024477951/FragmentApp