MVP+Retrofit+Rxjava+DataBinding泛型架構模型

一. 用到的知識點:

        UI—面向對象 

        數據交互 —MVP模式

        網絡圖片加載—–glide

        json解析—–gson 

        http請求—retrofit2+rxjava2

        事件總線—-eventbus

        註解—DataBinding

二.目錄結構

 

biz   —————————     業務模塊

bridge  ————————    底層功能實現跟UI層的銜接層 

capabilities  ——————   底層功能具體實現

constant  ———————    常量 

ui  ——————————    界面

util ——————————   業務層公共方法 

view  —————————   自定義view實現

三.解析

1.UI層

用到面向對象的封裝BaseActivity爲基類,同時BaseActivity實現三個接口,分別爲CreateInit,PublishActivityCallBack, PresentationLayerFunc,三個接口的作用依次是:界面初始化,頁面跳轉封裝,頁面交互封裝。PresentationLayerFunc的具體實現是在PresentationLayerFuncHelper裏面,BaseActivity類會初始化該類,把複雜的功能實現抽象出去,輕量化基類。

BaseActivity代碼如下所示:

/**
 * * 備註:
 * 1.XXActivity 繼承 BaseActivity,當頁面存在 Presenter 時,具體 Activity 需要調用 setPresenter(P... presenter)
 * 2.支持一個 Activity 存在多個 Presenter
 *
 * @param <T>
 * @param <V>
 * @param <P> Data:2018/12/18
 * @author yong
 */
public abstract class BaseActivity<T, V extends IMvpView, P extends BasePresenter<V>> extends RxAppCompatActivity implements
        CreateInit.CreateInitActivity<V, P>, PublishActivityCallBack, PresentationLayerFunc, IMvpView<T>, View.OnClickListener {

    protected ActivityMvpDelegate mvpDelegate;

    private PresentationLayerFuncHelper presentationLayerFuncHelper;

    public final String TAG = this.getClass().getSimpleName();

    /**
     * Context對象
     */
    protected static Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getMvpDelegate().onCreate(savedInstanceState);

        presentationLayerFuncHelper = new PresentationLayerFuncHelper(this);
        setContentView(savedInstanceState);
        mContext = this;
        Constants.isStartFragmen = false;

        initData();
        initListeners();
        MyApplication.mApplication.addActivity(this);
        EventBus.getDefault().register(this);
    }

    /**
     * 注入View
     *
     * @return
     */
    @Override
    public V[] createView() {
        V[] views = null;
        P[] pArray = createPresenter();
        if (pArray != null) {
            views = (V[]) new IMvpView[pArray.length];
            for (int i = 0; i < pArray.length; i++) {
                views[i] = (V) this;
            }
        }
        return views;
    }

    /**
     * 關聯Activity的生命週期
     *
     * @return
     */
    @NonNull
    protected ActivityMvpDelegate<V, P> getMvpDelegate() {
        if (mvpDelegate == null) {
            mvpDelegate = new ActivityMvpDelegateImpl(this, this);
        }
        return mvpDelegate;
    }

    /**
     * 事件線
     *
     * @param eventModel
     */
    @Subscribe
    public void onEventMainThread(T eventModel) {

    }

    /**
     * 鏈接Presenter
     *
     * @return
     */
    @Override
    public P[] createPresenter() {
        return getPresenterArray();
    }

    /**
     * 獲取 Presenter 數組
     */
    public abstract P[] getPresenterArray();

    /**
     * 網絡請求的錯誤信息,已在請求中處理提示Toast
     * 如果有特殊處理需重寫
     *
     * @param action 區分不同事件
     * @param code   錯誤碼
     * @param msg    錯誤信息
     */
    @Override
    public void onError(String action, int code, String msg) {

    }

    /**
     * 配合DataBinding點擊事件監聽
     * 添加防止重複點擊
     * 有點擊事件只需重寫
     *
     * @param v
     */
    @Override
    public void onClick(View v) {
        if (Tools.isDoubleClick()) return;
    }

    @Override
    protected void onResume() {
        MyApplication.mApplication.currentActivityName = this.getClass().getName();
        getMvpDelegate().onResume();
        super.onResume();
    }

    @Override
    public void startActivity(Class<?> openClass, Bundle bundle) {
        Intent intent = new Intent(this, openClass);
        if (null != bundle)
            intent.putExtras(bundle);
        startActivity(intent);
    }

    @Override
    public void openActivityForResult(Class<?> openClass, int requestCode, Bundle bundle) {
        Intent intent = new Intent(this, openClass);
        if (null != bundle)
            intent.putExtras(bundle);
        startActivityForResult(intent, requestCode);
    }

    @Override
    public void setResultOk(Bundle bundle) {
        Intent intent = new Intent();
        if (bundle != null) ;
        intent.putExtras(bundle);
        setResult(RESULT_OK, intent);
        finish();
    }

    @Override
    public void showToast(String msg) {
        presentationLayerFuncHelper.showToast(msg);
    }

    @Override
    public void showSoftKeyboard(View focusView) {
        presentationLayerFuncHelper.showSoftKeyboard(focusView);
    }

    @Override
    public void hideSoftKeyboard() {
        presentationLayerFuncHelper.hideSoftKeyboard();
    }

    @Override
    protected void onDestroy() {
        getMvpDelegate().onDestroy();
        MyApplication.mApplication.deleteActivity(this);
        EventBus.getDefault().unregister(this);
        Constants.isStartFragmen = true;

        super.onDestroy();
    }

    @Override
    public void finish() {
        try {
            presentationLayerFuncHelper.hideSoftKeyboard();
        } catch (Exception e) {
            LogUtil.E("finish 輸入法錯誤");
        }
        super.finish();
    }

    //監聽點擊事件 實現點擊頁面上除EditView外的位置隱藏輸入法
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        try {
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                View v = getCurrentFocus();
                if (isShouldHideKeyboard(v, ev)) {
                    presentationLayerFuncHelper.hideKeyboard(v.getWindowToken());
                }
            }
        } catch (Exception e) {
            LogUtil.E("dispatchTouchEvent 輸入法錯誤");
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * 根據EditText所在座標和用戶點擊的座標相對比,來判斷是否隱藏鍵盤,因爲當用戶點擊EditText時則不能隱藏
     *
     * @param v
     * @param event
     * @return
     */

    private boolean isShouldHideKeyboard(View v, MotionEvent event) {
        if (v != null && (v instanceof EditText)) {
            int[] l = {0, 0};
            v.getLocationInWindow(l);
            int left = l[0],
                    top = l[1],
                    bottom = top + v.getHeight(),
                    right = left + v.getWidth();
            if (event.getX() > left && event.getX() < right
                    && event.getY() > top && event.getY() < bottom) {
                // 點擊EditText的事件,忽略它。
                return false;
            } else {
                return true;
            }
        }
        // 如果焦點不是EditText則忽略,這個發生在視圖剛繪製完,第一個焦點不在EditText上,和用戶用軌跡球選擇其他的焦點
        return false;
    }



    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        getMvpDelegate().onSaveInstanceState(outState);
    }

    @Override
    protected void onPause() {
        super.onPause();
        getMvpDelegate().onPause();
    }

    @Override
    protected void onStart() {
        super.onStart();
        getMvpDelegate().onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
        getMvpDelegate().onStop();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        getMvpDelegate().onRestart();
    }

    @Override
    public void onContentChanged() {
        super.onContentChanged();
        getMvpDelegate().onContentChanged();
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        getMvpDelegate().onPostCreate(savedInstanceState);
    }
}

