美文网首页
2020-10-29

2020-10-29

作者: 程序员阿兵 | 来源:发表于2020-11-18 13:22 被阅读0次

    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.png

    1.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

    相关文章

      网友评论

          本文标题:2020-10-29

          本文链接:https://www.haomeiwen.com/subject/dlbkvktx.html