-
前言
-
1. 简介
- 1.1.架构介绍
-
1.2.项目结构
-
- 1.2.2.1 buis_home (页面组件)
- 1.2.2.2 buis_profile (页面组件)
- 1.2.2.3 buis_personal (页面组件
- 1.2.2.4 buis_main (主容器组件 用于填充首页各tab 组件)基础核心库
- 1.2.2.1 buis_splash (欢迎页启动页面组件)
- 1.2.2.2 buis_login (登录组件)
- 1.2.2.3 buis_inquery (问诊业务组件)
- 1.2.2.4 buis_shop (云药房业务组件)
- 1.2.2.5 service_debugtool (调试debug组件 用于切换环境等
- 1.2.2.6 service_track(用户行为日志统计组件)基础核心库
- 1.2.2.7 service_web (h5 web相关组件)基础核心库
- 1.2.2.8 service_ocr (实名认证组建)基础核心库
- 1.2.2.9 service_pay (支付组件 封装微信支付宝等支付平台对接)基础核心库
- 1.2.2.10 service_push (推送组件)基础核心库
- 1.2.2.11 service_gaode (高德服务组件)基础核心库
-
1. 简介
1.1 架构介绍
- 项目基础架构为MVVM +JetPack +Java+Kotlin+Retrofit+RxJava+组件化+Maven
1.2 项目结构
项目整体结构由基础功能库+功能组件+页面组件+服务化
- 1.2.1 基础公共库
1.2.1.1 lib_ui 为公共UI资源库包含自定义widget ,公共资源以及属性值
1.2.1.2 lib_util 为公用工具类 基本包含所需,后续可进行原有进行扩展
image.png1.2.1.2 lib_net 由网络基础库,只负责网络请求,不提供业务逻辑
由原先网络库基础上抽取抽象接口 INetExceptionHandler.提供给主工程实现达到业务分离
class HttpNetExceptionHandler : NetExceptionHandler() {
override fun handleException(e: Throwable): NetThrowable {
if (e is HttpException) {
try {
val params =
ArrayMap<String, Any>()
params["status_code"] = e.code()
if (e.code() == 400) {
val string = e.response()!!.errorBody()!!.string()
val jsonObject = JSONObject(string)
val serverTime = jsonObject.getLong("server_time")
ServerTimeUtils.setServerTime(serverTime)
}
val raw = e.response()!!.raw()
val httpUrl = raw.request().url()
val schemeHost = httpUrl.scheme() + "://" + httpUrl.host()
params["url"] = schemeHost
} catch (e1: Exception) {
e1.printStackTrace()
}
}
return super.handleException(e)
}
}
public class AppAplication extends BaseApplication {
/**
* 只有BuildConfig.DEBUG 在debug 模式下
* 才会去切换环境 默认情况都为线上 release 环境
*/
private fun switchHttp() {
if (BuildConfig.DEBUG) {
UrlUtils.setType(DebugToolProvider.getDebugService().currentEnv)
} else {
UrlUtils.changeToRelease()
}
//网络请求库
//网络请求库
RetrofitHelp.getInstance()
.addInterceptor(NetworkInterceptor())
.addInterceptor(RefreshInterceptor())
.addInterceptor(MoreBaseUrlInterceptor())
.build()
HttpConfig.setNetExceptionHandler(HttpNetExceptionHandler())
}
1.2.1.2 lib_core 项目基础框架核心库,封装项目基础架构
lib_core 为支撑项目基础框架核心库
2.1 maven更新流程
-
maven更新步骤为以下流程:
构建脚本
image.png - 依赖脚本
在当前model 添加
apply from: './nexus-push.gradle'
-
上传maven
image.png
2.1 上传远程仓库(Git)
将更新的maven仓库推送到远程git 保证最新代码大家维护
3 项目基本使用介绍
- 3.1 mvvm 简单封装
public abstract class JetNetLiveDataMap<T> {
private MutableLiveData<DataWrapper<T>> mLiveData;
private Disposable mDisposable;
public JetNetLiveDataMap() {
this(null, false);
}
public JetNetLiveDataMap(Context context, boolean isShowDialog) {
this.mLiveData = fetchAsyncLiveData(context, isShowDialog);
}
private MutableLiveData<DataWrapper<T>> fetchAsyncLiveData(Context context, boolean isShowDialog) {
MutableLiveData<DataWrapper<T>> liveData = new MutableLiveData<>();
CommonObserver<T> observer;
observer = new CommonObserver<T>() {
@Override
public void onResult(T result) {
setSuccess(result);
}
@Override
public void onError(HttpThrowable httpThrowable) {
setFail(httpThrowable.throwable);
}
};
mDisposable = createCall().subscribeWith(observer);
return liveData;
}
protected DataWrapper<T> setFail(Throwable exception) {
DataWrapper<T> typeDataWrapper = new DataWrapper<>();
typeDataWrapper.setStatus(Status.FAIL);
typeDataWrapper.setNetException(exception);
mLiveData.postValue(typeDataWrapper);
return typeDataWrapper;
}
protected DataWrapper<T> setSuccess(T resultEntity) {
DataWrapper<T> typeDataWrapper = new DataWrapper<>();
typeDataWrapper.setStatus(Status.SUCCESS);
typeDataWrapper.setData(resultEntity);
mLiveData.postValue(typeDataWrapper);
return typeDataWrapper;
}
public Disposable getDisposable() {
return mDisposable;
}
public LiveData<DataWrapper<T>> asLiveData() {
return mLiveData;
}
protected abstract Observable<T> createCall();
}
- 使用方式
override fun unBind(): LiveData<DataWrapper<WeatherModel>> { val id = "${BindDevicesInfoManager.familyMemberBindIotInfo[0].familyMemberIot!!.id}" val fid = "${BindDevicesInfoManager.familyMemberBindIotInfo[0].familyMemberIot!!.familyMemberId}" val listASyncLiveDataMap: JetNetLiveDataMap<WeatherModel> = object : JetNetLiveDataMap<WeatherModel>() { override fun createCall(): Observable<WeatherModel> { return HttpManager.getApiService(HealthApiService::class.java).unBind(fid, id).compose(RxSchedulers.observableCompose()) } } addDisposable(listASyncLiveDataMap.disposable) return listASyncLiveDataMap.asLiveData() }
基础Dilog 封装 BaseDialogFragement
使用实例
public class PermessionDialog extends BaseDialogFragment {
private ICallBackInterface iCallBackInterface;
public static PermessionDialog newInstance(){
PermessionDialog permessionDialog=new PermessionDialog();
return permessionDialog;
}
@Override
public int intLayoutId() {
return R.layout.splash_auth_dialog;
}
@Override
public void convertView(ViewHolder holder, BaseDialogFragment dialog) {
holder.getView(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
iCallBackInterface.confirm();
}
});
}
public interface ICallBackInterface{
void confirm();
}
public void setInterface(ICallBackInterface iCallBackInterface){
this.iCallBackInterface=iCallBackInterface;
}
}
-
3.3 路由
- 3.3.1 路由基础封装
所有web协议按dsl:///web/webview?title=nihao&url=https%3A%2F%2Fmbd.baidu去划分
public class RouterSdk {
private RouterManager mRouterManager;
private static class Holder {
private static RouterSdk mInstance = new RouterSdk();
}
public static RouterSdk getInstance() {
return Holder.mInstance;
}
private RouterSdk() {
}
public void init(boolean debug, Application application) {
if (this.mRouterManager == null) {
this.mRouterManager = new RouterManagerImpl();
mRouterManager.init(debug, application);
}
}
/**
* 传入的是全路径scheme --> dsl:///web/webview?title=nihao&url=https%3A%2F%2Fmbd.baidu
* 可能包含参数 注意跳转web 页面情况下url 必须先URLEncoder.encode 去掉= ?& 以便后续解析
*
* @param url
*/
public void navigation(String url) {
if (mRouterManager != null && !TextUtils.isEmpty(url)) {
mRouterManager.navigation(url);
}
}
/**
* 用于web协议跳转 不带title
*
* @param scheme
* @param url
*/
public void navigationWeb(String scheme, String url) {
if (mRouterManager != null && !TextUtils.isEmpty(url) && !TextUtils.isEmpty(scheme)) {
mRouterManager.navigationWeb(scheme, url, "");
}
}
/**
* 用于web 协议跳转 带title
*
* @param scheme
* @param url
* @param title
*/
public void navigationWebWithTitle(String scheme, String url, String title) {
if (mRouterManager != null && !TextUtils.isEmpty(url) && !TextUtils.isEmpty(scheme) && !TextUtils.isEmpty(title)) {
mRouterManager.navigationWeb(scheme, url, title);
}
}
}
-
3.3.1 路由交互
- 以登录组件为例,所有的登录业务逻辑全部由登录组件封装提供,暴露入口:
- 是否已完成登陆
- 提供用户信息
- 跳转完登录继续执行下一步
- 以登录组件为例,所有的登录业务逻辑全部由登录组件封装提供,暴露入口:
if (!ServiceProvider.getLoginService().isLogin()) {
dataWrapper.showUnReadMessageViews(MainActivity.this, false, navigation, FRAGMENT_PERSONAL);
return;
}
userModel =ServiceProvider.getLoginService().getUserModel();
ServiceProvider.getLoginService().doLoginFun(mContext, () -> {
if (!TextUtils.isEmpty(model.getLink())) {
if (model.getLink().contains("?")) {
bundle.putString(Constant.URL, model.getLink() + "&access_token=" + ServiceProvider.getLoginService().getToken());
} else {
bundle.putString(Constant.URL, model.getLink() + "?access_token=" + ServiceProvider.getLoginService().getToken());
}
ServiceProvider.getWebService().openHospitalH5Activity(mContext, bundle);
}
});
4. 一些优化
- 启动优化 在application 初始化增加一些优先级
```
/**
* 运行在子线程且必须在onCreate初始化完成的
*/
protected abstract void initOnCreateSubComplete();
/**
* 运行在子线程且不等待是否完成
*/
protected abstract void initOnCreateSub();
/**
* 运行在主线程且在onCreate初始化完成的 比如arouter 的初始化
*/
protected abstract void initOnCreateMainTreadComplete();
/**
* 运行在空闲时期的主中
*/
protected abstract void idleMainThreadRun();
```
- 整理统一管理activity 类
public class AppManagerUtil {
static final int FLAG_CLEAR_TOP = 0;
static final int FLAG_CLEAR_OLD = 1;
private static List<Activity> activities = Collections.synchronizedList(new LinkedList<Activity>());
private static Map<Class<? extends Activity>, Integer> singleInstanceActivities = Collections.synchronizedMap(new HashMap<Class<? extends Activity>, Integer>());
private static List<Activity> mainlists = new ArrayList<>();
public static void addMainActivity(Activity activity) {
mainlists.add(activity);
}
public static Activity getMainActivity() {
if (mainlists.size()>0){
return mainlists.get(0);
}
return null;
}
public static void addSingleInstanceActivity(Class<? extends Activity> cls, @Flag int flag) {
singleInstanceActivities.put(cls, flag);
}
/**
* 判断Android程序是否在前台运行
*/
public static boolean isAppOnForeground(Application application) {
android.app.ActivityManager activityManager = (android.app.ActivityManager) application.getSystemService(Context.ACTIVITY_SERVICE);
if (activityManager == null) {
return false;
}
List<android.app.ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
String packageName = application.getPackageName();
for (android.app.ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.processName.equals(packageName) && appProcess.importance == android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true;
}
}
return false;
}
/**
* APP从后台切换回前台
*/
public static void returnToForeground(Application application) {
if (!isAppOnForeground(application)) {
Activity currentActivity = currentActivity();
if (currentActivity != null) {
Intent intent = new Intent(application, currentActivity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
application.startActivity(intent);
}
}
}
public static boolean isMainProcess(Application application) {
String mainProcessName = application.getPackageName();
String processName = currentProcessName(application);
return TextUtils.equals(processName, mainProcessName);
}
public static String currentProcessName(Context context) {
int pid = Process.myPid();
android.app.ActivityManager activityManager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (activityManager != null) {
for (android.app.ActivityManager.RunningAppProcessInfo processInfo : activityManager.getRunningAppProcesses()) {
if (processInfo.pid == pid) {
return processInfo.processName;
}
}
}
return null;
}
/**
* 获取当前Activity
*/
public static Activity currentActivity() {
if (activities == null || activities.isEmpty()) {
return null;
}
return activities.get(activities.size() - 1);
}
/**
* 按照指定类名找到activity
*/
public static Activity findActivity(Class<?> cls) {
if (cls == null) {
return null;
}
if (activities == null || activities.isEmpty()) {
return null;
}
for (Activity activity : activities) {
if (activity.getClass().equals(cls)) {
return activity;
}
}
return null;
}
/**
* 结束当前Activity
*/
public static void finishCurrentActivity() {
finishActivity(currentActivity());
}
/**
* 结束指定的Activity
*/
public static void finishActivity(Activity activity) {
if (activity == null) {
return;
}
if (activities == null || activities.isEmpty()) {
return;
}
activities.remove(activity);
activity.finish();
activity = null;
}
/**
* 结束指定类名的Activity
*/
public static void finishActivity(Class<? extends Activity> cls) {
if (cls == null) {
return;
}
if (activities == null || activities.isEmpty()) {
return;
}
for (int i = activities.size() - 1; i >= 0; i--) {
Activity activity = activities.get(i);
if (cls.equals(activity.getClass())) {
finishActivity(activity);
}
}
}
/**
* 结束所有Activity
*/
public static void finishAllActivity() {
if (activities == null || activities.isEmpty()) {
return;
}
for (int i = activities.size() - 1; i >= 0; i--) {
Activity activity = activities.get(i);
if (!activity.isFinishing()) {
activity.finish();
}
}
activities.clear();
}
/**
* 退出应用程序
*/
public static void exitApp() {
finishAllActivity();
}
public static void finishActivityWithoutCount(int count) {
if (activities == null || activities.isEmpty()) {
return;
}
if (count <= 0) {
finishAllActivity();
return;
}
for (int i = activities.size() - 1; i >= count; i--) {
finishActivity(activities.get(i));
}
}
public static void finishActivityWithout(Class<? extends Activity> cls) {
if (cls == null) {
finishAllActivity();
return;
}
if (activities == null || activities.isEmpty()) {
return;
}
for (int i = activities.size() - 1; i >= 0; i--) {
Activity activity = activities.get(i);
if (!cls.equals(activity.getClass())) {
finishActivity(activity);
}
}
}
public static void finishActivityWithout(Activity activity) {
if (activity == null) {
finishAllActivity();
return;
}
finishActivityWithout(activity.getClass());
}
public static void activityCreated(Activity activity) {
if (activity == null) {
return;
}
Class<? extends Activity> cls = activity.getClass();
if (!singleInstanceActivities.containsKey(cls)) {
activities.add(activity);
return;
}
int flag = singleInstanceActivities.get(cls);
switch (flag) {
default:
throw new UnsupportedOperationException("Flag not find");
case FLAG_CLEAR_TOP:
int oldPos = -1;
for (int i = 0; i < activities.size(); i++) {
if (cls.equals(activities.get(i).getClass())) {
oldPos = i;
}
}
if (oldPos >= 0) {
for (int i = activities.size() - 1; i >= oldPos; i--) {
Activity top = activities.get(i);
if (!top.isFinishing()) {
top.finish();
}
}
}
break;
case FLAG_CLEAR_OLD:
for (int i = activities.size() - 1; i >= 0; i--) {
Activity old = activities.get(i);
if (cls.equals(old.getClass()) && !old.isFinishing()) {
old.finish();
}
}
break;
}
activities.add(activity);
}
public static void activityDestroyed(Activity activity) {
if (activity == null) {
return;
}
if (activities == null || activities.isEmpty()) {
return;
}
if (activities.contains(activity)) {
activities.remove(activity);
}
}
public static void clearMainActivity() {
if (mainlists != null) {
for (Activity activity : mainlists) {
if (!activity.isFinishing()) {
activity.finish();
}
}
mainlists.clear();
}
}
public static void registerActivityListener(Application application) {
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
activityCreated(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
activityDestroyed(activity);
}
});
}
@IntDef({FLAG_CLEAR_TOP, FLAG_CLEAR_OLD})
@Retention(RetentionPolicy.SOURCE)
@interface Flag {
}
}
-
删除 application 初始化 自定义路径 低版本手机
image.png
-
单点缩放收拾动画 导致viewpager 越界问题
image.png
....
项目拉取采用脚本 根据配置文件动态获取需要的组件:
配置文件模版
gradle.ext.moduleConfigs = [
//业务模块
[
name : "buis_search",
git_branch: "master",
style : 1
],
[
name : "buis_inquery",
git_branch: "master",
style : 1
],
[
name : "buis_message",
git_branch: "master",
style : 1
],
[
name : "buis_splash",
git_branch: "master",
style : 1
],
[
name : "buis_profile",
git_branch: "master",
style : 1
],
[
name : "buis_main",
git_branch: "master",
style : 1
],
[
name : "buis_shop",
git_branch: "master",
style : 1
],
[
name : "buis_login",
git_branch: "master",
style : 1
],
[
name : "buis_home",
git_branch: "master",
style : 1
],
[
name : "kit_update",
git_branch: "master",
style : 1
],
[
name : "kit_im",
git_branch: "master",
style : 1
],
[
name : "kit_util",
git_branch: "master",
style : 1
],
[
name : "kit_ui",
git_branch: "master",
style : 1
],
[
name : "kit_core",
git_branch: "master",
style : 1
],
[
name : "kit_wx",
git_branch: "master",
style : 1
],
[
name : "kit_router",
git_branch: "master",
style : 1
],
[
name : "kit_net",
git_branch: "master",
style : 1
],
[
name : "service_push",
git_branch: "master",
style : 1
],
[
name : "service_track",
git_branch: "master",
style : 1
],
[
name : "service_debugtool",
git_branch: "master",
style : 1
],
[
name : "service_web",
git_branch: "master",
style : 1
],
[
name : "service_gaode",
git_branch: "master",
style : 1
],
[
name : "service_pay",
git_branch: "master",
style : 1
],
[
name : "service_ocr",
git_branch: "master",
style : 1
],
//注意interface是用一个git仓库
[
name : "interface",
git_branch: "master",
style : 1
],
]
//0 无插件,1本地插件 2远程插件
gradle.ext.pluginStyle = 2
项目用到的第三方库
- glide 图片加载
- rx 系列
- klog log 工具
- 列表 BaseRecyclerViewAdapterHelper
-轮播 youthBanner - 权限 rxpermission
- 相册 pictureselector
网友评论