PresentationLayerFuncHelper代碼如下所示:

/**
 * <頁面基礎公共功能實現>
 * Data:2018/12/18
 *
 * @author yong
 */
public class PresentationLayerFuncHelper implements PresentationLayerFunc {

    private Context context;

    public PresentationLayerFuncHelper(Context context) {
        this.context = context;
    }

    /**
     * Toast提示
     *
     * @param msg
     */
    @Override
    public void showToast(String msg) {
        ToastUtil.makeTextShort(context, msg);
    }

    /**
     * 顯示軟鍵盤
     *
     * @param focusView
     */
    @Override
    public void showSoftKeyboard(View focusView) {
        ((Activity) context).getWindow().getDecorView().postDelayed(new Runnable() {
            @Override
            public void run() {
                InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm != null) {
                    focusView.requestFocus();
                    imm.showSoftInput(focusView, 0);
                }
            }
        }, 100);
    }

    /**
     * 隱藏軟鍵盤
     */
    @Override
    public void hideSoftKeyboard() {
        if ((context == null || ((Activity) context).getWindow() == null)) {
            return;
        }
        View view = ((Activity) context).getWindow().peekDecorView();
        if (view == null || view.getWindowToken() == null) {
            return;
        }
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm == null) {
            return;
        }
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

    /**
     * 獲取InputMethodManager,隱藏軟鍵盤
     *
     * @param token
     */
    public void hideKeyboard(IBinder token) {
        if (token != null) {

            InputMethodManager im = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);

            if (im != null) {

                im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);

            }
        }
    }
}

三個接口,分別爲CreateInit, PublishActivityCallBack, PresentationLayerFunc代碼如下所示:

/**
 * <公共方法抽象>
 * Data:2018/12/18
 *
 * @author yong
 */
public interface CreateInit<V extends IMvpView, P extends Presenter> {

    interface CreateInitActivity<V extends IMvpView, P extends Presenter> extends CreateInit<V, P> {
        /**
         * 設置佈局文件
         */
        void setContentView(Bundle savedInstanceState);

    }

