美文网首页
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