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

Topics: Android network Retrofit Java