    interface CreateInitFragment<V extends IMvpView, P extends Presenter> extends CreateInit<V, P> {
        /**
         * 設置佈局文件
         */
        View initView(LayoutInflater inflater);

    }

    /**
     * 連接P層
     *
     * @return
     */
    P[] createPresenter();

    /**
     * 注入view
     *
     * @return
     */
    V[] createView();

    /**
     * 初始化數據
     */
    void initData();

    /**
     * 增加按鈕點擊事件
     */
    void initListeners();

}
/**
 * <頁面跳轉封裝>
 * Data:2018/12/18
 *
 * @author yong
 */
public interface PublishActivityCallBack {
    /**
     * 打開新界面
     *
     * @param openClass 新開頁面
     * @param bundle    參數
     */
    void startActivity(Class<?> openClass, Bundle bundle);

    /**
     * 打開新界面,期待返回
     *
     * @param openClass   新界面
     * @param requestCode 請求碼
     * @param bundle      參數
     */
    void openActivityForResult(Class<?> openClass, int requestCode, Bundle bundle);

    /**
     * 返回到上個頁面
     *
     * @param bundle 參數
     */
    void setResultOk(Bundle bundle);
}
/**
 * <頁面基礎公共功能抽象>
 * Data:2018/12/18
 *
 * @author yong
 */
public interface PresentationLayerFunc {
    /**
     * 彈出消息
     *
     * @param msg
     */
    void showToast(String msg);

    /**
     * 顯示軟鍵盤
     *
     * @param focusView
     */
    void showSoftKeyboard(View focusView);

    /**
     * 隱藏軟鍵盤
     */
    void hideSoftKeyboard();
}

界面只要繼承BaseLoadActivity,而BaseLoadActivity繼承BaseActivity:BaseLoadActivity是帶空頁面額錯誤顯示頁面

/**
 * <功能詳細描述>
 * 泛型傳入
 * 1、網絡請求實體類:如果有多個實體類可以傳入Object或是通過BaseListMode中set、get方法設置
 * 2、自動生成ViewDataBinding
 * <p>
 * Data:2018/12/18
 *
 * @author yong
 */
public class MainActivity extends BaseLoadActivity<LoginModel, ActivityMainBinding> {

    private LoginPresenter presenter = new LoginPresenter(this);

    @Override
    public int getLayout() {
        return R.layout.activity_main;
    }


    @Override
    public void onSuccess(String action, LoginModel data) {
        mLoadBinding.text.setText(SharedPrefManager.getUser().getString(SharedPrefUser.USER_NAME, ""));
        mLoadBinding.text1.setText(data.getNickName());
        mLoadBinding.bt.setText(action);
    }

    @Override
    public void initListeners() {
        mLoadBinding.bt.setOnClickListener(this);
    }

    @Override
    public void initData() {
//        presenter.login("", "123456");
    }

    @Override
    public BasePresenter<IMvpView<LoginModel>>[] getPresenterArray() {
        return new BasePresenter[]{presenter};
    }

    @Override
    public void onClick(View v) {
        super.onClick(v);
    }
}

2.數據交互層

Presenter與View交互是通過接口:成功,失敗(如有特需處理可以使用此方法)。

/**
 * <功能詳細描述>
 * <p>
 * Data:2018/12/18
 *
 * @author yong
 * <p>
 * action 方式: 考慮多個請求時 根據 action 區分處理
 */
public interface IMvpView<T> {

    /**
     * 網絡請求的錯誤信息,已在請求中處理提示Toast
     *
     * @param action 區分不同事件
     * @param code   錯誤碼
     * @param msg    錯誤信息
     */
    @UiThread
    void onError(String action, int code, String msg);

    /**
     * 成功返回結果
     *
     * @param action 區分不同事件
     * @param data   數據
     */
    @UiThread
    void onSuccess(String action, T data);

}

LoginPresenter 爲登錄的業務實現類:1、業務處理。2.通知頁面數據刷新。Presenter與頁面交互是通過接口實現的,通過繼承基類BasePresenter,從而實現接口attachView(V view),view是個泛型,MainActivity會實現這個接口,在初始化LoginPresenter 的時候,會把自身傳過來loginPresenter.attachView(this),這段代碼是在onCreate中,Presenter通知頁面刷新。在使用BaseModelObserver或是BaseListModelObserver時提供兩個構造器,多參數可以提示加載彈窗和設置點擊返回鍵是否消失加載窗。

/**
 * <基礎業務類>
 * <p>
 * Data:2018/12/18
 *
 * @author yong
 */
public interface Presenter<V> {

    /**
     * 將 View 添加到當前 Presenter
     *
     * @param view
     */
    @UiThread
    void attachView(@NonNull V view);

    /**
     * 將 View 從 Presenter 中移除
     */
    @UiThread
    void detachView();

    /**
     * 銷燬 V 實例
     */
    @UiThread
    void destroy();
}
/**
 * <基礎業務類>
 * <p>
 * Data:2018/12/18
 *
 * @author yong
 */
