一. 用到的知识点:
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中提供的登录接口返回数据类型错误,请不要使用,断点下载的没有实现的