public abstract class BasePresenter<V extends IMvpView> implements Presenter<V> {

    private WeakReference<V> viewRef;

    private SecurityManager securityManager;

    private RetrofitHttp.Builder retrofitHttp;

    /**
     * 獲取 View
     *
     * @return
     */
    @UiThread
    public V getMvpView() {
        return viewRef == null ? null : viewRef.get();
    }

    /**
     * 判斷View是否已經添加
     *
     * @return
     */
    @UiThread
    public boolean isViewAttached() {
        return viewRef != null && viewRef.get() != null;
    }

    /**
     * 綁定 View
     *
     * @param view
     */
    @UiThread
    @Override
    public void attachView(V view) {
        viewRef = new WeakReference<>(view);
    }

    /**
     * 移除 View
     */
    @Override
    public void detachView() {
        if (viewRef != null) {
            viewRef.clear();
            viewRef = null;
        }
    }

    @Override
    public void destroy() {
    }

    /**
     * MD5加密
     */
    public SecurityManager getSecurityManager() {
        if (securityManager == null)
            securityManager = BridgeFactory.getBridge(Bridges.SECURITY);
        return securityManager;
    }

    /**
     * 網絡請求
     */
    public RetrofitHttp.Builder getRetrofitHttp() {
        if (retrofitHttp == null)
            retrofitHttp = BridgeFactory.getBridge(Bridges.HTTP);
        retrofitHttp.clear();
        retrofitHttp.lifecycle((LifecycleProvider) getMvpView());
        return retrofitHttp;
    }
}
/**
 * <功能詳細描述>
 * <p>
 * Data:2018/12/18
 *
 * @author yong
 */
public class LoginPresenter extends BasePresenter<IMvpView<LoginModel>> {

    private Context context;

    public LoginPresenter(Context context) {
        this.context = context;
    }

    public void login(String userid, String pwd) {

        if (!isViewAttached()) return;

        Map<String, Object> map = new HashMap<>();
        map.put("userid", userid);
        map.put("pwd", pwd);

        getRetrofitHttp().post().apiUrl(UrlConstans.LOGIN)
                .addParameter(map).build()
                .request(new BaseModelObserver<LoginModel>(context) {//BaseListModelObserver:返回數據List集合

                    @Override
                    public void onSuccess(String action, LoginModel value) {
                        getMvpView().onSuccess(action, value);
                    }

                    @Override
                    public void onError(String action, int code, String desc) {//有需要需重寫
                        super.onError(action, code, desc);
                        getMvpView().onError(action, code, desc);
                    }
                });

    }
}

3.網絡層

/**
 * Http請求類
 * <p>
 * Data:2018/12/18
 *
 * @author yong
 */
public class RetrofitHttp {

    /*請求方式*/
    private Method method;
    /*請求參數*/
    private Map<String, Object> parameter;
    /*header*/
    private Map<String, Object> header;
    /*LifecycleProvider*/
    private LifecycleProvider lifecycle;
    /*ActivityEvent*/
    private ActivityEvent activityEvent;
    /*FragmentEvent*/
    private FragmentEvent fragmentEvent;
    /*HttpObserver*/
    private HttpObserver httpObserver;
    /*標識請求的TAG*/
    private String tag;
    /*文件map*/
    private Map<String, File> fileMap;
    /*上傳文件回調*/
    private UploadObserver uploadCallback;
    /*基礎URL*/
    private String baseUrl;
    /*apiUrl*/
    private String apiUrl;
    /*String參數*/
    String bodyString;
    /*是否強制JSON格式*/
    boolean isJson;

    /*構造函數*/
    private RetrofitHttp(Builder builder) {
        this.parameter = builder.parameter;
        this.header = builder.header;
        this.lifecycle = builder.lifecycle;
        this.activityEvent = builder.activityEvent;
        this.fragmentEvent = builder.fragmentEvent;
        this.tag = builder.tag;
        this.fileMap = builder.fileMap;
        this.baseUrl = builder.baseUrl;
        this.apiUrl = builder.apiUrl;
        this.isJson = builder.isJson;
        this.bodyString = builder.bodyString;
        this.method = builder.method;
    }

    /*普通Http請求*/
    public void request(HttpObserver httpObserver) {
        this.httpObserver = httpObserver;
        if (httpObserver == null) {
            throw new NullPointerException("HttpObserver must not null!");
        } else {
            doRequest();
        }
    }

    /*上傳文件請求*/
    public void upload(UploadObserver uploadCallback) {
        this.uploadCallback = uploadCallback;
        if (uploadCallback == null) {
            throw new NullPointerException("UploadObserver must not null!");
        } else {
            doUpload();
        }
    }

    /*執行請求*/
    private void doRequest() {

        /*設置請求唯一標識*/
        httpObserver.setTag(TextUtils.isEmpty(tag) ? disposeApiUrl() : tag);

        /*header處理*/
        disposeHeader();

        /*Parameter處理*/
        disposeParameter();

        /*請求方式處理*/
        Observable apiObservable = disposeApiObservable();

        /* 被觀察者 httpObservable */
        HttpObservable httpObservable = new HttpObservable.Builder(apiObservable)
                .baseObserver(httpObserver)
                .lifecycleProvider(lifecycle)
                .activityEvent(activityEvent)
                .fragmentEvent(fragmentEvent)
                .build();
        /* 觀察者  httpObserver */
        /*設置監聽*/
        httpObservable.observe().subscribe(httpObserver);

    }

    /*執行文件上傳*/
    private void doUpload() {

        /*設置請求唯一標識*/
        uploadCallback.setTag(TextUtils.isEmpty(tag) ? disposeApiUrl() : tag);

        /*header處理*/
        disposeHeader();

        /*Parameter處理*/
        disposeParameter();

        /*處理文件集合*/
        List<MultipartBody.Part> fileList = new ArrayList<>();
        if (fileMap != null && fileMap.size() > 0) {
            int size = fileMap.size();
            int index = 1;
            File file;
            RequestBody requestBody;
            for (String key : fileMap.keySet()) {
                file = fileMap.get(key);
                requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
                MultipartBody.Part part = MultipartBody.Part.createFormData(key, file.getName(), new UploadRequestBody(requestBody, file, index, size, uploadCallback));
                fileList.add(part);
                index++;
            }
        }

        /*請求處理*/
        Observable apiObservable = RetrofitUtils.get().getRetrofit(getBaseUrl(), header).create(Api.class).upload(disposeApiUrl(), parameter, header, fileList);

        /* 被觀察者 httpObservable */
        HttpObservable httpObservable = new HttpObservable.Builder(apiObservable)
                .baseObserver(uploadCallback)
                .lifecycleProvider(lifecycle)
                .activityEvent(activityEvent)
                .fragmentEvent(fragmentEvent)
                .build();
        /* 觀察者  uploadCallback */
        /*設置監聽*/
        httpObservable.observe().subscribe(uploadCallback);

    }

    /*獲取基礎URL*/
    private String getBaseUrl() {
        //如果沒有重新指定URL則是用默認配置
        return TextUtils.isEmpty(baseUrl) ? Configure.get().getBaseUrl() : baseUrl;
    }

    /*ApiUrl處理*/
    private String disposeApiUrl() {
        return TextUtils.isEmpty(apiUrl) ? "" : apiUrl;
    }

    /*處理Header*/
    private void disposeHeader() {

        /*header空處理*/
        if (header == null) {
            header = new TreeMap<>();
        }

        //添加基礎 Header
        Map<String, Object> baseHeader = Configure.get().getBaseHeader();
        if (baseHeader != null && baseHeader.size() > 0) {
            header.putAll(baseHeader);
        }

        if (!header.isEmpty()) {
            //處理header中文或者換行符出錯問題
            for (String key : header.keySet()) {
                header.put(key, RequestUtils.getHeaderValueEncoded(header.get(key)));
            }
        }

    }

    /*處理 Parameter*/
    private void disposeParameter() {

        /*空處理*/
        if (parameter == null) {
            parameter = new TreeMap<>();
        }

        //添加基礎 Parameter
        Map<String, Object> baseParameter = Configure.get().getBaseParameter();
        if (baseParameter != null && baseParameter.size() > 0) {
            parameter.putAll(baseParameter);
        }
    }

    /*處理ApiObservable*/
    private Observable disposeApiObservable() {

        Observable apiObservable = null;

        /*是否JSON格式提交參數*/
        boolean hasBodyString = !TextUtils.isEmpty(bodyString);
        RequestBody requestBody = null;
        if (hasBodyString) {
            String mediaType = isJson ? "application/json; charset=utf-8" : "text/plain;charset=utf-8";
            requestBody = RequestBody.create(okhttp3.MediaType.parse(mediaType), bodyString);
        }

        /*Api接口*/
        Api apiService = RetrofitUtils.get().getRetrofit(getBaseUrl(), header).create(Api.class);
        /*未指定默認POST*/
        if (method == null) method = Method.POST;

        switch (method) {
            case GET:
                apiObservable = apiService.get(disposeApiUrl(), parameter, header);
                break;
            case POST:
                if (hasBodyString)
                    apiObservable = apiService.post(disposeApiUrl(), requestBody, header);
                else
                    apiObservable = apiService.post(disposeApiUrl(), parameter, header);
                break;
            case DELETE:
                apiObservable = apiService.delete(disposeApiUrl(), parameter, header);
                break;
            case PUT:
                apiObservable = apiService.put(disposeApiUrl(), parameter, header);
                break;
        }
        return apiObservable;
    }

    /**
     * Configure配置
     */
    public static final class Configure {

        /*請求基礎路徑*/
        String baseUrl;
        /*超時時長*/
        long timeout;
        /*時間單位*/
        TimeUnit timeUnit;
        /*全局上下文*/
        Context context;
        /*全局Handler*/
        Handler handler;
        /*請求參數*/
        Map<String, Object> parameter;
        /*header*/
        Map<String, Object> header;
        /*是否顯示Log*/
        boolean showLog;


        public static Configure get() {
            return Configure.Holder.holder;
        }

        private static class Holder {
            private static Configure holder = new Configure();
        }

        private Configure() {
            timeout = 60;//默認60秒
            timeUnit = TimeUnit.SECONDS;//默認秒
            showLog = true;//默認打印LOG
        }

        /*請求基礎路徑*/
        public RetrofitHttp.Configure baseUrl(String baseUrl) {
            this.baseUrl = baseUrl;
            return this;
        }

        public String getBaseUrl() {
            return baseUrl;
        }

        /*基礎參數*/
        public RetrofitHttp.Configure baseParameter(Map<String, Object> parameter) {
            this.parameter = parameter;
            return this;
        }

        public Map<String, Object> getBaseParameter() {
            return parameter;
        }

        /*基礎Header*/
        public RetrofitHttp.Configure baseHeader(Map<String, Object> header) {
            this.header = header;
            return this;
        }

        public Map<String, Object> getBaseHeader() {
            return header;
        }

        /*超時時長*/
        public RetrofitHttp.Configure timeout(long timeout) {
            this.timeout = timeout;
            return this;
        }

        public long getTimeout() {
            return timeout;
        }

        /*是否顯示LOG*/
        public RetrofitHttp.Configure showLog(boolean showLog) {
            this.showLog = showLog;
            return this;
        }

        public boolean isShowLog() {
            return showLog;
        }

        /*時間單位*/
        public RetrofitHttp.Configure timeUnit(TimeUnit timeUnit) {
            this.timeUnit = timeUnit;
            return this;
        }

        public TimeUnit getTimeUnit() {
            return timeUnit;
        }

        /*Handler*/
        public Handler getHandler() {
            return handler;
        }

        /*Context*/
        public Context getContext() {
            return context;
        }

        /*初始化全局上下文*/
        public RetrofitHttp.Configure init(Application app) {
            this.context = app.getApplicationContext();
            this.handler = new Handler(Looper.getMainLooper());
            return this;
        }

    }

    /**
     * Builder
     * 構造Request所需參數,按需設置
     */
    public static class Builder implements BridgeLifeCycleListener {
        /*請求方式*/
        Method method;
        /*請求參數*/
        Map<String, Object> parameter;
        /*header*/
        Map<String, Object> header;
        /*LifecycleProvider*/
        LifecycleProvider lifecycle;
        /*ActivityEvent*/
        ActivityEvent activityEvent;
        /*FragmentEvent*/
        FragmentEvent fragmentEvent;
        /*標識請求的TAG*/
        String tag;
        /*文件map*/
        Map<String, File> fileMap;
        /*基礎URL*/
        String baseUrl;
        /*apiUrl*/
        String apiUrl;
        /*String參數*/
        String bodyString;
        /*是否強制JSON格式*/
        boolean isJson;
        private Builder instance;

        public Builder getInstanc() {
            if (instance == null) {
                synchronized (RetrofitHttp.class) {
                    if (instance == null) {
                        instance = new Builder();
                    }
                }
            }
            return instance;
        }

        /*GET*/
        public RetrofitHttp.Builder get() {
            this.method = Method.GET;
            return this;
        }

        /*POST*/
        public RetrofitHttp.Builder post() {
            this.method = Method.POST;
            return this;
        }

        /*DELETE*/
        public RetrofitHttp.Builder delete() {
            this.method = Method.DELETE;
            return this;
        }

        /*PUT*/
        public RetrofitHttp.Builder put() {
            this.method = Method.PUT;
            return this;
        }

        /*基礎URL*/
        public RetrofitHttp.Builder baseUrl(String baseUrl) {
            this.baseUrl = baseUrl;
            return this;
        }

        /*API URL*/
        public RetrofitHttp.Builder apiUrl(@NonNull String apiUrl) {
            this.apiUrl = apiUrl;
            return this;
        }

        /* 增加 Parameter 不斷疊加參數 包括基礎參數 */
        public RetrofitHttp.Builder addParameter(Map<String, Object> parameter) {
            if (this.parameter == null) {
                this.parameter = new TreeMap<>();
            }
            this.parameter.putAll(parameter);
            return this;
        }

        /* 增加 Parameter 不斷疊加參數 包括基礎參數 */
        public RetrofitHttp.Builder addParameter(String key, Object parameter) {
            if (this.parameter == null) {
                this.parameter = new TreeMap<>();
            }
            this.parameter.put(key, parameter);
            return this;
        }

        /*設置 Parameter 會覆蓋 Parameter 包括基礎參數*/
        public RetrofitHttp.Builder setParameter(Map<String, Object> parameter) {
            this.parameter = parameter;
            return this;
        }

        /* 設置String 類型參數  覆蓋之前設置  isJson:是否強制JSON格式    bodyString設置後Parameter則無效 */
        public RetrofitHttp.Builder setBodyString(String bodyString, boolean isJson) {
            this.isJson = isJson;
            this.bodyString = bodyString;
            return this;
        }

        /* 增加 Header 不斷疊加 Header 包括基礎 Header */
        public RetrofitHttp.Builder addHeader(String key, Object header) {
            if (this.header == null) {
                this.header = new TreeMap<>();
            }
            this.header.put(key, header);
            return this;
        }

        /* 增加 Header 不斷疊加 Header 包括基礎 Header */
        public RetrofitHttp.Builder addHeader(Map<String, Object> header) {
            if (this.header == null) {
                this.header = new TreeMap<>();
            }
            this.header.putAll(header);
            return this;
        }

        /*設置 Header 會覆蓋 Header 包括基礎參數*/
        public RetrofitHttp.Builder setHeader(Map<String, Object> header) {
            this.header = header;
            return this;
        }

        /*LifecycleProvider*/
        public RetrofitHttp.Builder lifecycle(LifecycleProvider lifecycle) {
            this.lifecycle = lifecycle;
            return this;
        }

        /*ActivityEvent*/
        public RetrofitHttp.Builder activityEvent(ActivityEvent activityEvent) {
            this.activityEvent = activityEvent;
            return this;
        }

        /*FragmentEvent*/
        public RetrofitHttp.Builder fragmentEvent(FragmentEvent fragmentEvent) {
            this.fragmentEvent = fragmentEvent;
            return this;
        }

        /*tag*/
        public RetrofitHttp.Builder tag(String tag) {
            this.tag = tag;
            return this;
        }

        /*文件集合*/
        public RetrofitHttp.Builder file(Map<String, File> file) {
            this.fileMap = file;
            return this;
        }

        /*一個Key對應多個文件*/
        public RetrofitHttp.Builder file(String key, List<File> fileList) {
            if (fileMap == null) {
                fileMap = new IdentityHashMap();
            }
            if (fileList != null && fileList.size() > 0) {
                for (File file : fileList) {
                    fileMap.put(new String(key), file);
                }
            }
            return this;
        }

        public RetrofitHttp.Builder clear() {
            this.method = Method.POST;
            this.parameter = null;
            this.header = null;
            this.lifecycle = null;
            this.activityEvent = null;
            this.fragmentEvent = null;
            this.tag = "";
            this.fileMap = null;
            this.apiUrl = "";
            this.bodyString = "";
            this.isJson = false;
            this.instance = null;
            return this;
        }

        public RetrofitHttp build() {
            return new RetrofitHttp(this);
        }


        @Override
        public void initOnApplicationCreate(Context context) {

        }

        @Override
        public void clearOnApplicationQuit() {
            clear();
            RequestManagerImpl.getInstance().cancelAll();
        }
    }
}
/**
 * Api接口
 * <p>
 * Data:2018/12/18
 *
 * @author yong
 */
public interface Api {

    /**
     * GET 請求
     *
     * @param url       api接口url
     * @param parameter 請求參數map
     * @param header    請求頭map
     * @return
     */
    @GET
    Observable<JsonElement> get(@Url String url, @QueryMap Map<String, Object> parameter, @HeaderMap Map<String, Object> header);

    /**
     * POST 請求
     *
     * @param url       api接口url
     * @param parameter 請求參數map
     * @param header    請求頭map
     * @return
     */
    @FormUrlEncoded
    @POST
    Observable<JsonElement> post(@Url String url, @FieldMap Map<String, Object> parameter, @HeaderMap Map<String, Object> header);

    /**
     * @param requestBody 用於String/JSON格式數據
     */
    @POST
    Observable<JsonElement> post(@Url String url, @Body RequestBody requestBody, @HeaderMap Map<String, Object> header);

    /**
     * DELETE 請求
     *
     * @param url       api接口url
     * @param parameter 請求參數map
     * @param header    請求頭map
     * @return
     */
    @DELETE
    Observable<JsonElement> delete(@Url String url, @QueryMap Map<String, Object> parameter, @HeaderMap Map<String, Object> header);


    /**
     * PUT 請求
     *
     * @param url       api接口url
     * @param parameter 請求參數map
     * @param header    請求頭map
     * @return
     */
    @FormUrlEncoded
    @PUT
    Observable<JsonElement> put(@Url String url, @FieldMap Map<String, Object> parameter, @HeaderMap Map<String, Object> header);

    /**
     * 多文件上傳
     *
     * @param url       api接口url
     * @param parameter 請求接口參數
     * @param header    請求頭map
     * @param fileList  文件列表
     * @return
     * @Multipart 文件上傳註解 multipart/form-data
     */
    @Multipart
    @POST
    Observable<JsonElement> upload(@Url String url, @PartMap Map<String, Object> parameter, @HeaderMap Map<String, Object> header, @Part List<MultipartBody.Part> fileList);

    /**
     * 斷點續傳下載
     *
     * @param range 斷點下載範圍 bytes= start - end
     * @param url   下載地址
     * @return
     * @Streaming 防止內容寫入內存, 大文件通過此註解避免OOM
     */
    @Streaming
    @GET
    Observable<ResponseBody> download(@Header("RANGE") String range, @Url String url);

}

4.Bridge層抽象

BridgeFactory用來統一管理基礎功能,類似本地服務的實現原理。 實現了文件,網絡,安全等等管理類的實現,並保存了各類管理類的引用。業務層或者上層調用底層實現時,通過BridgeFactory去訪問,而不是直接的調。

/**
 * <中間連接層>
 * Data:2018/12/18
 *
 * @author yong
 */
public class BridgeFactory {

    private static BridgeFactory model;

    private HashMap<String, Object> mBridges;

    private BridgeFactory() {
        mBridges = new HashMap<String, Object>();
    }

    public static void init(Application application) {
        model = new BridgeFactory();
        model.iniLocalFileStorageManager();
        model.initPreferenceManager();
        model.initSecurityManager();
        model.initUserSession();
        model.initOkHttpManager(application);
    }

    public static void destroy() {
        model.mBridges = null;
        model = null;
    }

    /**
     * 初始化本地存儲路徑管理類
     */
    private void iniLocalFileStorageManager() {
        LocalFileStorageManager localFileStorageManager = new LocalFileStorageManager();
        model.mBridges.put(Bridges.LOCAL_FILE_STORAGE, localFileStorageManager);
        BridgeLifeCycleSetKeeper.getInstance().trustBridgeLifeCycle(localFileStorageManager);
    }

    /**
     * 初始化SharedPreference管理類
     */
    private void initPreferenceManager() {
        SharedPrefManager sharedPrefManager = new SharedPrefManager();
        model.mBridges.put(Bridges.SHARED_PREFERENCE, sharedPrefManager);
        BridgeLifeCycleSetKeeper.getInstance().trustBridgeLifeCycle(sharedPrefManager);
    }

    /**
     * 網絡請求管理類
     */
    private void initOkHttpManager(Application application) {
        RetrofitHttp.Configure.get().baseUrl(UrlConstans.SERVER).init(application);
        RetrofitHttp.Builder builder = new RetrofitHttp.Builder().getInstanc();
        model.mBridges.put(Bridges.HTTP, builder);
        BridgeLifeCycleSetKeeper.getInstance().trustBridgeLifeCycle(builder);
    }

    /**
     * 初始化安全模塊
     */
    private void initSecurityManager() {
        SecurityManager securityManager = new SecurityManager();
        model.mBridges.put(Bridges.SECURITY, securityManager);
        BridgeLifeCycleSetKeeper.getInstance().trustBridgeLifeCycle(securityManager);
    }

    /**
     * 初始化用戶信息模塊
     */
    private void initUserSession() {
    }

    /**
     * 通過bridgeKey {@link Bridges}來獲取對應的Bridge模塊
     *
     * @param bridgeKey {@link Bridges}
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <V extends Object> V getBridge(String bridgeKey) {
        final Object bridge = model.mBridges.get(bridgeKey);
        if (bridge == null) {
            throw new NullPointerException("-no defined bridge-");
        }
        return (V) bridge;
    }
}

BridgeLifeCycleListener 接口,實現各個底層功能管理類的統一初始化跟銷燬工作,保持跟app的生命週期一致。

/**
 * 如果Bridge層的生命週期和App的生命週期相關(在Application
 * onCreate的時候初始化,在用戶雙擊back鍵退出),則實現此接口,屆時統一初始化和銷燬
 * Data:2018/12/18
 *
 * @author yong
 */
public interface BridgeLifeCycleListener {
    void initOnApplicationCreate(Context context);

    void clearOnApplicationQuit();
}

5.多頁面交互

EventBus是一款針對Android優化的發佈/訂閱事件總線。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,線程之間傳遞消息。優點是開銷小,代碼更優雅,以及將發送者和接收者解耦。

EventBus.getDefault().register(this);//訂閱事件

EventBus.getDefault().post(object);//發佈事件

EventBus.getDefault().unregister(this);//取消訂閱

Demo下載地址:https://download.csdn.net/download/qq_39735504/10861424

MVP模式封裝框架地址:https://github.com/AgnoiY/MvpLibrary

注意:Demo中提供的登錄接口返回數據類型錯誤,請不要使用,斷點下載的沒有實現的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章