allen 4 gadi atpakaļ
revīzija
f4f450bfad
100 mainītis faili ar 11307 papildinājumiem un 0 dzēšanām
  1. 10 0
      .gitignore
  2. 1 0
      app/.gitignore
  3. 128 0
      app/build.gradle
  4. 592 0
      app/proguard-rules.pro
  5. BIN
      app/release/app-release.apk
  6. 1 0
      app/release/output.json
  7. 26 0
      app/src/androidTest/java/com/enation/javashop/android/ExampleInstrumentedTest.java
  8. 146 0
      app/src/main/AndroidManifest.xml
  9. 4 0
      app/src/main/assets/config.javashop
  10. 7 0
      app/src/main/code/com/enation/app/javashop/WBShareActivity.kt
  11. 26 0
      app/src/main/code/com/enation/app/javashop/activity/SchemeActivity.kt
  12. 173 0
      app/src/main/code/com/enation/app/javashop/application/Application.kt
  13. 8 0
      app/src/main/code/com/enation/app/javashop/apshare/ShareEntryActivity.kt
  14. 9 0
      app/src/main/code/com/enation/app/javashop/wxapi/WXEntryActivity.kt
  15. 59 0
      app/src/main/code/com/enation/app/javashop/wxapi/WXPayEntryActivity.kt
  16. 63 0
      app/src/main/res/layout/notification_lay.xml
  17. 17 0
      app/src/test/java/com/enation/javashop/android/ExampleUnitTest.java
  18. 115 0
      build.gradle
  19. 1 0
      cart/.gitignore
  20. 124 0
      cart/build.gradle
  21. 21 0
      cart/proguard-rules.pro
  22. 26 0
      cart/src/androidTest/java/com/enation/javashop/android/component/cart/ExampleInstrumentedTest.java
  23. 13 0
      cart/src/main/AndroidManifest.xml
  24. 15 0
      cart/src/main/ApkBuildDir/AndroidManifest.xml
  25. 81 0
      cart/src/main/code/apkbuild/CartApplication.kt
  26. 31 0
      cart/src/main/code/com/enation/javashop/android/component/cart/activity/CartActivity.kt
  27. 199 0
      cart/src/main/code/com/enation/javashop/android/component/cart/adapter/CartGoodsItemAdapter.kt
  28. 93 0
      cart/src/main/code/com/enation/javashop/android/component/cart/adapter/CartPromotionItemAdapter.kt
  29. 129 0
      cart/src/main/code/com/enation/javashop/android/component/cart/adapter/CartShopItemAdapter.kt
  30. 100 0
      cart/src/main/code/com/enation/javashop/android/component/cart/adapter/CartSinglePromotionItemAdapter.kt
  31. 16 0
      cart/src/main/code/com/enation/javashop/android/component/cart/di/CartComponent.kt
  32. 424 0
      cart/src/main/code/com/enation/javashop/android/component/cart/fragment/CartFragment.kt
  33. 26 0
      cart/src/main/code/com/enation/javashop/android/component/cart/launch/CartLaunch.kt
  34. 26 0
      cart/src/main/code/com/enation/javashop/android/component/cart/util/BaseCartItemAdapter.kt
  35. 91 0
      cart/src/main/code/com/enation/javashop/android/component/cart/util/CartActionAgreement.kt
  36. 11 0
      cart/src/main/res/layout/cart_act_lay.xml
  37. 157 0
      cart/src/main/res/layout/cart_frag_lay.xml
  38. 361 0
      cart/src/main/res/layout/cart_goods_item.xml
  39. 66 0
      cart/src/main/res/layout/cart_promotion_item.xml
  40. 104 0
      cart/src/main/res/layout/cart_shop_item.xml
  41. 41 0
      cart/src/main/res/layout/cart_single_promotion_lay.xml
  42. 3 0
      cart/src/main/res/values/strings.xml
  43. 17 0
      cart/src/test/java/com/enation/javashop/android/component/cart/ExampleUnitTest.java
  44. 1 0
      common/.gitignore
  45. 275 0
      common/build.gradle
  46. BIN
      common/libs/chinese2py.jar
  47. 17 0
      common/proguard-rules.pro
  48. 26 0
      common/src/androidTest/java/com/enation/javashop/android/lib/ExampleInstrumentedTest.java
  49. 18 0
      common/src/main/AndroidManifest.xml
  50. 156 0
      common/src/main/code/com/enation/javashop/android/lib/adapter/BaseDelegateAdapter.kt
  51. 114 0
      common/src/main/code/com/enation/javashop/android/lib/adapter/ListViewBaseAdapter.kt
  52. 171 0
      common/src/main/code/com/enation/javashop/android/lib/adapter/TextViewDelegateAdapter.kt
  53. 74 0
      common/src/main/code/com/enation/javashop/android/lib/adapter/VlayoutHolderAdapter.kt
  54. 302 0
      common/src/main/code/com/enation/javashop/android/lib/base/BaseActivity.kt
  55. 99 0
      common/src/main/code/com/enation/javashop/android/lib/base/BaseApplication.kt
  56. 84 0
      common/src/main/code/com/enation/javashop/android/lib/base/BaseContract.kt
  57. 32 0
      common/src/main/code/com/enation/javashop/android/lib/base/BaseControl.kt
  58. 274 0
      common/src/main/code/com/enation/javashop/android/lib/base/BaseFragment.kt
  59. 41 0
      common/src/main/code/com/enation/javashop/android/lib/base/BaseLaunch.kt
  60. 49 0
      common/src/main/code/com/enation/javashop/android/lib/base/DisposableManager.kt
  61. 384 0
      common/src/main/code/com/enation/javashop/android/lib/base/GalleryActivity.kt
  62. 136 0
      common/src/main/code/com/enation/javashop/android/lib/base/GalleryFragment.kt
  63. 81 0
      common/src/main/code/com/enation/javashop/android/lib/base/RxPresenter.kt
  64. 103 0
      common/src/main/code/com/enation/javashop/android/lib/bind/BaseBindingHelper.kt
  65. 97 0
      common/src/main/code/com/enation/javashop/android/lib/core/framework/ActivityLifeController.kt
  66. 67 0
      common/src/main/code/com/enation/javashop/android/lib/core/framework/Framework.kt
  67. 161 0
      common/src/main/code/com/enation/javashop/android/lib/core/framework/InstallResourceHelper.kt
  68. 75 0
      common/src/main/code/com/enation/javashop/android/lib/core/framework/JavaShopInstrumentationHook.java
  69. 269 0
      common/src/main/code/com/enation/javashop/android/lib/core/framework/ResourceManager.java
  70. 141 0
      common/src/main/code/com/enation/javashop/android/lib/core/framework/UnInstallResourceHelper.kt
  71. 68 0
      common/src/main/code/com/enation/javashop/android/lib/core/hack/AndroidHack.kt
  72. 23 0
      common/src/main/code/com/enation/javashop/android/lib/core/runtime/ClassNotFoundInterceptor.kt
  73. 136 0
      common/src/main/code/com/enation/javashop/android/lib/core/runtime/JavaShopActivityTask.kt
  74. 59 0
      common/src/main/code/com/enation/javashop/android/lib/core/split/ComponentManager.kt
  75. 36 0
      common/src/main/code/com/enation/javashop/android/lib/core/split/ComponentManagerImpl.kt
  76. 15 0
      common/src/main/code/com/enation/javashop/android/lib/jni/CommonJNI.kt
  77. 466 0
      common/src/main/code/com/enation/javashop/android/lib/utils/AppTool.kt
  78. 47 0
      common/src/main/code/com/enation/javashop/android/lib/utils/AutoClearHelper.kt
  79. 69 0
      common/src/main/code/com/enation/javashop/android/lib/utils/AutoClearValue.kt
  80. 53 0
      common/src/main/code/com/enation/javashop/android/lib/utils/BaseRecyclerViewHolder.kt
  81. 46 0
      common/src/main/code/com/enation/javashop/android/lib/utils/ChinaeseSortHelper.kt
  82. 144 0
      common/src/main/code/com/enation/javashop/android/lib/utils/ConnectionObserver.kt
  83. 66 0
      common/src/main/code/com/enation/javashop/android/lib/utils/ConnectionQualityMonitor.kt
  84. 374 0
      common/src/main/code/com/enation/javashop/android/lib/utils/Do.kt
  85. 113 0
      common/src/main/code/com/enation/javashop/android/lib/utils/EcodeHelper.kt
  86. 743 0
      common/src/main/code/com/enation/javashop/android/lib/utils/ExtendMethods.kt
  87. 314 0
      common/src/main/code/com/enation/javashop/android/lib/utils/GalleryHelper.kt
  88. 31 0
      common/src/main/code/com/enation/javashop/android/lib/utils/ImageWatchLoader.kt
  89. 45 0
      common/src/main/code/com/enation/javashop/android/lib/utils/JsonTranforHelper.kt
  90. 47 0
      common/src/main/code/com/enation/javashop/android/lib/utils/MD5Util.kt
  91. 51 0
      common/src/main/code/com/enation/javashop/android/lib/utils/NetReceiver.kt
  92. 614 0
      common/src/main/code/com/enation/javashop/android/lib/utils/NoAlphaItemAnimator.kt
  93. 39 0
      common/src/main/code/com/enation/javashop/android/lib/utils/OnClickListenerAntiViolence.kt
  94. 57 0
      common/src/main/code/com/enation/javashop/android/lib/utils/OnItemClickListenerAntiViolence.kt
  95. 338 0
      common/src/main/code/com/enation/javashop/android/lib/utils/RecycleViewScrollHelper.kt
  96. 305 0
      common/src/main/code/com/enation/javashop/android/lib/utils/ReflexHelper.kt
  97. 26 0
      common/src/main/code/com/enation/javashop/android/lib/utils/RegularHelper.kt
  98. 18 0
      common/src/main/code/com/enation/javashop/android/lib/utils/RxExtra.kt
  99. 156 0
      common/src/main/code/com/enation/javashop/android/lib/utils/SmartHideViewHelper.kt
  100. 0 0
      common/src/main/code/com/enation/javashop/android/lib/utils/TangramPlugin.kt

+ 10 - 0
.gitignore

@@ -0,0 +1,10 @@
+*.iml
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+/gradle
+.externalNativeBuild
+/.gradle

+ 1 - 0
app/.gitignore

@@ -0,0 +1 @@
+/build

+ 128 - 0
app/build.gradle

@@ -0,0 +1,128 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+//apply plugin: 'com.enation.javashop.aspectjrt'
+
+kapt {
+    arguments {
+        arg("moduleName", project.getName())
+    }
+}
+android {
+    compileSdkVersion target_sdk_version
+    buildToolsVersion build_tools_version
+    aaptOptions.cruncherEnabled = false
+    aaptOptions.useNewCruncher = false
+    defaultConfig {
+        applicationId "com.enation.app.javashop"
+        minSdkVersion min_sdk_version
+        targetSdkVersion target_sdk_version
+        versionCode app_version_code
+        versionName app_version
+        multiDexEnabled true
+        dataBinding {
+            enabled = true
+        }
+        ndk {
+            //选择要添加的对应cpu类型的.so库。
+            abiFilters 'armeabi', 'armeabi-v7a', 'armeabi-v8a' ,'x86', 'x86_64', 'mips', 'mips64'
+        }
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+        debug {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+    sourceSets {
+        main.java.srcDirs += 'src/main/code'
+    }
+    lintOptions{
+        checkReleaseBuilds false
+        abortOnError false
+    }
+    dexOptions {
+
+        javaMaxHeapSize "4g"
+
+        jumboMode=true
+
+        preDexLibraries=true
+
+        threadCount=8
+    }
+}
+
+dependencies {
+    compile fileTree(include: ['*.jar'], dir: 'libs')
+    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+    /**
+     * 单元测试
+     */
+    testCompile 'junit:junit:4.12'
+    /**
+     * Dagger编译依赖
+     */
+    kapt 'com.google.dagger:dagger-compiler:2.7'
+    /**
+     * 内存泄漏监控
+     */
+    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
+    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+    testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+    /**
+     * Kotlin依赖
+     */
+    kapt 'com.android.databinding:compiler:2.3.3'
+    /**
+     * 路由注解处理器
+     */
+    kapt "com.enation.geamtear:jrouter-compiler:$router_version"
+    /**
+     * 外部化Moudle配置
+     * moudle独立编译配置
+     */
+    if (!componentTag) {
+        compile project(':welcome') // ===> 开始模块  建议在模块内添加广告 欢迎页 等页面
+        compile project(':home')   // ===> 主页模块  里面一般是App的首页 分类楼层页面
+        compile project(':cart')   // ===> 购物车模块 主要就是购物车的逻辑的Item
+        compile project(':goods')  // ===> 商品模块   主要是商品列表 商品详细 等等页面
+        compile project(':member') // ===> 会员模块  主要是会员信息 会员修改 会员主页 等
+        compile project(':order')  // ===> 订单模块 订单列表 详细 退货等
+        compile project(':promotion') // ===> 促销模块 秒杀 团购 等
+        compile project(':shop')      // ===> 店铺模块 店铺列表 详细 等
+        compile project(':setting')   // ===> 设置模块 设置 缓存 App分享等
+        compile project(':extra')    // ===> 额外的一些页面 比如二维码扫描等一些附加功能
+    }
+    /**
+     * JavaShopAndroid 中间件依赖库
+     */
+    compile project(':middleware')
+
+    /**
+     *  constraint-layout布局依赖
+     */
+    compile 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
+
+}
+
+///**
+// * kawo组件化框架配置
+// */
+//kawo {
+//    /**
+//     * Aop注解排除Jar
+//     */
+//    aspectExcludeJarFilter 'com.enation.geamtear.pay','AlipaySdk'
+//}
+//
+

+ 592 - 0
app/proguard-rules.pro

@@ -0,0 +1,592 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/Android/MAC_SDK/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+#############################################
+#
+# 对于一些基本指令的添加
+#
+#############################################
+# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
+-optimizationpasses 5
+
+# 混合时不使用大小写混合,混合后的类名为小写
+-dontusemixedcaseclassnames
+
+# 指定不去忽略非公共库的类
+-dontskipnonpubliclibraryclasses
+
+# 这句话能够使我们的项目混淆后产生映射文件
+# 包含有类名->混淆后类名的映射关系
+-verbose
+
+# 指定不去忽略非公共库的类成员
+-dontskipnonpubliclibraryclassmembers
+
+# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
+-dontpreverify
+
+# 保留Annotation不混淆
+-keepattributes *Annotation*,InnerClasses
+
+# 避免混淆泛型
+-keepattributes Signature
+
+# 抛出异常时保留代码行号
+-keepattributes SourceFile,LineNumberTable
+
+# 指定混淆是采用的算法,后面的参数是一个过滤器
+# 这个过滤器是谷歌推荐的算法,一般不做更改
+-optimizations !code/simplification/cast,!field/*,!class/merging/*
+
+
+#############################################
+#
+# Android开发中一些需要保留的公共部分
+#
+#############################################
+
+# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆
+# 因为这些子类都有可能被外部调用
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Appliction
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class * extends android.view.View
+-keep public class com.android.vending.licensing.ILicensingService
+
+
+# 保留support下的所有类及其内部类
+-keep class android.support.** {*;}
+
+# 保留继承的
+-keep public class * extends android.support.v4.**
+-keep public class * extends android.support.v7.**
+-keep public class * extends android.support.annotation.**
+
+# 保留R下面的资源
+-keep class **.R$* {*;}
+
+# 保留本地native方法不被混淆
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+# 保留在Activity中的方法参数是view的方法,
+# 这样以来我们在layout中写的onClick就不会被影响
+-keepclassmembers class * extends android.app.Activity{
+    public void *(android.view.View);
+}
+
+# 保留枚举类不被混淆
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+# 保留我们自定义控件(继承自View)不被混淆
+-keep public class * extends android.view.View{
+    *** get*();
+    void set*(***);
+    public <init>(android.content.Context);
+    public <init>(android.content.Context, android.util.AttributeSet);
+    public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+# 保留Parcelable序列化类不被混淆
+-keep class * implements android.os.Parcelable {
+    public static final android.os.Parcelable$Creator *;
+}
+
+# 保留Serializable序列化的类不被混淆
+-keepnames class * implements java.io.Serializable
+-keepclassmembers class * implements java.io.Serializable {
+    static final long serialVersionUID;
+    private static final java.io.ObjectStreamField[] serialPersistentFields;
+    !static !transient <fields>;
+    !private <fields>;
+    !private <methods>;
+    private void writeObject(java.io.ObjectOutputStream);
+    private void readObject(java.io.ObjectInputStream);
+    java.lang.Object writeReplace();
+    java.lang.Object readResolve();
+}
+
+# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
+-keepclassmembers class * {
+    void *(**On*Event);
+    void *(**On*Listener);
+}
+
+# webView处理,项目中没有使用到webView忽略即可
+-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+    public *;
+}
+-keepclassmembers class * extends android.webkit.webViewClient {
+    public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
+    public boolean *(android.webkit.WebView, java.lang.String);
+}
+-keepclassmembers class * extends android.webkit.webViewClient {
+    public void *(android.webkit.webView, jav.lang.String);
+}
+
+# 移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用
+# 记得proguard-android.txt中一定不要加-dontoptimize才起作用
+# 另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制
+#-assumenosideeffects class android.util.Log {
+#    public static int v(...);
+#    public static int i(...);
+#    public static int w(...);
+#    public static int d(...);
+#    public static int e(...);
+#}
+
+#############################################
+#
+# 项目中特殊处理部分
+#
+#############################################
+
+#-----------处理反射类---------------
+
+
+
+#-----------处理js交互---------------
+
+
+
+#-----------处理实体类---------------
+# 在开发的时候我们可以将所有的实体类放在一个包内,这样我们写一次混淆就行了。
+-keep class com.enation.javashop.android.middleware.model.**{ *; }
+
+-keep class com.enation.app.javashop.**{ *; }
+
+-keep class com.enation.app.javashop.**{ *; }
+
+-keep class com.enation.javashop.android.component.member.adapterPostCommentGoodsAdapter
+-keep class com.enation.javashop.android.component.shop.adapter.ShopAllGoodsAdapter
+-keep class com.enation.javashop.android.component.member.adapter.CouponAdapter
+-keep class com.enation.javashop.android.component.order.adapter.OrderItemAdapter
+
+
+#-----------处理第三方依赖库---------
+
+
+
+# AndroidEventBus
+-keep class org.simple.** { *; }
+-keep interface org.simple.** { *; }
+-keepclassmembers class * {
+    @org.simple.eventbus.Subscriber <methods>;
+}
+
+
+# BRVAH
+-keep class com.chad.library.adapter.** { *; }
+-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter
+-keep public class * extends com.chad.library.adapter.base.BaseViewHolder
+-keepclassmembers public class * extends com.chad.library.adapter.base.BaseViewHolder {
+    <init>(android.view.View);
+}
+
+
+# Bugly
+-dontwarn com.tencent.bugly.**
+-keep class com.tencent.bugly.** {*;}
+
+
+# ButterKnife
+-keep public class * implements butterknife.Unbinder {
+    public <init>(**, android.view.View);
+}
+-keep class butterknife.*
+-keepclasseswithmembernames class * {
+    @butterknife.* <methods>;
+}
+-keepclasseswithmembernames class * {
+    @butterknife.* <fields>;
+}
+
+
+# Dagger2
+-dontwarn com.google.errorprone.annotations.*
+
+
+# EventBus
+-keepattributes *Annotation*
+-keepclassmembers class ** {
+    @org.greenrobot.eventbus.Subscribe <methods>;
+}
+-keep enum org.greenrobot.eventbus.ThreadMode { *; }
+
+
+# Facebook
+-keep class com.facebook.** {*;}
+-keep interface com.facebook.** {*;}
+-keep enum com.facebook.** {*;}
+
+
+# FastJson
+-dontwarn com.alibaba.fastjson.**
+-keep class com.alibaba.fastjson.** { *; }
+-keepattributes Signature
+-keepattributes *Annotation*
+
+
+# Fresco
+-keep class com.facebook.fresco.** {*;}
+-keep interface com.facebook.fresco.** {*;}
+-keep enum com.facebook.fresco.** {*;}
+
+
+# 高德相关依赖
+# 集合包:3D地图3.3.2 导航1.8.0 定位2.5.0
+-dontwarn com.amap.api.**
+-dontwarn com.autonavi.**
+-keep class com.amap.api.**{*;}
+-keep class com.autonavi.**{*;}
+# 地图服务
+-dontwarn com.amap.api.services.**
+-keep class com.map.api.services.** {*;}
+# 3D地图
+-dontwarn com.amap.api.mapcore.**
+-dontwarn com.amap.api.maps.**
+-dontwarn com.autonavi.amap.mapcore.**
+-keep class com.amap.api.mapcore.**{*;}
+-keep class com.amap.api.maps.**{*;}
+-keep class com.autonavi.amap.mapcore.**{*;}
+# 定位
+-dontwarn com.amap.api.location.**
+-dontwarn com.aps.**
+-keep class com.amap.api.location.**{*;}
+-keep class com.aps.**{*;}
+# 导航
+-dontwarn com.amap.api.navi.**
+-dontwarn com.autonavi.**
+-keep class com.amap.api.navi.** {*;}
+-keep class com.autonavi.** {*;}
+
+
+# Glide
+-keep public class * implements com.bumptech.glide.module.GlideModule
+-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
+  **[] $VALUES;
+  public *;
+}
+
+
+### greenDAO 3
+-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
+    public static java.lang.String TABLENAME;
+}
+-keep class **$Properties
+
+# If you do not use SQLCipher:
+-dontwarn org.greenrobot.greendao.database.**
+# If you do not use RxJava:
+-dontwarn rx.**
+
+
+# Gson
+-keepattributes Signature
+-keepattributes *Annotation*
+-keep class sun.misc.Unsafe { *; }
+-keep class com.google.gson.stream.** { *; }
+# 使用Gson时需要配置Gson的解析对象及变量都不混淆。不然Gson会找不到变量。
+# 将下面替换成自己的实体类
+#-keep class com.example.bean.** { *; }
+
+
+# Jackson
+-dontwarn org.codehaus.jackson.**
+-dontwarn com.fasterxml.jackson.databind.**
+-keep class org.codehaus.jackson.** { *;}
+-keep class com.fasterxml.jackson.** { *; }
+
+
+# 极光推送
+-dontoptimize
+-dontpreverify
+-dontwarn cn.jpush.**
+-keep class cn.jpush.** { *; }
+
+
+# OkHttp
+-dontwarn okio.**
+-dontwarn okhttp3.**
+-dontwarn javax.annotation.Nullable
+-dontwarn javax.annotation.ParametersAreNonnullByDefault
+
+
+# Okio
+-dontwarn com.squareup.**
+-dontwarn okio.**
+-keep public class org.codehaus.* { *; }
+-keep public class java.nio.* { *; }
+
+
+# OrmLite
+-keepattributes *DatabaseField*
+-keepattributes *DatabaseTable*
+-keepattributes *SerializedName*
+-keep class com.j256.**
+-keepclassmembers class com.j256.** { *; }
+-keep enum com.j256.**
+-keepclassmembers enum com.j256.** { *; }
+-keep interface com.j256.**
+-keepclassmembers interface com.j256.** { *; }
+
+
+# Realm
+-keep class io.realm.annotations.RealmModule
+-keep @io.realm.annotations.RealmModule class *
+-keep class io.realm.internal.Keep
+-keep @io.realm.internal.Keep class * { *; }
+-dontwarn javax.**
+-dontwarn io.realm.**
+
+
+# Retrofit
+-keep class retrofit2.** { *; }
+-dontwarn retrofit2.**
+-keepattributes Signature
+-keepattributes Exceptions
+-dontwarn okio.**
+-dontwarn javax.annotation.**
+
+
+# Retrolambda
+-dontwarn java.lang.invoke.*
+
+
+# RxJava RxAndroid
+-dontwarn sun.misc.**
+-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
+    long producerIndex;
+    long consumerIndex;
+}
+-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
+    rx.internal.util.atomic.LinkedQueueNode producerNode;
+}
+-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
+    rx.internal.util.atomic.LinkedQueueNode consumerNode;
+}
+-dontnote rx.internal.util.PlatformDependent
+
+
+
+# 微信支付
+-dontwarn com.tencent.mm.**
+-dontwarn com.tencent.wxop.stat.**
+-keep class com.tencent.mm.** {*;}
+-keep class com.tencent.wxop.stat.**{*;}
+
+
+# 信鸽
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep class com.tencent.android.tpush.**  {* ;}
+-keep class com.tencent.mid.**  {* ;}
+-keepattributes *Annotation*
+
+
+# 新浪微博
+-keep class com.sina.weibo.sdk.* { *; }
+-keep class android.support.v4.* { *; }
+-keep class com.tencent.* { *; }
+-keep class com.baidu.* { *; }
+-keep class lombok.ast.ecj.* { *; }
+-dontwarn android.support.v4.**
+-dontwarn com.tencent.**s
+-dontwarn com.baidu.**
+
+
+# XLog
+-keep class com.tencent.mars.** { *; }
+-keepclassmembers class com.tencent.mars.** { *; }
+-dontwarn com.tencent.mars.**
+
+
+# 讯飞语音
+-dontwarn com.iflytek.**
+-keep class com.iflytek.** {*;}
+
+
+# 银联
+-dontwarn com.unionpay.**
+-keep class com.unionpay.** { *; }
+
+
+# 友盟统计分析
+-keepclassmembers class * { public <init>(org.json.JSONObject); }
+-keepclassmembers enum com.umeng.analytics.** {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+
+# 友盟自动更新
+-keepclassmembers class * { public <init>(org.json.JSONObject); }
+-keep public class cn.irains.parking.cloud.pub.R$*{ public static final int *; }
+-keep public class * extends com.umeng.**
+-keep class com.umeng.** { *; }
+
+
+# 支付宝钱包
+-dontwarn com.alipay.**
+-dontwarn HttpUtils.HttpFetcher
+-dontwarn com.ta.utdid2.**
+-dontwarn com.ut.device.**
+-keep class com.alipay.android.app.IAlixPay{*;}
+-keep class com.alipay.android.app.IAlixPay$Stub{*;}
+-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
+-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
+-keep class com.alipay.sdk.app.PayTask{ public *;}
+-keep class com.alipay.sdk.app.AuthTask{ public *;}
+-keep class com.alipay.mobilesecuritysdk.*
+-keep class com.ut.*
+
+
+
+#解决使用Retrofit+rxJava联网时,在6.0系统出现java.lang.InternalError奔溃的问题:http://blog.csdn.net/mp624183768/article/details/79242147
+-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
+    long producerIndex;
+    long consumerIndex;
+}
+-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
+    rx.internal.util.atomic.LinkedQueueNode producerNode;
+}
+-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
+    rx.internal.util.atomic.LinkedQueueNode consumerNode;
+}
+
+-keep class com.tencent.mm.opensdk.** {
+*;
+}
+-keep class com.tencent.wxop.** {
+*;
+}
+-keep class com.tencent.mm.sdk.** {
+*;
+}
+-keep class com.umeng.commonsdk.** {*;}
+-keepclassmembers class * {
+   public <init> (org.json.JSONObject);
+}
+-keep public class [com.zongxueguan.naochanle_android].R$*{
+public static final int *;
+}
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+-dontshrink
+ -dontoptimize
+ -dontwarn com.google.android.maps.**
+ -dontwarn android.webkit.WebView
+ -dontwarn com.umeng.**
+ -dontwarn com.tencent.weibo.sdk.**
+ -dontwarn com.facebook.**
+ -keep public class javax.**
+ -keep public class android.webkit.**
+ -dontwarn android.support.v4.**
+ -keep enum com.facebook.**
+ -keepattributes Exceptions,InnerClasses,Signature
+ -keepattributes *Annotation*
+ -keepattributes SourceFile,LineNumberTable
+
+ -keep public interface com.facebook.**
+ -keep public interface com.tencent.**
+ -keep public interface com.umeng.socialize.**
+ -keep public interface com.umeng.socialize.sensor.**
+ -keep public interface com.umeng.scrshot.**
+
+ -keep public class com.umeng.socialize.* {*;}
+
+
+ -keep class com.facebook.**
+ -keep class com.facebook.** { *; }
+ -keep class com.umeng.scrshot.**
+ -keep public class com.tencent.** {*;}
+ -keep class com.umeng.socialize.sensor.**
+ -keep class com.umeng.socialize.handler.**
+ -keep class com.umeng.socialize.handler.*
+ -keep class com.umeng.weixin.handler.**
+ -keep class com.umeng.weixin.handler.*
+ -keep class com.umeng.qq.handler.**
+ -keep class com.umeng.qq.handler.*
+ -keep class UMMoreHandler{*;}
+ -keep class com.tencent.mm.sdk.modelmsg.WXMediaMessage {*;}
+ -keep class com.tencent.mm.sdk.modelmsg.** implements com.tencent.mm.sdk.modelmsg.WXMediaMessage$IMediaObject {*;}
+ -keep class im.yixin.sdk.api.YXMessage {*;}
+ -keep class im.yixin.sdk.api.** implements im.yixin.sdk.api.YXMessage$YXMessageData{*;}
+ -keep class com.tencent.mm.sdk.** {
+    *;
+ }
+ -keep class com.tencent.mm.opensdk.** {
+    *;
+ }
+ -keep class com.tencent.wxop.** {
+    *;
+ }
+ -keep class com.tencent.mm.sdk.** {
+    *;
+ }
+ -dontwarn twitter4j.**
+ -keep class twitter4j.** { *; }
+
+ -keep class com.tencent.** {*;}
+ -dontwarn com.tencent.**
+ -keep class com.kakao.** {*;}
+ -dontwarn com.kakao.**
+ -keep public class com.umeng.com.umeng.soexample.R$*{
+     public static final int *;
+ }
+ -keep public class com.linkedin.android.mobilesdk.R$*{
+     public static final int *;
+ }
+ -keepclassmembers enum * {
+     public static **[] values();
+     public static ** valueOf(java.lang.String);
+ }
+
+ -keep class com.tencent.open.TDialog$*
+ -keep class com.tencent.open.TDialog$* {*;}
+ -keep class com.tencent.open.PKDialog
+ -keep class com.tencent.open.PKDialog {*;}
+ -keep class com.tencent.open.PKDialog$*
+ -keep class com.tencent.open.PKDialog$* {*;}
+ -keep class com.umeng.socialize.impl.ImageImpl {*;}
+ -keep class com.sina.** {*;}
+ -dontwarn com.sina.**
+ -keep class  com.alipay.share.sdk.** {
+    *;
+ }
+
+ -keepnames class * implements android.os.Parcelable {
+     public static final ** CREATOR;
+ }
+
+ -keep class com.linkedin.** { *; }
+ -keep class com.android.dingtalk.share.ddsharemodule.** { *; }
+ -keepattributes Signature
+
+-dontwarn okio.**
+-dontwarn javax.annotation.**

BIN
app/release/app-release.apk


+ 1 - 0
app/release/output.json

@@ -0,0 +1 @@
+[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1},"path":"app-release.apk","properties":{"packageId":"com.enation.app.javashop","split":"","minSdkVersion":"17"}}]

+ 26 - 0
app/src/androidTest/java/com/enation/javashop/android/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.enation.javashop.android;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.enation.javashop.android", appContext.getPackageName());
+    }
+}

+ 146 - 0
app/src/main/AndroidManifest.xml

@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="com.enation.app.javashop">
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
+
+    <uses-permission android:name ="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/launcher"
+        android:label="@string/javashop_app_name"
+        android:supportsRtl="true"
+        tools:replace="android:label"
+        android:networkSecurityConfig="@xml/network_security_config"
+        android:name=".application.Application"
+        android:theme="@style/MyAppTheme">
+        <meta-data
+            android:name="com.enation.javashop.imagepluin.cache.MyGlideModule"
+            android:value="GlideModule" />
+        <meta-data
+            android:name="design_width_in_dp"
+            android:value="360"/>
+        <meta-data
+            android:name="design_height_in_dp"
+            android:value="640"/>
+        <meta-data
+            android:name="UMENG_APPKEY"
+            android:value="596453f8c895762c7e00028e" >
+        </meta-data>
+        <meta-data
+            android:name="UMENG_MESSAGE_SECRET"
+            android:value="53d15319bc4f06721db8dd3e4813c7df">
+        </meta-data>
+        <activity android:name="com.enation.javashop.android.component.welcome.activity.WelcomeActivity"
+            >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="com.alipay.sdk.app.H5PayActivity"
+            android:configChanges="keyboardHidden|navigation|orientation"
+            android:exported="false"/>
+        <activity
+            android:name="com.alipay.sdk.auth.AuthActivity"
+            android:configChanges="keyboardHidden|navigation|orientation"
+            android:exported="false"/>
+        <activity
+            android:name="com.alipay.sdk.app.H5AuthActivity"
+            android:configChanges="keyboardHidden|navigation|orientation"
+            android:exported="false"/>
+
+        <activity
+            android:name=".wxapi.WXEntryActivity"
+            android:exported="true"
+            android:label="@string/app_name"/>
+        <activity
+            android:name=".wxapi.WXPayEntryActivity"
+            android:configChanges="keyboardHidden|orientation|screenSize"
+            android:exported="true"
+            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
+
+        <activity
+            android:name=".WBShareActivity"
+            android:configChanges="keyboardHidden|orientation"
+            >
+            <intent-filter>
+                <action android:name="com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="com.umeng.qq.tencent.AuthActivity"
+            android:launchMode="singleTask"
+            android:noHistory="true" >
+
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="tencent1105873778" />
+            </intent-filter>
+        </activity>
+
+        <activity
+            android:name="com.umeng.qq.tencent.AssistActivity"
+            android:theme="@android:style/Theme.Translucent.NoTitleBar"
+            android:configChanges="orientation|keyboardHidden|screenSize"/>
+        <activity
+            android:name="com.umeng.socialize.editorpage.ShareActivity"
+            android:theme="@style/Theme.UMDefault"
+            android:excludeFromRecents="true"
+            />
+        <activity
+            android:name=".apshare.ShareEntryActivity"
+            android:configChanges="keyboardHidden|orientation|screenSize"
+            android:exported="true"
+            android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+
+        <activity android:name=".activity.SchemeActivity">
+
+            <!-- Schame -->
+            <intent-filter>
+                <data
+                    android:host="m.javashop.com"
+                    android:scheme="javashop"/>
+
+                <action android:name="android.intent.action.VIEW"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+            </intent-filter>
+
+            <!-- App Links -->
+            <intent-filter android:autoVerify="true">
+                <action android:name="android.intent.action.VIEW"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+
+                <data
+                    android:host="m.javashop.com"
+                    android:scheme="http"/>
+                <data
+                    android:host="m.javashop.com"
+                    android:scheme="https"/>
+            </intent-filter>
+        </activity>
+        <meta-data
+            android:name="android.max_aspect"
+            android:value="2.2" />
+    </application>
+
+</manifest>

+ 4 - 0
app/src/main/assets/config.javashop

@@ -0,0 +1,4 @@
+{
+    "TestMode" : false ,
+    "TestPath" : "/order/create"
+}

+ 7 - 0
app/src/main/code/com/enation/app/javashop/WBShareActivity.kt

@@ -0,0 +1,7 @@
+package com.enation.app.javashop
+
+import com.umeng.socialize.media.WBShareCallBackActivity
+
+
+class WBShareActivity : WBShareCallBackActivity() {
+}

+ 26 - 0
app/src/main/code/com/enation/app/javashop/activity/SchemeActivity.kt

@@ -0,0 +1,26 @@
+package com.enation.app.javashop.activity
+
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import com.enation.javashop.android.jrouter.JRouter
+import com.enation.javashop.android.jrouter.logic.datainfo.Postcard
+import com.enation.javashop.android.jrouter.logic.listener.NavListener
+import java.lang.ref.PhantomReference
+import java.lang.ref.ReferenceQueue
+
+/**
+ * Created by LDD on 2017/9/10.
+ */
+class SchemeActivity:AppCompatActivity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        val uri = intent.data
+        JRouter.prepare().create(uri).seek(this,object:NavListener(){
+            override fun onArrival(postcard: Postcard?) {
+                finish()
+            }
+        })
+    }
+
+}

+ 173 - 0
app/src/main/code/com/enation/app/javashop/application/Application.kt

@@ -0,0 +1,173 @@
+package com.enation.app.javashop.application
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+import android.graphics.Color
+import android.os.Build
+import android.provider.Settings
+import android.support.v4.app.NotificationCompat
+import android.util.Log
+import android.widget.RemoteViews
+import com.enation.app.javashop.R
+import com.enation.javashop.android.jrouter.JRouter
+import com.enation.javashop.android.lib.base.BaseApplication
+import com.enation.javashop.android.lib.utils.errorLog
+import com.enation.javashop.android.middleware.api.MemberState.Companion.manager
+import com.enation.javashop.android.middleware.config.JavaShopConfigCenter
+import com.enation.javashop.connectview.UmengConfig
+import com.enation.javashop.net.engine.config.NetEngineConfig
+import com.enation.javashop.net.engine.plugin.exception.RestfulExceptionInterceptor
+import com.enation.javashop.utils.base.config.BaseConfig
+import com.enation.javashop.utils.base.tool.CommonTool
+import com.google.gson.Gson
+import com.squareup.leakcanary.LeakCanary
+import com.umeng.commonsdk.UMConfigure
+import com.umeng.message.IUmengRegisterCallback
+import com.umeng.message.MsgConstant
+import com.umeng.message.PushAgent
+import com.umeng.message.UmengMessageHandler
+import com.umeng.message.entity.UMessage
+import io.reactivex.Observable
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.functions.Function4
+import io.reactivex.schedulers.Schedulers
+
+/**
+ * @author LDD
+ * @Date   2018/1/11 下午12:48
+ * @From   com.enation.javashop.android.application
+ * @Note   应用Application
+ */
+class Application : BaseApplication() {
+
+
+    /**
+     * @author LDD
+     * @From   Application
+     * @Date   2018/1/11 下午12:50
+     * @Note   应用启动时调用
+     */
+    override fun onCreate() {
+        super.onCreate()
+        initRouter()
+        initFrame()
+        initLeaks()
+        initPush()
+    }
+
+    /**
+     * @author  LDD
+     * @From    Application
+     * @Date   2018/1/11 下午12:50
+     * @Note   初始化路由
+     * @return rx观察者
+     */
+    private fun initRouter() {
+        JRouter.init(this)
+        JRouter.openDebug()
+        JRouter.openLog()
+        JRouter.prepare().create("/welcome/launch").seek()
+        JRouter.prepare().create("/home/launch").seek()
+        JRouter.prepare().create("/member/launch").seek()
+        JRouter.prepare().create("/cart/launch").seek()
+        JRouter.prepare().create("/setting/launch").seek()
+        JRouter.prepare().create("/goods/launch").seek()
+        JRouter.prepare().create("/shop/launch").seek()
+        JRouter.prepare().create("/order/launch").seek()
+        JRouter.prepare().create("/promotion/launch").seek()
+        JRouter.prepare().create("/extra/launch").seek()
+    }
+
+    /**
+     * @author  LDD
+     * @From    Application
+     * @Date   2018/1/11 下午12:50
+     * @Note   初始化内存检测器
+     * @return rx观察者
+     */
+    private fun initLeaks() {
+//        if (JavaShopConfigCenter.INSTANCE.APP_DEV) {
+//            LeakCanary.install(this)
+//        }
+    }
+
+    /**
+     * @author  LDD
+     * @From    Application
+     * @Date   2018/1/11 下午12:50
+     * @Note   初始化内部框架
+     * @return rx观察者
+     */
+    private fun initFrame() {
+        if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIPOP) {
+            BaseConfig.getInstance().addActivity("WelcomeActivity", "HomeActivity")
+        } else {
+            BaseConfig.getInstance().closeScrollBack()
+        }
+        NetEngineConfig.init(baseContext)
+                .openLogger()
+                .addNetInterceptor(RestfulExceptionInterceptor())
+        /**初始化友盟分享*/
+        //Config.DEBUG = true
+        UmengConfig.initWechat(JavaShopConfigCenter.INSTANCE.WECHAT_APP_ID, JavaShopConfigCenter.INSTANCE.WECHAT_SCRECT)
+        UmengConfig.initQQ(JavaShopConfigCenter.INSTANCE.QQ_Key, JavaShopConfigCenter.INSTANCE.QQ_SCRECT)
+        UmengConfig.initWeiBo(JavaShopConfigCenter.INSTANCE.WEIBO_KEY, JavaShopConfigCenter.INSTANCE.WEIBO_SCRECT, JavaShopConfigCenter.INSTANCE.WEIBO_URL)
+        UmengConfig.initAliPay(JavaShopConfigCenter.INSTANCE.ALIPAY_KEY)
+    }
+
+    private fun initPush() {
+        UMConfigure.init(this, JavaShopConfigCenter.INSTANCE.UMENG_KEY, "Umeng", UMConfigure.DEVICE_TYPE_PHONE, JavaShopConfigCenter.INSTANCE.UMENG_SCRECT)
+        /**初始化推送对象*/
+        val mPushAgent = PushAgent.getInstance(this)
+        /**开启推送*/
+        mPushAgent.onAppStart()
+        /**设置后台接受通知*/
+        mPushAgent.setNotificaitonOnForeground(true)
+        /**设置响铃*/
+        mPushAgent.notificationPlaySound = MsgConstant.NOTIFICATION_PLAY_SDK_ENABLE
+        /**设置呼吸灯闪烁*/
+        mPushAgent.notificationPlayLights = MsgConstant.NOTIFICATION_PLAY_SDK_ENABLE
+        /**设置是否显示*/
+        mPushAgent.notificationPlayVibrate = MsgConstant.NOTIFICATION_PLAY_SDK_ENABLE
+        /**设置推送信息监听器*/
+        mPushAgent.messageHandler = object : UmengMessageHandler() {
+
+            override fun getNotification(context: Context?, uMessage: UMessage?): Notification {
+                //Log.e("getNotification", Gson().toJson(uMessage))
+                val builder = Notification.Builder(context)
+                /**自定义通知样式*/
+                val myNotificationView = RemoteViews(context!!.getPackageName(), R.layout.notification_lay)
+                myNotificationView.setTextViewText(R.id.notification_time, CommonTool.DataMilltoString(System.currentTimeMillis(), "YYYY-MM-DD"))
+                myNotificationView.setTextViewText(R.id.notification_content, uMessage!!.text)
+                builder.setContent(myNotificationView)
+                        .setSmallIcon(getSmallIconId(context, uMessage))
+                        .setTicker(uMessage!!.ticker)
+                        .setAutoCancel(true)
+                return builder.notification
+                return super.getNotification(context, uMessage)
+            }
+
+            override fun dealWithNotificationMessage(p0: Context?, p1: UMessage?) {
+                super.dealWithNotificationMessage(p0, p1)
+            }
+
+
+        }
+
+        //注册推送服务,每次调用register方法都会回调该接口
+        mPushAgent.register(object : IUmengRegisterCallback {
+
+            override fun onSuccess(deviceToken: String) {
+                //注册成功会返回device token
+                errorLog("PushRegisterSuccess", "$deviceToken")
+            }
+
+            override fun onFailure(s: String, s1: String) {
+                errorLog("PushRegisterError", "$s  $s1")
+            }
+        })
+    }
+
+}

+ 8 - 0
app/src/main/code/com/enation/app/javashop/apshare/ShareEntryActivity.kt

@@ -0,0 +1,8 @@
+package com.enation.app.javashop.apshare
+
+import com.umeng.socialize.media.ShareCallbackActivity
+
+/**
+ * 支付宝分享回调
+ */
+class ShareEntryActivity : ShareCallbackActivity()

+ 9 - 0
app/src/main/code/com/enation/app/javashop/wxapi/WXEntryActivity.kt

@@ -0,0 +1,9 @@
+package com.enation.app.javashop.wxapi
+
+import com.umeng.weixin.callback.WXCallbackActivity
+
+/**
+ * Created by LDD on 2018/10/23.
+ */
+class WXEntryActivity : WXCallbackActivity() {
+}

+ 59 - 0
app/src/main/code/com/enation/app/javashop/wxapi/WXPayEntryActivity.kt

@@ -0,0 +1,59 @@
+package com.enation.app.javashop.wxapi
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import com.enation.javashop.android.lib.utils.getEventCenter
+import com.enation.javashop.android.middleware.config.JavaShopConfigCenter
+import com.enation.javashop.android.middleware.event.PayEvent
+import com.enation.javashop.android.middleware.event.PayState
+import com.tencent.mm.sdk.modelbase.BaseReq
+import com.tencent.mm.sdk.modelbase.BaseResp
+import com.tencent.mm.sdk.openapi.IWXAPI
+import com.tencent.mm.sdk.openapi.IWXAPIEventHandler
+import com.tencent.mm.sdk.openapi.WXAPIFactory
+
+/**
+ * Created by LDD on 2018/10/23.
+ */
+class WXPayEntryActivity :Activity() , IWXAPIEventHandler {
+
+    private val TAG = "WXPayEntryActivity"
+    private val api by lazy { WXAPIFactory.createWXAPI(this, JavaShopConfigCenter.INSTANCE.WECHAT_APP_ID); }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        this.api.handleIntent(intent, this)
+    }
+
+    override fun onNewIntent(intent: Intent?) {
+        super.onNewIntent(intent)
+        this.api.handleIntent(intent, this)
+    }
+
+    override fun onResp(paramBaseResp: BaseResp) {
+        Log.d("WXPayEntryActivity", "onPayFinish, errCode = " + paramBaseResp.errCode)
+        if (paramBaseResp.type == 5){
+            when (paramBaseResp.errCode) {
+                -1 -> {
+                    getEventCenter().post(PayEvent(PayState.FAILD))
+                    return
+                }
+                0 -> {
+                    getEventCenter().post(PayEvent(PayState.SUCCESS))
+                    return
+                }
+                else -> {
+                    getEventCenter().post(PayEvent(PayState.FAILD))
+                    return
+                }
+            }
+        }
+        getEventCenter().post(PayEvent(PayState.CANCLE))
+    }
+
+    override fun onReq(p0: BaseReq?) {
+
+    }
+}

+ 63 - 0
app/src/main/res/layout/notification_lay.xml

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:background="#88000000"
+              android:orientation="horizontal"
+              android:paddingLeft="15dp"
+              android:paddingRight="15dp"
+              android:layout_width="match_parent"
+              android:layout_height="64dp">
+    <ImageView
+        android:layout_width="64dp"
+        android:src="@mipmap/launcher"
+        android:padding="5dp"
+        android:layout_gravity="center_vertical"
+        android:layout_height="64dp"/>
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_weight="1.5"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <TextView
+                android:id="@+id/notification_title"
+                android:text="JavaShop"
+                android:textColor="#fff"
+                android:gravity="bottom"
+                android:textSize="15dp"
+                android:maxLines="1"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"/>
+            <TextView
+                android:id="@+id/notification_time"
+                android:layout_marginLeft="10dp"
+                android:textSize="12dp"
+                android:text="16-10-07"
+                android:maxLines="1"
+                android:textColor="#99ffffff"
+                android:gravity="bottom"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"/>
+        </LinearLayout>
+        <LinearLayout
+            android:layout_marginBottom="5dp"
+            android:layout_weight="1"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <TextView
+                android:id="@+id/notification_content"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:textSize="12dp"
+                android:textColor="#99ffffff"
+                android:gravity="top"
+                android:maxLines="2"
+                android:ellipsize="end"
+                android:layout_marginBottom="5dp"
+                android:text="asdasdadasddasdasdasdasasaasdasdsadasdasdasdasdasdadasasddasdasasdasdadadada"
+                />
+        </LinearLayout>
+    </LinearLayout>
+</LinearLayout>

+ 17 - 0
app/src/test/java/com/enation/javashop/android/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.enation.javashop.android;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() throws Exception {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 115 - 0
build.gradle

@@ -0,0 +1,115 @@
+
+buildscript {
+    /**
+     * Kotlin统一版本
+     */
+    ext.kotlin_version = '1.2.40'
+
+    /**
+     * Aop编制版本
+     */
+    ext.aspectj_version = '1.8.9'
+
+    /**
+     * 是否开启单独Module编译
+     */
+    ext.componentTag = false
+
+    /**
+     * 路由注解处理器版本
+     */
+    ext.router_version = '1.0.2'
+
+    /**
+     * kawo组件化框架版本
+     */
+    ext.kawo_version = '1.0.9'
+
+    /**
+     * SDK最小支持版本
+     */
+    ext.min_sdk_version = 17
+
+    /**
+     * SDK目标支持版本
+     */
+    ext.target_sdk_version = 28
+
+    /**
+     * SDK编译版本
+     */
+    ext.build_tools_version = "26.0.2"
+
+    /**
+     * 支持库版本
+     */
+    ext.support_library_version = "26.0.1"
+
+    /**
+     * APP版本码
+     */
+    ext.app_version_code = 1
+
+    /**
+     * APP版本号
+     */
+    ext.app_version = "1.0"
+
+
+    /**
+     * 项目依赖库
+     */
+    dependencies {
+        repositories {
+            /**
+             * 依赖仓储
+             */
+            jcenter()
+            mavenCentral()
+            google()
+        }
+        /**
+         * Gradle插件
+         */
+        classpath 'com.android.tools.build:gradle:3.0.1'
+
+        /**
+         * Kawo组件化插件
+         */
+        classpath "com.enation.geamtear.gradle:kawo:$kawo_version"
+
+        /**
+         * KotlinGradle插件
+         */
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+
+        /**
+         * Kotlin辅助工具
+         */
+        classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
+
+        /**
+         * Aop埋点相关
+         */
+        classpath "org.aspectj:aspectjtools:$aspectj_version"
+    }
+}
+/**
+ * 统一依赖仓储
+ */
+allprojects {
+    repositories {
+        google()
+        jcenter()
+        mavenCentral()
+        maven{ url 'https://dl.bintray.com/geamtear/maven' }
+        maven{ url "https://jitpack.io" }
+    }
+}
+
+/**
+ *  清除Build配置时 删除根目录Build文件夹
+ */
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}

+ 1 - 0
cart/.gitignore

@@ -0,0 +1 @@
+/build

+ 124 - 0
cart/build.gradle

@@ -0,0 +1,124 @@
+
+if (componentTag){
+    apply plugin: 'com.android.application'
+    apply plugin: 'com.enation.javashop.aspectjrt'
+}else{
+    apply plugin: 'com.android.library'
+}
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+
+kapt {
+    arguments {
+        arg("moduleName", project.getName())
+    }
+}
+
+android {
+    compileSdkVersion target_sdk_version
+    buildToolsVersion build_tools_version
+
+    defaultConfig {
+        if (componentTag){
+            applicationId "com.enation.javashop.android.component.cart"
+            multiDexEnabled true
+        }
+        minSdkVersion min_sdk_version
+        targetSdkVersion target_sdk_version
+        versionCode app_version_code
+        versionName app_version
+        dataBinding {
+            enabled = true
+        }
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+    }
+    lintOptions {
+        abortOnError false
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+    sourceSets {
+        main.java.srcDirs += 'src/main/code'
+        if(componentTag){
+            main.manifest.srcFile 'src/main/ApkBuildDir/AndroidManifest.xml'
+        }else{
+            main.manifest.srcFile 'src/main/AndroidManifest.xml'
+            main.java {
+                exclude 'apkbuild/**'
+            }
+        }
+    }
+}
+
+dependencies {
+    compile fileTree(include: ['*.jar'], dir: 'libs')
+    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+    /**
+     * 单元测试
+     */
+    testCompile 'junit:junit:4.12'
+
+    /**
+     *  Android基础依赖库
+     */
+    compile "com.android.support:design:$support_library_version"
+    compile "com.android.support:support-v4:$support_library_version"
+    compile "com.android.support:cardview-v7:$support_library_version"
+
+    /**
+     * 公共库依赖
+     */
+    compile project(':middleware')
+
+    /**
+     * 内存泄漏监控
+     */
+    if(componentTag){
+        debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
+        releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+        testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+    }
+
+    /**
+     * Dagger编译依赖
+     */
+    kapt 'com.google.dagger:dagger-compiler:2.7'
+
+    /**
+     * Kotlin依赖
+     */
+    kapt 'com.android.databinding:compiler:2.3.3'
+
+    /**
+     * 路由注解处理器
+     */
+    kapt "com.enation.geamtear:jrouter-compiler:$router_version"
+
+    /**
+     *  constraint-layout布局依赖
+     */
+    compile 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
+
+}
+
+/**
+ * kawo组件化框架配置
+ */
+if(componentTag){
+    kawo {
+        /**
+         * Aop注解排除Jar
+         */
+        aspectExcludeJarFilter 'com.enation.geamtear.pay','AlipaySdk'
+    }
+}
+

+ 21 - 0
cart/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
cart/src/androidTest/java/com/enation/javashop/android/component/cart/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.enation.javashop.android.component.cart;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.enation.javashop.android.component.cart.test", appContext.getPackageName());
+    }
+}

+ 13 - 0
cart/src/main/AndroidManifest.xml

@@ -0,0 +1,13 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.enation.javashop.android.component.cart">
+    <application android:allowBackup="true"
+                 android:label="@string/app_name"
+                 android:supportsRtl="true"
+        >
+        <activity android:name=".activity.CartActivity"
+            />
+    </application>
+</manifest>
+
+
+

+ 15 - 0
cart/src/main/ApkBuildDir/AndroidManifest.xml

@@ -0,0 +1,15 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.enation.javashop.android.welcome">
+    <uses-permission android:name="android.permission.INTERNET"/>
+
+    <application
+        android:allowBackup="true"
+        android:label="@string/app_name"
+        android:theme="@style/Theme.AppCompat.Light.NoActionBar"
+        android:name="apkbuild.CartApplication"
+        android:supportsRtl="true">
+    </application>
+</manifest>
+
+    <!--单独Module调试 需要往Application作用域下加入皮肤-->
+    <!--android:theme="@style/Theme.AppCompat.Light.NoActionBar"-->

+ 81 - 0
cart/src/main/code/apkbuild/CartApplication.kt

@@ -0,0 +1,81 @@
+//package apkbuild
+//
+//import com.enation.javashop.android.jrouter.JRouter
+//import com.enation.javashop.android.lib.base.BaseApplication
+//import com.enation.javashop.net.engine.config.NetEngineConfig
+//import com.enation.javashop.net.engine.plugin.exception.RestfulExceptionInterceptor
+//import com.enation.javashop.utils.base.config.BaseConfig
+//import com.squareup.leakcanary.LeakCanary
+//import io.reactivex.Observable
+//import io.reactivex.android.schedulers.AndroidSchedulers
+//import io.reactivex.schedulers.Schedulers
+//import io.reactivex.functions.Function3
+//
+///**
+// * 单Moudle编译 Application
+// */
+//class CartApplication:BaseApplication() {
+//    /**
+//     * @author LDD
+//     * @From   Application
+//     * @Date   2018/1/11 下午12:50
+//     * @Note   应用启动时调用
+//     */
+//    override fun onCreate() {
+//        super.onCreate()
+//        Observable.zip(initRouter().subscribeOn(Schedulers.newThread()),
+//                initLeaks().subscribeOn(Schedulers.newThread()),
+//                initFrame().subscribeOn(Schedulers.newThread()),
+//                Function3<String,String,String,String> { _ , _ , _ -> return@Function3 "" }).
+//                observeOn(AndroidSchedulers.mainThread()).subscribe({})
+//    }
+//
+//    /**
+//     * @author  LDD
+//     * @From    Application
+//     * @Date   2018/1/11 下午12:50
+//     * @Note   初始化路由
+//     * @return rx观察者
+//     */
+//    private fun initRouter(): Observable<String> {
+//        return Observable.create {
+//            JRouter.init(this)
+//            JRouter.openDebug()
+//            JRouter.openLog()
+//            JRouter.prepare().create("/welcome/launch").seek()
+//        }
+//    }
+//
+//    /**
+//     * @author  LDD
+//     * @From    Application
+//     * @Date   2018/1/11 下午12:50
+//     * @Note   初始化内存检测器
+//     * @return rx观察者
+//     */
+//    private fun initLeaks(): Observable<String> {
+//        return Observable.create {
+//            LeakCanary.install(this)
+//        }
+//    }
+//
+//    /**
+//     * @author  LDD
+//     * @From    Application
+//     * @Date   2018/1/11 下午12:50
+//     * @Note   初始化内部框架
+//     * @return rx观察者
+//     */
+//    private fun initFrame(): Observable<String> {
+//        return Observable.create {
+//            if (android.os.Build.VERSION.SDK_INT> android.os.Build.VERSION_CODES.LOLLIPOP){
+//                BaseConfig.getInstance().addActivity("HomeActivity")
+//            }else{
+//                BaseConfig.getInstance().closeScrollBack()
+//            }
+//            NetEngineConfig.init(baseContext)
+//                    .openLogger()
+//                    .addNetInterceptor(RestfulExceptionInterceptor())
+//        }
+//    }
+//}

+ 31 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/activity/CartActivity.kt

@@ -0,0 +1,31 @@
+package com.enation.javashop.android.component.cart.activity
+
+import android.graphics.Color
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import com.enation.javashop.android.component.cart.R
+import com.enation.javashop.android.component.cart.fragment.CartFragment
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.android.lib.utils.AppTool
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+
+/**
+ * @author LDD
+ * @Date   2018/2/24 下午4:29
+ * @From   com.enation.javashop.android.component.cart.activity
+ * @Note   cartFragment的Activity载体
+ */
+@Router(path = "/cart/main")
+class CartActivity : BaseToolActivity() {
+
+    private lateinit var fragment:CartFragment
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        AppTool.SystemUI.ImmersiveWithBottomBarColor(this, Color.BLACK)
+        setContentView(R.layout.cart_act_lay)
+        fragment = CartFragment()
+        supportFragmentManager?.beginTransaction()?.add(R.id.fragment,fragment)?.addToBackStack(null)?.commit()
+    }
+
+}

+ 199 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/adapter/CartGoodsItemAdapter.kt

@@ -0,0 +1,199 @@
+package com.enation.javashop.android.component.cart.adapter
+
+import android.databinding.DataBindingUtil
+import android.graphics.Color
+import android.graphics.Outline
+import android.util.TypedValue
+import android.view.*
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.enation.javashop.android.component.cart.R
+import com.enation.javashop.android.component.cart.databinding.CartGoodsItemBinding
+import com.enation.javashop.android.component.cart.util.BaseCartItemAdapter
+import com.enation.javashop.android.component.cart.util.CartActionAgreement
+import com.enation.javashop.android.lib.utils.*
+import com.enation.javashop.android.middleware.model.CartGoodsItemViewModel
+
+import com.enation.javashop.android.middleware.model.SingglePromotionViewModel
+import com.enation.javashop.utils.base.tool.CommonTool
+import com.enation.javashop.utils.base.tool.ScreenTool
+
+/**
+ * @author LDD
+ * @Date   2018/2/6 下午4:33
+ * @From   com.enation.javashop.android.component.cart.adapter
+ * @Note   购物车商品Item适配器
+ */
+class CartGoodsItemAdapter(agreement: CartActionAgreement, private val datas: List<CartGoodsItemViewModel>) : BaseCartItemAdapter<BaseRecyclerViewHolder<CartGoodsItemBinding>, CartGoodsItemViewModel>(agreement) {
+
+    /**
+     * @author LDD
+     * @From   CartGoodsItemAdapter
+     * @Date   2018/2/9 下午2:42
+     * @Note   数据提供者
+     * @return 数据
+     */
+    override fun dataProvider(): Any {
+        return datas
+    }
+
+    /**
+     * @author LDD
+     * @From   CartGoodsItemAdapter
+     * @Date   2018/2/9 下午2:42
+     * @Note   响应事件过滤
+     * @param  position item坐标
+     * @return 是否过滤
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    override fun getItemViewType(position: Int): Int {
+        return 1
+    }
+
+    /**
+     * @author LDD
+     * @From   CartGoodsItemAdapter
+     * @Date   2018/2/9 下午2:43
+     * @Note   创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<CartGoodsItemBinding> {
+        return BaseRecyclerViewHolder(DataBindingUtil.inflate(LayoutInflater.from(parent?.context), R.layout.cart_goods_item, parent, false))
+    }
+
+    /**
+     * @author LDD
+     * @From   CartGoodsItemAdapter
+     * @Date   2018/2/9 下午2:43
+     * @Note   item总数
+     * @return 数量总数
+     */
+    override fun getItemCount(): Int {
+        return datas.size
+    }
+
+    /**
+     * @author LDD
+     * @From   CartGoodsItemAdapter
+     * @Date   2018/2/9 下午2:44
+     * @Note   ViewHelper提供者
+     * @return ViewHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0, datas.size)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartGoodsItemAdapter
+     * @Date   2018/2/9 下午2:45
+     * @Note   绑定ViewHolder
+     * @param  holder ViewHolder
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<CartGoodsItemBinding>?, position: Int) {
+        holder?.bind { binding ->
+            binding.cartGoodsItemErrorEdit.setOnClickListener {
+                CommonTool.createVerifyDialog(datas[position].errorMessage,"我已知晓","移除商品",binding.root.context,object : CommonTool.DialogInterface{
+                    override fun yes() {
+                        actionProvider().deleteGoods(datas[position].skuId)
+                    }
+
+                    override fun no() {
+
+                    }
+                }).show()
+            }
+            binding.promotionTagParent.removeAllViews()
+            binding.goodsItemData = datas[position]
+            binding.cartGoodsPriceTv.text = String.format("¥%.2f", datas[position].price)
+            binding.cartGoodsItemSingglePromotionLay.visibility = (datas[position].promotionList == null || datas[position].promotionList!!.count() == 0).judge(View.GONE, View.VISIBLE)
+            goodsEdit(binding.cartGoodsAddBtn, position, getItem(position).skuId, getItem(position).currentNum.toInt() + 1, null)
+            goodsEdit(binding.cartGoodsReduceBtn, position, getItem(position).skuId, getItem(position).currentNum.toInt() - 1, null)
+            goodsEdit(binding.cartGoodsItemCheck, position, getItem(position).skuId, null, !getItem(position).isCheck)
+            goodsMoreAction(binding.cartGoodsItemContent, position, getItem(position).skuId, getItem(position).goodsId)
+            toGoods(binding.cartGoodsItemContent, getItem(position).goodsId)
+            selectSingglePromotion(binding.cartGoodsItemSingglePromotionEdit, datas[position].skuId, datas[position].shopId, getItem(position).promotionList
+                    ?: emptyList())
+            datas[position].promotionList?.forEach {
+                when (it.type) {
+                    "MINUS" -> {
+                        buildItem(binding.promotionTagParent, "立减")
+                    }
+                    "GROUPBUY" -> {
+                        buildItem(binding.promotionTagParent, "团购")
+                    }
+                    "EXCHANGE" -> {
+                        buildItem(binding.promotionTagParent, "积分商城")
+                    }
+                    "HALF_PRICE" -> {
+                        buildItem(binding.promotionTagParent, "第二件半价")
+                    }
+                    "SECKILL" -> {
+                        buildItem(binding.promotionTagParent, "秒杀")
+                    }
+                }
+            }
+        }
+    }
+
+    private val goodsEdit = { view: View, position: Int, productId: Int, num: Int?, check: Boolean? ->
+        view.setOnClickListener {
+            actionProvider().goodsEdit(productId, num, check)
+        }
+    }
+
+    /**
+     * @Name  goodsMoreAction
+     * @Type  Block
+     * @Note  商品更多操作
+     */
+    private val goodsMoreAction = { view: View, position: Int, productId: Int, goodsId: Int ->
+        view.setOnLongClickListener {
+            actionProvider().showGoodsMoreMask(productId, goodsId)
+            return@setOnLongClickListener true
+        }
+    }
+
+    /**
+     * @Name  toGoods
+     * @Type  Block
+     * @Note  去商品页面
+     */
+    private val toGoods = { view: View, goodsId: Int ->
+        view.setOnClickListener {
+            actionProvider().toGoods(goodsId)
+        }
+    }
+
+    /**
+     * @Name  selectSingglePromotion
+     * @Type  Block
+     * @Note  选择单品促销
+     */
+    private val selectSingglePromotion = { view: View, skuId: Int, sellerId: Int, singglePromotionList: List<SingglePromotionViewModel> ->
+        view.setOnClickListener {
+            actionProvider().selectSingglePromotion(sellerId, skuId, singglePromotionList)
+        }
+    }
+
+    private fun buildItem(parentView: ViewGroup, single: String) {
+        var tv = TextView(parentView.context)
+        tv.gravity = Gravity.CENTER
+        tv.setPadding(5.dpToPx(), 0, 5.dpToPx(), 0)
+        tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, ScreenTool.getScreenWidth(parentView.context) / 40)
+        tv.setBackgroundResource(R.drawable.javashop_red_radis_bg)
+        tv.setTextColor(Color.WHITE)
+        tv.text = single
+        parentView.addView(tv)
+        tv.reLayout<LinearLayout.LayoutParams> {
+            it.setMargins(0, 2.dpToPx(), 5.dpToPx(), 2.dpToPx())
+            it.width = LinearLayout.LayoutParams.WRAP_CONTENT
+            it.height = LinearLayout.LayoutParams.MATCH_PARENT
+        }
+
+    }
+}

+ 93 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/adapter/CartPromotionItemAdapter.kt

@@ -0,0 +1,93 @@
+package com.enation.javashop.android.component.cart.adapter
+
+import android.databinding.DataBindingUtil
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.enation.javashop.android.component.cart.R
+import com.enation.javashop.android.component.cart.databinding.CartPromotionItemBinding
+import com.enation.javashop.android.component.cart.util.BaseCartItemAdapter
+import com.enation.javashop.android.component.cart.util.CartActionAgreement
+import com.enation.javashop.android.middleware.model.CartPromotionItemViewModel
+import com.enation.javashop.android.lib.utils.BaseRecyclerViewHolder
+
+/**
+ * @author LDD
+ * @Date   2018/2/24 下午4:20
+ * @From   com.enation.javashop.android.component.cart.adapter
+ * @Note   购物车促销Item适配器
+ */
+class CartPromotionItemAdapter(agreement :CartActionAgreement,private val promotionItemViewModel: String) : BaseCartItemAdapter<BaseRecyclerViewHolder<CartPromotionItemBinding>, CartPromotionItemViewModel>(agreement) {
+
+    /**
+     * @author LDD
+     * @From   CartPromotionItemAdapter
+     * @Date   2018/2/24 下午4:20
+     * @Note   数据提供者
+     * @return 数据
+     */
+    override fun dataProvider(): Any {
+        return promotionItemViewModel
+    }
+
+    override fun getItemViewType(position: Int): Int {
+        return 2
+    }
+
+    /**
+     * @author LDD
+     * @From   CartPromotionItemAdapter
+     * @Date   2018/2/24 下午4:21
+     * @Note   点击时Item的过滤
+     * @param  position item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * @author LDD
+     * @From   CartPromotionItemAdapter
+     * @Date   2018/2/24 下午4:21
+     * @Note   创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<CartPromotionItemBinding> {
+        return BaseRecyclerViewHolder(DataBindingUtil.inflate(LayoutInflater.from(parent?.context), R.layout.cart_promotion_item,parent,false))
+    }
+
+    /**
+     * @author LDD
+     * @From   CartPromotionItemAdapter
+     * @Date   2018/2/24 下午4:22
+     * @Note   获取Item大小
+     */
+    override fun getItemCount(): Int {
+        return 1
+    }
+
+    /**
+     * @author LDD
+     * @From   CartPromotionItemAdapter
+     * @Date   2018/2/24 下午4:22
+     * @Note   创布局辅助器
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0,1)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartPromotionItemAdapter
+     * @Date   2018/2/24 下午4:23
+     * @Note   绑定ViewHolder
+     * @param  ...
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<CartPromotionItemBinding>?, position: Int) {
+        holder?.bind {
+            binding ->
+            binding.promotionItemData = promotionItemViewModel
+        }
+    }
+}

+ 129 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/adapter/CartShopItemAdapter.kt

@@ -0,0 +1,129 @@
+package com.enation.javashop.android.component.cart.adapter
+
+import android.databinding.DataBindingUtil
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.CheckBox
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.enation.javashop.android.component.cart.R
+import com.enation.javashop.android.component.cart.databinding.CartShopItemBinding
+import com.enation.javashop.android.component.cart.util.BaseCartItemAdapter
+import com.enation.javashop.android.component.cart.util.CartActionAgreement
+import com.enation.javashop.android.middleware.model.CartShopItemViewModel
+import com.enation.javashop.android.lib.utils.BaseRecyclerViewHolder
+
+/**
+ * @author LDD
+ * @Date   2018/2/24 下午4:26
+ * @From   com.enation.javashop.android.component.cart.adapter
+ * @Note   购物车店铺Item适配器
+ */
+class CartShopItemAdapter(agreement: CartActionAgreement,private val shopItemViewModel: CartShopItemViewModel) : BaseCartItemAdapter<BaseRecyclerViewHolder<CartShopItemBinding>, CartShopItemViewModel>(agreement) {
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:26
+     * @Note   数据提供者
+     * @return 数据
+     */
+    override fun dataProvider(): Any {
+        return shopItemViewModel
+    }
+
+    override fun getItemViewType(position: Int): Int {
+        return 3
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:27
+     * @Note   item点击过滤
+     * @param  position item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:27
+     * @Note   常见viewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<CartShopItemBinding> {
+        return BaseRecyclerViewHolder(DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.cart_shop_item,parent,false))
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:27
+     * @Note   获取数据源大小
+     */
+    override fun getItemCount(): Int {
+        return 1
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:27
+     * @Note   创建布局辅助器
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0,1)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:28
+     * @Note   绑定操作
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<CartShopItemBinding>, position: Int) {
+        holder.bind {
+            binding ->
+            binding.shopItemData = shopItemViewModel
+            shopCheck(binding.cartShopItemCheck , shopItemViewModel.shopId , !shopItemViewModel.isCheck)
+            toShop(binding.root,shopItemViewModel.shopId)
+            showShopBonus(binding.cartShopItemRightTv,shopItemViewModel.shopId)
+        }
+    }
+
+    /**
+     * @Name  shopCheck
+     * @Type  Block
+     * @Note  店铺选中
+     */
+    private val shopCheck = { view : CheckBox, shopId :Int, checked :Boolean ->
+        view.setOnClickListener({
+            actionProvider().shopCheck(shopId,checked)
+        })
+    }
+
+    /**
+     * @Name  toShop
+     * @Type  Block
+     * @Note  去店铺
+     */
+    private val toShop = {view :View ,shopId :Int ->
+        view.setOnClickListener {
+            actionProvider().toShop(shopId)
+        }
+    }
+
+    /**
+     * @Name  showShopBonus
+     * @Type  Block
+     * @Note  显示店铺可领取的优惠券
+     */
+    private val showShopBonus = { view : View , shopId : Int ->
+        view.setOnClickListener {
+            actionProvider().showShopBonus(shopId)
+        }
+    }
+}

+ 100 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/adapter/CartSinglePromotionItemAdapter.kt

@@ -0,0 +1,100 @@
+package com.enation.javashop.android.component.cart.adapter
+
+import android.databinding.DataBindingUtil
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.CheckBox
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.enation.javashop.android.component.cart.R
+import com.enation.javashop.android.component.cart.databinding.CartShopItemBinding
+import com.enation.javashop.android.component.cart.databinding.CartSinglePromotionLayBinding
+import com.enation.javashop.android.component.cart.util.BaseCartItemAdapter
+import com.enation.javashop.android.component.cart.util.CartActionAgreement
+import com.enation.javashop.android.lib.adapter.BaseDelegateAdapter
+import com.enation.javashop.android.middleware.model.CartShopItemViewModel
+import com.enation.javashop.android.lib.utils.BaseRecyclerViewHolder
+import com.enation.javashop.android.middleware.model.SingglePromotionViewModel
+import com.enation.javashop.utils.base.tool.ScreenTool
+
+/**
+ * @author LDD
+ * @Date   2018/2/24 下午4:26
+ * @From   com.enation.javashop.android.component.cart.adapter
+ * @Note   购物车店铺Item适配器
+ */
+class CartSinglePromotionItemAdapter(val data :List<SingglePromotionViewModel>) : BaseDelegateAdapter<BaseRecyclerViewHolder<CartSinglePromotionLayBinding>, SingglePromotionViewModel>() {
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:26
+     * @Note   数据提供者
+     * @return 数据
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+
+    override fun getItemViewType(position: Int): Int {
+        return 10
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:27
+     * @Note   item点击过滤
+     * @param  position item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:27
+     * @Note   常见viewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<CartSinglePromotionLayBinding> {
+        return BaseRecyclerViewHolder(DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.cart_single_promotion_lay,parent,false))
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:27
+     * @Note   获取数据源大小
+     */
+    override fun getItemCount(): Int {
+        return data.count()
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:27
+     * @Note   创建布局辅助器
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0,data.count())
+    }
+
+    /**
+     * @author LDD
+     * @From   CartShopItemAdapter
+     * @Date   2018/2/24 下午4:28
+     * @Note   绑定操作
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<CartSinglePromotionLayBinding>, position: Int) {
+        holder.bind {
+            binding ->
+            var item = getItem(position)
+            binding.tag.text = if (item.promotionId == 0){"其他操作"}else{"促销"}
+            binding.content.text = item.title
+        }
+    }
+}

+ 16 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/di/CartComponent.kt

@@ -0,0 +1,16 @@
+package com.enation.javashop.android.component.cart.di
+
+import com.enation.javashop.android.component.cart.fragment.CartFragment
+import com.enation.javashop.android.middleware.di.ApplicationComponent
+import dagger.Component
+
+/**
+ * @author LDD
+ * @Date   2018/1/30 下午2:35
+ * @From   com.enation.javashop.android.component.cart.di
+ * @Note   Cart模块依赖注入
+ */
+@Component(dependencies = arrayOf(ApplicationComponent::class))
+interface CartComponent {
+    fun inject(fragment : CartFragment)
+}

+ 424 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/fragment/CartFragment.kt

@@ -0,0 +1,424 @@
+package com.enation.javashop.android.component.cart.fragment
+
+import android.graphics.Color
+import android.os.Handler
+import android.support.v7.widget.RecyclerView
+import android.view.View
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.enation.javashop.android.component.cart.R
+import com.enation.javashop.android.component.cart.activity.CartActivity
+import com.enation.javashop.android.component.cart.adapter.CartGoodsItemAdapter
+import com.enation.javashop.android.component.cart.adapter.CartPromotionItemAdapter
+import com.enation.javashop.android.component.cart.adapter.CartShopItemAdapter
+import com.enation.javashop.android.component.cart.adapter.CartSinglePromotionItemAdapter
+import com.enation.javashop.android.component.cart.databinding.CartFragLayBinding
+import com.enation.javashop.android.component.cart.launch.CartLaunch
+import com.enation.javashop.android.component.cart.util.CartActionAgreement
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.android.lib.adapter.BaseDelegateAdapter
+import com.enation.javashop.android.lib.adapter.TextViewDelegateAdapter
+import com.enation.javashop.android.lib.adapter.VlayoutHolderAdapter
+import com.enation.javashop.android.lib.base.BaseFragment
+import com.enation.javashop.android.lib.utils.*
+import com.enation.javashop.android.lib.widget.PopCommonView
+import com.enation.javashop.android.middleware.api.MemberState
+import com.enation.javashop.android.middleware.event.CartDataChange
+import com.enation.javashop.android.middleware.event.LoginEvent
+import com.enation.javashop.android.middleware.event.LogoutEvent
+import com.enation.javashop.android.middleware.logic.contract.cart.CartFragmentContract
+import com.enation.javashop.android.middleware.logic.presenter.cart.CartFragmentPresenter
+import com.enation.javashop.android.middleware.model.*
+import com.enation.javashop.net.engine.model.NetState
+import com.enation.javashop.utils.base.tool.CommonTool
+import com.enation.javashop.utils.base.tool.ScreenTool
+import com.scwang.smartrefresh.layout.header.ClassicsHeader
+import kotlinx.android.synthetic.main.cart_frag_lay.*
+import java.util.*
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.component.cart.fragment
+ * @Date   2018/2/24 下午4:31
+ * @Note   购物车Fragment
+ */
+@Router(path = "/cart/fragment")
+class CartFragment :BaseFragment<CartFragmentPresenter,CartFragLayBinding>(),CartFragmentContract.View ,CartActionAgreement {
+
+    private var hasSelectGoods = false
+
+    /**
+     * @Name  adapterList
+     * @Type  ArrayList<DelegateAdapter.Adapter<*>>
+     * @Note  适配器列表
+     */
+    private var adapterList = ArrayList<DelegateAdapter.Adapter<*>>()
+
+    /**
+     * @Name  virtualLayoutManager
+     * @Type  VirtualLayoutManager
+     * @Note  七巧板LayoutManager
+     */
+    private lateinit var virtualLayoutManager : VirtualLayoutManager
+
+    /**
+     * @Name  delegateAdapter
+     * @Type  DelegateAdapter
+     * @Note  七巧板适配器
+     */
+    private lateinit var delegateAdapter : DelegateAdapter
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:35
+     * @Note   获取LayoutId
+     */
+    override fun getLayId(): Int {
+        return R.layout.cart_frag_lay
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:35
+     * @Note   依赖注入
+     */
+    override fun bindDagger() {
+        CartLaunch.component.inject(this)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:35
+     * @Note   初始化
+     */
+    override fun init() {
+        virtualLayoutManager =  VirtualLayoutManager(this.activity)
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+        mViewDataBinding.cartFragRcList.layoutManager = virtualLayoutManager
+        mViewDataBinding.cartFragRcList.adapter = delegateAdapter
+        mViewDataBinding.cartFragRcList.setBackgroundColor(Color.WHITE)
+        presenter.loadCartData()
+        mViewDataBinding.cartFragHeader.setLineBgColor(Color.TRANSPARENT)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:35
+     * @Note   绑定事件及数据
+     */
+    override fun bindEvent() {
+        if (getActivity() is CartActivity){
+            cart_frag_header.setLeftImage(R.drawable.javashop_back_black).setLeftClickListener {
+                getActivity().to<CartActivity>().pop()
+            }
+        }
+        cart_frag_create_order_tv.setOnClickListener {
+            if (!MemberState.manager.getLoginState()){
+                showMessage("未登录")
+                return@setOnClickListener
+            }
+            if (!hasSelectGoods){
+                showMessage("请选择结算商品")
+                return@setOnClickListener
+            }
+            push("/order/create")
+        }
+        cart_frag_all_ck.setOnClickListener {
+            presenter.allCheck(cart_frag_all_ck.isChecked)
+        }
+        cart_refresh_layout.setHeaderHeight((ScreenTool.getScreenWidth(activity) * 0.25).pxToDp().toFloat())
+        cart_refresh_layout.setEnableRefresh(true)
+        cart_refresh_layout.setRefreshHeader(ClassicsHeader(activity))
+        cart_refresh_layout.setOnRefreshListener {
+            Handler().postDelayed({
+                presenter.loadCartData()
+                it.finishRefresh()
+            },1000)
+        }
+        getEventCenter().register(LoginEvent::class.java) {
+            presenter.loadCartData()
+        }.joinManager(disposableManager)
+        getEventCenter().register(LogoutEvent::class.java) {
+            showCartView(listOf(),0.0,0.0,0.0)
+        }.joinManager(disposableManager)
+        getEventCenter().register(CartDataChange::class.java) {
+            presenter.loadCartData()
+        }.joinManager(disposableManager)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:37
+     * @Note   显示购物车数据
+     * @param  cart 购物车数据
+     */
+    override fun showCartView(cart: List<Any>,price :Double,cashPrice :Double ,orgPrice :Double) {
+        var allCheck = true
+        adapterList.clear()
+        adapterList = ArrayList<DelegateAdapter.Adapter<*>>().then {
+            self ->
+            cart.forEach { item ->
+                when(item){
+                    is CartShopItemViewModel ->{
+                        if (allCheck){
+                            allCheck = item.isCheck
+                        }
+                        if (!hasSelectGoods){
+                            hasSelectGoods = item.isCheck
+                        }
+                        self.add(CartShopItemAdapter(this,item))
+                    }
+                    is String ->{
+                        if (item == "Holder"){
+                            /**
+                             * 占位视图
+                             */
+                            val holderView = VlayoutHolderAdapter(object : VlayoutHolderAdapter.HolderCallBack{
+                                override fun bindView(holder: RecyclerView.ViewHolder) {
+                                    holder.itemView.setBackgroundColor(Color.WHITE)
+                                    holder.itemView.layoutParams = VirtualLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (ScreenTool.dip2px(holder.itemView.context,15f)))
+                                }
+
+                                override fun layoutHelperProvider(): LayoutHelper {
+                                    return LinearLayoutHelper(0,1)
+                                }
+
+                                override fun viewHolderProvider(parent : ViewGroup): RecyclerView.ViewHolder {
+                                    return VlayoutHolderAdapter.PlaceHolder(View(parent.context))
+                                }
+
+                            })
+                            self.add(holderView)
+                        }else{
+                            self.add(CartPromotionItemAdapter(this,item))
+                        }
+                    }
+                    is CartGoodsItemViewModel ->{
+                        if (allCheck){
+                            allCheck = item.isCheck
+                        }
+                        if (!hasSelectGoods){
+                            hasSelectGoods = item.isCheck
+                        }
+                        self.add(CartGoodsItemAdapter(this, arrayListOf(item)))
+                    }
+                }
+            }
+        }
+        if (adapterList.count() == 0){
+            allCheck = false
+            hasSelectGoods = false
+        }
+        delegateAdapter.clear()
+        delegateAdapter.notifyDataSetChanged()
+        delegateAdapter.addAdapters(adapterList)
+        delegateAdapter.notifyDataSetChanged()
+        cart_frag_all_ck.isChecked = allCheck
+        cart_frag_price_tv.text = String.format("合计:¥%.2f",price)
+        cart_frag_promotion_price_tv.text = String.format("总额:¥%.2f 立减:¥%.2f",orgPrice,cashPrice)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:36
+     * @Note   列表店铺Item选中回调
+     * @param  shopId 店铺ID
+     * @param  checked 是否选中
+     */
+    override fun shopCheck(shopId: Int, checked: Boolean) {
+        presenter.shopCheck(shopId,checked)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:38
+     * @Note   商品选中回调
+     * @param  productId 商品ProductId
+     * @param  checked 是否选中
+     */
+    override fun goodsEdit(productId: Int, num: Int?, checked: Boolean?) {
+        presenter.editItem(productId,checked,num)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:39
+     * @Note   组合促销详细回调
+     * @param  cartPromotionItemViewModel 组合促销详细数据
+     */
+    override fun groupPromotionDetail(cartPromotionItemViewModel: CartPromotionItemViewModel) {
+
+    }
+
+    override fun showCoupon(coupons: ArrayList<CouponViewModel>) {
+        showPopView("优惠券", TextViewDelegateAdapter("可领取优惠券",23, Color.BLACK,10.dpToPx(),10.dpToPx(),10.dpToPx(),10.dpToPx(), Color.TRANSPARENT),
+                ReflexHelper.build("com.enation.javashop.android.component.member.adapter.CouponAdapter")
+                        .newInstance(coupons).getInstance<BaseDelegateAdapter<*, CouponViewModel>>().then {
+                            it.setOnItemClickListener { data, position ->
+                                presenter.getCoupon(data.id)
+                            }
+                        })
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:41
+     * @Note   单品促销选择回调
+     * @param  singglepromotionList 单品促销列表
+     */
+    override fun selectSingglePromotion(sellerId: Int, skuId: Int, singglepromotionList: List<SingglePromotionViewModel>?) {
+        var data : List<SingglePromotionViewModel> = ArrayList()
+        data += singglepromotionList!!
+        data += SingglePromotionViewModel(0,false,"取消促销","NONE")
+        val dialog = PopCommonView.build(activity)
+        dialog.setAdapters(CartSinglePromotionItemAdapter(data).then {
+                    it.setOnItemClickListener { data, position ->
+                        presenter.editPromotion(sellerId,skuId,data.promotionId,data.type)
+                        dialog.dismiss()
+                    }
+                })
+                .setTitle("促销")
+                .setConfirmVisable(false)
+                .show(cart_frag_header.holderViewProvider())
+    }
+
+    private fun showPopView(title: String ,vararg adapters : DelegateAdapter.Adapter<*>){
+        PopCommonView.build(activity)
+                .setAdapters(adapters.asList())
+                .setTitle(title)
+                .setConfirmVisable(false)
+                .show(cart_frag_header.holderViewProvider())
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:42
+     * @Note   显示商品Item更多操作Mask层
+     * @param  productId 商品productId
+     * @param  goodsId 商品Id
+     */
+    override fun showGoodsMoreMask(productId: Int, goodsId: Int) {
+       CommonTool.createVerifyDialog("请选择您要进行的操作","删除","收藏",activity,object :CommonTool.DialogInterface{
+           override fun yes() {
+               presenter.collectionGoods(goodsId)
+           }
+
+           override fun no() {
+               presenter.deleteGoods(productId)
+           }
+       }).then {
+           it.setCanceledOnTouchOutside(true)
+       }.show()
+    }
+
+    override fun deleteGoods(productId: Int) {
+        presenter.deleteGoods(productId)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:43
+     * @Note   显示店铺可领取优惠券
+     * @param  shopId 店铺Id
+     */
+    override fun showShopBonus(shopId: Int) {
+       presenter.loadCoupon(shopId)
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:43
+     * @Note   去店铺页面
+     * @param  shopId 店铺Id
+     */
+    override fun toShop(shopId: Int) {
+        push("/shop/detail",{
+            it.withInt("shopId",shopId)
+        })
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:43
+     * @Note   去商品页面
+     * @param  goodsId 商品ID
+     */
+    override fun toGoods(goodsId: Int) {
+        push("/goods/detail",{
+            it.withInt("goodsId",goodsId)
+        })
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:44
+     * @Note   逻辑操作失败回调
+     * @param  message 失败原因
+     */
+    override fun onError(message: String, type: Int) {
+        if (message != "未登录"){
+            showMessage(message)
+        }
+        getUtils().dismissDialog()
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:44
+     * @Note   逻辑操作完成回调
+     * @param  message 完成信息
+     */
+    override fun complete(message: String, type: Int) {
+        showMessage(message)
+        getUtils().dismissDialog()
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:44
+     * @Note   逻辑操作开始回调
+     */
+    override fun start() {
+        getUtils().showDialog()
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:45
+     * @Note   网络状态实时监听回调
+     * @param  state 网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+
+    }
+
+    /**
+     * @author LDD
+     * @From   CartFragment
+     * @Date   2018/2/24 下午4:36
+     * @Note   页面销毁时调用
+     */
+    override fun destory() {
+
+    }
+}

+ 26 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/launch/CartLaunch.kt

@@ -0,0 +1,26 @@
+package com.enation.javashop.android.component.cart.launch
+
+import com.enation.javashop.android.component.cart.di.CartComponent
+import com.enation.javashop.android.component.cart.di.DaggerCartComponent
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.android.lib.base.BaseLaunch
+import com.enation.javashop.android.middleware.di.DaggerManager
+
+/**
+ * @author LDD
+ * @Date   2018/1/22 下午2:44
+ * @From   com.enation.javashop.android.component.cart.launch
+ * @Note   Cart模块启动类 代替Application 在壳工程Application中反射调用
+ */
+@Router(path = "/cart/launch")
+class CartLaunch :BaseLaunch(){
+    companion object {
+        lateinit var component: CartComponent
+    }
+
+    override fun moduleInit() {
+        component = DaggerCartComponent.builder()
+                .applicationComponent(DaggerManager.APPLICATION_COMPONENT)
+                .build()
+    }
+}

+ 26 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/util/BaseCartItemAdapter.kt

@@ -0,0 +1,26 @@
+package com.enation.javashop.android.component.cart.util
+
+import android.support.v7.widget.RecyclerView
+import com.enation.javashop.android.lib.adapter.BaseDelegateAdapter
+
+
+/**
+ * @author LDD
+ * @Date   2018/2/6 下午5:06
+ * @From   com.enation.javashop.android.component.cart.util
+ * @Note   购物车Item基础适配器
+ */
+ abstract class BaseCartItemAdapter<VH : RecyclerView.ViewHolder,DataType>(private val cartAction : CartActionAgreement): BaseDelegateAdapter<VH, DataType>() {
+
+    /**
+     * @author LDD
+     * @From   BaseCartItemAdapter
+     * @Date   2018/2/9 下午2:02
+     * @Note   购物车操作协议提供者
+     * @return 购物车操作协议
+     */
+    fun actionProvider():CartActionAgreement{
+        return cartAction
+    }
+
+}

+ 91 - 0
cart/src/main/code/com/enation/javashop/android/component/cart/util/CartActionAgreement.kt

@@ -0,0 +1,91 @@
+package com.enation.javashop.android.component.cart.util
+
+import com.enation.javashop.android.middleware.model.CartPromotionItemViewModel
+import com.enation.javashop.android.middleware.model.SingglePromotionViewModel
+
+/**
+ * @author LDD
+ * @Date   2018/2/6 下午4:19
+ * @From   com.enation.javashop.android.component.cart.util
+ * @Note   购物车列表操作协议
+ */
+interface CartActionAgreement {
+
+    /**
+     * @author LDD
+     * @From   CartActionAgreement
+     * @Date   2018/2/6 下午4:25
+     * @Note   店铺选择
+     * @param  shopId 店铺Id
+     * @param  checked 是否选中
+     */
+    fun shopCheck(shopId :Int , checked : Boolean)
+
+    /**
+     * @author LDD
+     * @From   CartActionAgreement
+     * @Date   2018/2/6 下午4:26
+     * @Note   商品数量修改
+     * @param  productId 商品ID
+     * @param  num 修改后的数量
+     */
+    fun goodsEdit(productId: Int,num :Int?,checked: Boolean?)
+
+    /**
+     * @author LDD
+     * @From   CartActionAgreement
+     * @Date   2018/2/6 下午4:28
+     * @Note   组合促销详细
+     * @param  cartPromotionItemViewModel 组合促销详情
+     */
+    fun groupPromotionDetail(cartPromotionItemViewModel: CartPromotionItemViewModel)
+
+    /**
+     * @author LDD
+     * @From   CartActionAgreement
+     * @Date   2018/2/6 下午4:29
+     * @Note   单品促销选择
+     * @param  singglepromotionList 单品促销列表
+     */
+    fun selectSingglePromotion(sellerId :Int , skuId :Int,singglepromotionList : List<SingglePromotionViewModel>?)
+
+    /**
+     * @author LDD
+     * @From   CartActionAgreement
+     * @Date   2018/2/6 下午4:30
+     * @Note   显示商品操作遮罩
+     * @param  productId  商品skuId
+     * @param  goodsId    商品ID
+     */
+    fun showGoodsMoreMask(productId : Int , goodsId :Int)
+
+    /**
+     * @author LDD
+     * @From   CartActionAgreement
+     * @Date   2018/2/6 下午4:31
+     * @Note   显示店铺优惠券列表
+     * @param  shopId 店铺Id
+     */
+    fun showShopBonus(shopId: Int)
+
+    /**
+     * @author LDD
+     * @From   CartActionAgreement
+     * @Date   2018/2/24 下午1:43
+     * @Note   去店铺
+     * @param  shopId 店铺Id
+     */
+    fun toShop(shopId : Int)
+
+    /**
+     * @author LDD
+     * @From   CartActionAgreement
+     * @Date   2018/2/24 下午1:44
+     * @Note   去商品页
+     * @param  goodsId 商品ID
+     */
+    fun toGoods(goodsId :Int)
+
+    fun deleteGoods(productId: Int)
+
+}

+ 11 - 0
cart/src/main/res/layout/cart_act_lay.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+<FrameLayout
+    android:id="@+id/fragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+</FrameLayout>
+</android.support.constraint.ConstraintLayout>

+ 157 - 0
cart/src/main/res/layout/cart_frag_lay.xml

@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+    <android.support.constraint.ConstraintLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:app="http://schemas.android.com/apk/res-auto"
+        xmlns:bind="http://schemas.android.com/apk/res-auto"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        xmlns:tools="http://schemas.android.com/tools">
+        <com.enation.javashop.android.lib.widget.CommonActionBar
+            android:id="@+id/cart_frag_header"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toRightOf="parent"
+            bind:auto_topbar_height="@{true}"
+            app:title_text="购物车"
+            app:title_text_color="@color/javashop_color_black"
+            app:holder_visibility="false"
+            />
+        <android.support.constraint.ConstraintLayout
+            android:id="@+id/cart_frag_bottom_bar"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintDimensionRatio="h,7:1"
+            bind:backgroundColor="@{@color/javashop_color_white}"
+            android:background="@color/javashop_color_white"
+            >
+            <CheckBox
+                android:id="@+id/cart_frag_all_ck"
+                style="@style/constraintLayout_config"
+                android:layout_gravity="center_vertical"
+                android:background="@drawable/javashop_check_box_selector"
+                android:button="@null"
+                android:checked="true"
+                android:visibility="visible"
+                android:layout_marginLeft="10dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintDimensionRatio="w,1:1"
+                app:layout_constraintHeight_default="percent"
+                app:layout_constraintHeight_percent="0.4"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                />
+            <TextView
+                android:id="@+id/cart_frag_all_tv"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toRightOf="@id/cart_frag_all_ck"
+                app:layout_constraintWidth_percent="0.08"
+                android:text="全选"
+                android:lines="1"
+                style="@style/auto_text_size"
+                android:layout_marginLeft="5dp"
+                android:gravity="center"
+                android:textColor="@color/javashop_color_navy"
+                app:autoSizeMaxTextSize="100sp"
+                app:autoSizeMinTextSize="10sp"
+                app:autoSizeStepGranularity="2sp"
+                app:autoSizeTextType="uniform"
+                tools:ignore="MissingPrefix"
+                />
+            <TextView
+                android:id="@+id/cart_frag_create_order_tv"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintWidth_percent="0.3"
+                android:gravity="center"
+                android:lines="1"
+                android:text="去结算"
+                android:textSize="18sp"
+                android:textColor="@color/javashop_color_white"
+                android:background="@drawable/javashop_bg_red_shadow"
+                />
+            <TextView
+                android:id="@+id/cart_frag_price_tv"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:gravity="center_vertical"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toTopOf="@+id/cart_frag_promotion_price_tv"
+                app:layout_constraintLeft_toRightOf="@id/cart_frag_all_tv"
+                app:layout_constraintRight_toLeftOf="@id/cart_frag_create_order_tv"
+                android:text="合计:¥0.00"
+                app:layout_constraintHeight_percent="0.45"
+                android:lines="1"
+                style="@style/auto_text_size"
+                android:textStyle="bold"
+                android:layout_marginLeft="5dp"
+                android:layout_marginRight="5dp"
+                android:textColor="@color/javashop_color_navy"
+                app:autoSizeMaxTextSize="100sp"
+                app:autoSizeMinTextSize="10sp"
+                app:autoSizeStepGranularity="2sp"
+                app:autoSizeTextType="uniform"
+                tools:ignore="MissingPrefix"
+                />
+            <TextView
+                android:textStyle="bold"
+                android:id="@+id/cart_frag_promotion_price_tv"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:gravity="center_vertical"
+                app:layout_constraintTop_toBottomOf="@id/cart_frag_price_tv"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toRightOf="@id/cart_frag_all_tv"
+                app:layout_constraintRight_toLeftOf="@id/cart_frag_create_order_tv"
+                android:text="总额:¥0.00 立减¥0.00"
+                app:layout_constraintHeight_percent="0.3"
+                android:lines="1"
+                style="@style/auto_text_size"
+                android:layout_marginLeft="5dp"
+                android:layout_marginRight="5dp"
+                android:textColor="@color/javashop_color_navy"
+                app:autoSizeMaxTextSize="100sp"
+                app:autoSizeMinTextSize="1sp"
+                app:autoSizeStepGranularity="2sp"
+                app:autoSizeTextType="uniform"
+                tools:ignore="MissingPrefix"
+                />
+            <View
+                android:layout_width="0dp"
+                android:layout_height="0.5dp"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toLeftOf="@id/cart_frag_create_order_tv"
+                android:background="@color/color_gray"
+                />
+        </android.support.constraint.ConstraintLayout>
+        <com.scwang.smartrefresh.layout.SmartRefreshLayout
+            android:id="@+id/cart_refresh_layout"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            app:srlEnableLoadMore="false"
+            app:srlEnableRefresh="true"
+            app:srlHeaderHeight="100dp"
+            app:layout_constraintBottom_toTopOf="@id/cart_frag_bottom_bar"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/cart_frag_header">
+            <android.support.v7.widget.RecyclerView
+                android:id="@+id/cart_frag_rc_list"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@color/color_white"
+                />
+        </com.scwang.smartrefresh.layout.SmartRefreshLayout>
+    </android.support.constraint.ConstraintLayout>
+</layout>

+ 361 - 0
cart/src/main/res/layout/cart_goods_item.xml

@@ -0,0 +1,361 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:app="http://schemas.android.com/apk/res-auto">
+    <data>
+        <variable
+            name="goodsItemData"
+            type="com.enation.javashop.android.middleware.model.CartGoodsItemViewModel"/>
+        <import type="android.view.View"/>
+    </data>
+
+    <android.support.constraint.ConstraintLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:bind="http://schemas.android.com/apk/res-auto"
+        xmlns:tools="http://schemas.android.com/tools"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/javashop_color_white"
+        bind:backgroundColor="@{@color/javashop_color_white}"
+        >
+        <CheckBox
+            android:id="@+id/cart_goods_item_check"
+            android:layout_width="25dp"
+            android:layout_height="25dp"
+            android:layout_marginLeft="10dp"
+            android:layout_gravity="center_vertical"
+            android:background="@drawable/javashop_check_box_selector"
+            android:button="@null"
+            android:checked="@{goodsItemData.checkedObservable.get()}"
+            android:visibility="visible"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            />
+        <android.support.constraint.ConstraintLayout
+            android:id="@+id/cart_goods_item_content"
+            android:layout_marginLeft="10dp"
+            android:layout_width="0dp"
+            android:paddingBottom="10dp"
+            android:paddingLeft="10dp"
+            android:paddingTop="10dp"
+            android:layout_marginRight="10dp"
+            android:layout_height="wrap_content"
+            android:background="@drawable/javashop_shadow_white_bg"
+            bind:layout_constraintLeft_toRightOf="@id/cart_goods_item_check"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            >
+            <android.support.constraint.ConstraintLayout
+                android:id="@+id/goods_content"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                bind:layout_constraintDimensionRatio="h,10:3"
+                bind:layout_constraintLeft_toLeftOf="parent"
+                bind:layout_constraintRight_toRightOf="parent"
+                bind:layout_constraintTop_toTopOf="parent"
+                >
+                <ImageView
+                    android:id="@+id/cart_goods_item_iv"
+                    style="@style/constraintLayout_config"
+                    android:scaleType="centerCrop"
+                    bind:layout_constraintVertical_bias="0"
+                    app:layout_constraintDimensionRatio="h,1:1"
+                    bind:layout_constraintWidth_percent="0.3"
+                    bind:layout_constraintWidth_default="percent"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    bind:layout_constraintLeft_toLeftOf="parent"
+                    bind:layout_constraintRight_toRightOf="parent"
+                    app:layout_constraintTop_toTopOf="parent"
+                    bind:layout_constraintHorizontal_bias="0"
+                    bind:url="@{goodsItemData.imageUrl}"
+                    />
+                <ImageView
+                    android:id="@+id/cart_goods_item_nostack"
+                    style="@style/constraintLayout_config"
+                    android:scaleType="centerCrop"
+                    app:layout_constraintDimensionRatio="h,1:1"
+                    bind:layout_constraintWidth_percent="0.21"
+                    bind:layout_constraintLeft_toLeftOf="@id/cart_goods_item_iv"
+                    bind:layout_constraintRight_toRightOf="@id/cart_goods_item_iv"
+                    bind:layout_constraintTop_toTopOf="@id/cart_goods_item_iv"
+                    bind:layout_constraintBottom_toBottomOf="@id/cart_goods_item_iv"
+                    android:background="@drawable/javashop_icon_no_stock"
+                    android:visibility="@{goodsItemData.errorMessage.empty ? View.GONE : View.VISIBLE}"
+                    />
+                <TextView
+                    android:id="@+id/cart_goods_item_name_tv"
+                    android:layout_width="0dp"
+                    android:layout_height="0dp"
+                    bind:layout_constraintDimensionRatio="h,4:1"
+                    android:layout_marginLeft="10dp"
+                    android:layout_marginRight="10dp"
+                    android:ellipsize="end"
+                    android:lines="2"
+                    android:text="@{goodsItemData.name}"
+                    android:textColor="@color/javashop_color_cart_goods_item_name_tc"
+                    android:textSize="17sp"
+                    app:layout_constraintHeight_default="percent"
+                    app:layout_constraintLeft_toRightOf="@id/cart_goods_item_iv"
+                    app:layout_constraintRight_toRightOf="parent"
+                    app:layout_constraintTop_toTopOf="@id/cart_goods_item_iv"
+                    tools:ignore="MissingPrefix"
+                    />
+
+                <TextView
+                    android:id="@+id/cart_goods_item_spec_tv"
+                    style="@style/constraintLayout_config"
+                    android:layout_marginLeft="10dp"
+                    android:layout_marginRight="10dp"
+                    android:ellipsize="end"
+                    android:layout_marginTop="5dp"
+                    android:lines="1"
+                    android:text="@{goodsItemData.spec}"
+                    android:textColor="@color/javashop_color_cart_goods_item_spec_tc"
+                    app:autoSizeMaxTextSize="100sp"
+                    app:autoSizeMinTextSize="10sp"
+                    app:autoSizeStepGranularity="1sp"
+                    app:autoSizeTextType="uniform"
+                    app:layout_constraintHeight_default="percent"
+                    app:layout_constraintHeight_percent="0.15"
+                    app:layout_constraintLeft_toRightOf="@id/cart_goods_item_iv"
+                    app:layout_constraintRight_toRightOf="parent"
+                    app:layout_constraintTop_toBottomOf="@id/cart_goods_item_name_tv"
+                    tools:ignore="MissingPrefix"
+                    />
+
+                <ImageView
+                    android:id="@+id/cart_goods_add_btn"
+                    android:layout_width="0dp"
+                    android:layout_height="0dp"
+                    android:layout_marginBottom="5dp"
+                    android:layout_marginRight="5dp"
+                    android:padding="5dp"
+                    android:src="@drawable/javashop_cart_add_btn_bg"
+                    app:layout_constraintBottom_toBottomOf="@id/cart_goods_item_iv"
+                    app:layout_constraintDimensionRatio="w,1:1"
+                    app:layout_constraintRight_toRightOf="parent"
+                    app:layout_constraintWidth_default="percent"
+                    app:layout_constraintWidth_percent="0.07"
+                    />
+
+                <TextView
+                    android:id="@+id/cart_goods_num_tv"
+                    style="@style/constraintLayout_config"
+                    android:layout_marginLeft="10dp"
+                    android:gravity="center"
+                    android:lines="1"
+                    android:background="#f6f6f6"
+                    android:paddingBottom="3dp"
+                    android:paddingTop="3dp"
+                    android:paddingLeft="10dp"
+                    android:paddingRight="10dp"
+                    android:text="@{goodsItemData.currentNum}"
+                    android:textSize="12sp"
+                    app:layout_constraintRight_toLeftOf="@id/cart_goods_add_btn"
+                    app:layout_constraintTop_toTopOf="@id/cart_goods_add_btn"
+                    bind:layout_constraintBottom_toBottomOf="@id/cart_goods_add_btn"
+                    app:layout_constraintWidth_default="wrap"
+                    />
+
+                <ImageView
+                    android:id="@+id/cart_goods_reduce_btn"
+                    style="@style/constraintLayout_config"
+                    android:padding="5dp"
+                    android:src="@drawable/javashop_cart_add_reduce_bg"
+                    app:layout_constraintBottom_toBottomOf="@id/cart_goods_add_btn"
+                    app:layout_constraintDimensionRatio="h,1:1"
+                    app:layout_constraintRight_toLeftOf="@id/cart_goods_num_tv"
+                    app:layout_constraintTop_toTopOf="@id/cart_goods_add_btn"
+                    app:layout_constraintWidth_default="percent"
+                    app:layout_constraintWidth_percent="0.07"
+                    />
+
+                <TextView
+                    android:id="@+id/cart_goods_price_tv"
+                    style="@style/constraintLayout_config"
+                    android:gravity="center_vertical"
+                    android:paddingRight="10dp"
+                    android:textColor="@color/javashop_color_cart_goods_price"
+                    app:autoSizeMaxTextSize="100sp"
+                    app:autoSizeMinTextSize="10sp"
+                    app:autoSizeStepGranularity="2sp"
+                    app:autoSizeTextType="uniform"
+                    app:layout_constraintBottom_toBottomOf="@id/cart_goods_item_iv"
+                    app:layout_constraintHeight_default="percent"
+                    bind:layout_constraintTop_toBottomOf="@id/cart_goods_item_spec_tv"
+                    app:layout_constraintLeft_toRightOf="@id/cart_goods_item_iv"
+                    app:layout_constraintRight_toLeftOf="@id/cart_goods_reduce_btn"
+                    bind:layout_constraintWidth_percent="0.4"
+                    bind:layout_constraintDimensionRatio="h,6:1"
+                    tools:ignore="MissingPrefix"/>
+            </android.support.constraint.ConstraintLayout>
+
+            <LinearLayout
+                android:id="@+id/promotion_tag_parent"
+                android:orientation="horizontal"
+                android:visibility="@{goodsItemData.promotionList == null || goodsItemData.promotionList.size() == 0 ? View.GONE : View.VISIBLE}"
+                style="@style/constraintLayout_config"
+                android:layout_marginTop="5dp"
+                app:layout_constraintDimensionRatio="h,16.5:1"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/goods_content">
+            </LinearLayout>
+
+            <android.support.constraint.ConstraintLayout
+                android:id="@+id/cart_goods_item_error_lay"
+                style="@style/constraintLayout_config"
+                android:layout_marginTop="5dp"
+                android:visibility="@{goodsItemData.errorMessage.empty ? View.GONE : View.VISIBLE}"
+                app:layout_constraintDimensionRatio="h,16.5:1"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/promotion_tag_parent">
+
+                <TextView
+                    android:id="@+id/cart_goods_item_error_header"
+                    style="@style/constraintLayout_config"
+                    android:gravity="center"
+                    android:background="@drawable/javashop_fillet_red_circle_bg"
+                    android:text="无货原因"
+                    android:textColor="#f52523"
+                    app:autoSizeMaxTextSize="100sp"
+                    android:paddingLeft="2.5dp"
+                    android:paddingRight="2.5dp"
+                    app:autoSizeMinTextSize="10sp"
+                    app:autoSizeStepGranularity="2sp"
+                    app:autoSizeTextType="uniform"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintHeight_default="percent"
+                    app:layout_constraintHeight_percent="0.8"
+                    bind:layout_constraintLeft_toLeftOf="parent"
+                    app:layout_constraintTop_toTopOf="parent"
+                    app:layout_constraintWidth_default="percent"
+                    bind:layout_constraintWidth_percent="0.2"
+                    tools:ignore="MissingPrefix"
+                    />
+
+                <TextView
+                    android:id="@+id/cart_goods_item_error_edit"
+                    style="@style/constraintLayout_config"
+                    android:layout_marginRight="10dp"
+                    android:gravity="end"
+                    android:text="查看详情"
+                    android:textColor="@color/black"
+                    app:autoSizeMaxTextSize="100sp"
+                    app:autoSizeMinTextSize="7sp"
+                    app:autoSizeStepGranularity="2sp"
+                    app:autoSizeTextType="uniform"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintHeight_default="percent"
+                    app:layout_constraintHeight_percent="1"
+                    app:layout_constraintRight_toRightOf="parent"
+                    app:layout_constraintTop_toTopOf="parent"
+                    app:layout_constraintWidth_default="percent"
+                    bind:layout_constraintWidth_percent="0.18"
+                    tools:ignore="MissingPrefix"
+                    />
+
+                <TextView
+                    android:id="@+id/cart_goods_item_error_content"
+                    style="@style/constraintLayout_config"
+                    android:gravity="center_vertical"
+                    android:paddingLeft="10dp"
+                    android:text="@{goodsItemData.errorMessage}"
+                    android:textColor="#474747"
+                    android:ellipsize="end"
+                    app:autoSizeMaxTextSize="100sp"
+                    app:autoSizeMinTextSize="12sp"
+                    android:singleLine="true"
+                    app:autoSizeStepGranularity="2sp"
+                    app:autoSizeTextType="uniform"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintHeight_percent="1"
+                    app:layout_constraintLeft_toRightOf="@id/cart_goods_item_error_header"
+                    app:layout_constraintRight_toLeftOf="@id/cart_goods_item_error_edit"
+                    app:layout_constraintTop_toTopOf="parent"
+                    tools:ignore="MissingPrefix"
+                    />
+            </android.support.constraint.ConstraintLayout>
+
+
+            <android.support.constraint.ConstraintLayout
+                android:id="@+id/cart_goods_item_singgle_promotion_lay"
+                style="@style/constraintLayout_config"
+                android:layout_marginTop="5dp"
+                android:visibility="@{goodsItemData.promotionList == null || goodsItemData.promotionList.size() == 0 ? View.GONE : View.VISIBLE}"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintDimensionRatio="h,16.5:1"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/cart_goods_item_error_lay">
+
+                <TextView
+                    android:id="@+id/cart_goods_item_singgle_promotion_header"
+                    style="@style/constraintLayout_config"
+                    android:gravity="center"
+                    android:background="@drawable/javashop_fillet_red_circle_bg"
+                    android:text="@string/javashop_promotion_string"
+                    android:textColor="#f52523"
+                    app:autoSizeMaxTextSize="100sp"
+                    android:paddingLeft="2.5dp"
+                    android:paddingRight="2.5dp"
+                    app:autoSizeMinTextSize="10sp"
+                    app:autoSizeStepGranularity="2sp"
+                    app:autoSizeTextType="uniform"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintHeight_default="percent"
+                    app:layout_constraintHeight_percent="0.8"
+                    bind:layout_constraintLeft_toLeftOf="parent"
+                    app:layout_constraintTop_toTopOf="parent"
+                    app:layout_constraintWidth_default="percent"
+                    bind:layout_constraintWidth_percent="0.125"
+                    tools:ignore="MissingPrefix"
+                    />
+
+                <TextView
+                    android:id="@+id/cart_goods_item_singgle_promotion_edit"
+                    style="@style/constraintLayout_config"
+                    android:layout_marginRight="10dp"
+                    android:gravity="end"
+                    android:text="@string/javashop_singgle_promotion_edit_string"
+                    android:textColor="@color/black"
+                    app:autoSizeMaxTextSize="100sp"
+                    app:autoSizeMinTextSize="7sp"
+                    app:autoSizeStepGranularity="2sp"
+                    app:autoSizeTextType="uniform"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintHeight_default="percent"
+                    app:layout_constraintHeight_percent="1"
+                    app:layout_constraintRight_toRightOf="parent"
+                    app:layout_constraintTop_toTopOf="parent"
+                    app:layout_constraintWidth_default="percent"
+                    bind:layout_constraintWidth_percent="0.15"
+                    tools:ignore="MissingPrefix"
+                    />
+
+                <TextView
+                    android:id="@+id/cart_goods_item_singgle_promotion_content"
+                    style="@style/constraintLayout_config"
+                    android:gravity="center_vertical"
+                    android:paddingLeft="10dp"
+                    android:text="@{goodsItemData.title()}"
+                    android:textColor="#474747"
+                    app:autoSizeMaxTextSize="100sp"
+                    app:autoSizeMinTextSize="7sp"
+                    app:autoSizeStepGranularity="2sp"
+                    app:autoSizeTextType="uniform"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintHeight_percent="1"
+                    app:layout_constraintLeft_toRightOf="@id/cart_goods_item_singgle_promotion_header"
+                    app:layout_constraintRight_toLeftOf="@id/cart_goods_item_singgle_promotion_edit"
+                    app:layout_constraintTop_toTopOf="parent"
+                    tools:ignore="MissingPrefix"
+                    />
+            </android.support.constraint.ConstraintLayout>
+
+        </android.support.constraint.ConstraintLayout>
+
+
+
+    </android.support.constraint.ConstraintLayout>
+</layout>

+ 66 - 0
cart/src/main/res/layout/cart_promotion_item.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+    <data>
+        <import type="android.view.View"/>
+        <variable
+            name="promotionItemData"
+            type="String"/>
+    </data>
+<android.support.constraint.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="40dp"
+    android:background="@color/javashop_color_cart_promotion_item_bg"
+    >
+    <TextView
+        android:layout_marginLeft="45dp"
+        android:id="@+id/cart_promotion_tag"
+        style="@style/auto_text_size"
+        app:autoSizeMaxTextSize="100sp"
+        app:autoSizeMinTextSize="1sp"
+        app:autoSizeStepGranularity="2sp"
+        android:paddingLeft="5dp"
+        android:paddingRight="5dp"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:autoSizeTextType="uniform"
+        android:background="@drawable/javashop_red_radis_bg"
+        android:gravity="center"
+        android:text="满优惠"
+        android:textColor="@color/color_white"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintHeight_default="percent"
+        app:layout_constraintHeight_percent="0.5"
+        app:layout_constraintWidth_percent="0.13"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:ignore="MissingPrefix"
+        />
+    <TextView
+        android:id="@+id/cart_promotion_content_tv"
+        style="@style/auto_text_size"
+        app:autoSizeMaxTextSize="100sp"
+        app:autoSizeMinTextSize="1sp"
+        app:autoSizeStepGranularity="2sp"
+        android:paddingLeft="5dp"
+        android:paddingRight="5dp"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:autoSizeTextType="uniform"
+        android:gravity="center_vertical"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="10dp"
+        android:textColor="@color/javashop_color_navy"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintHeight_default="percent"
+        app:layout_constraintHeight_percent="0.55"
+        app:layout_constraintLeft_toRightOf="@id/cart_promotion_tag"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        tools:ignore="MissingPrefix"
+        android:text="@{promotionItemData}"
+        />
+</android.support.constraint.ConstraintLayout>
+</layout>

+ 104 - 0
cart/src/main/res/layout/cart_shop_item.xml

@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+    <data>
+        <variable
+            name="shopItemData"
+            type="com.enation.javashop.android.middleware.model.CartShopItemViewModel"/>
+        <import type="android.view.View"/>
+    </data>
+<android.support.constraint.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="40dp"
+    android:background="@color/javashop_color_transparent">
+
+   <android.support.constraint.ConstraintLayout
+       style="@style/constraintLayout_config"
+       app:layout_constraintLeft_toLeftOf="parent"
+       app:layout_constraintRight_toRightOf="parent"
+       app:layout_constraintTop_toTopOf="parent"
+       app:layout_constraintHeight_default="percent"
+       app:layout_constraintHeight_percent="1"
+       >
+       <android.support.constraint.Guideline
+           android:id="@+id/ver_line"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:orientation="vertical"
+           app:layout_constraintGuide_percent="0.7"/>
+
+       <CheckBox
+           android:id="@+id/cart_shop_item_check"
+           android:layout_width="25dp"
+           android:layout_height="25dp"
+           android:layout_gravity="center_vertical"
+           android:layout_marginLeft="10dp"
+           android:background="@drawable/javashop_check_box_selector"
+           android:button="@null"
+           android:checked="@{shopItemData.isCheck}"
+           android:visibility="visible"
+           app:layout_constraintBottom_toBottomOf="parent"
+           app:layout_constraintLeft_toLeftOf="parent"
+           app:layout_constraintTop_toTopOf="parent"
+           />
+
+       <ImageView
+           android:id="@+id/cart_shop_item_icon_iv"
+           style="@style/constraintLayout_config"
+           android:layout_height="20dp"
+           android:layout_marginLeft="5dp"
+           android:src="@{shopItemData.self ? @drawable/javashop_cart_self_shop_icon : @drawable/javashop_cart_shop_icon}"
+           app:layout_constraintBottom_toBottomOf="parent"
+           app:layout_constraintDimensionRatio="w,1:1"
+           app:layout_constraintHeight_default="percent"
+           app:layout_constraintHeight_percent="0.5"
+           app:layout_constraintLeft_toRightOf="@id/cart_shop_item_check"
+           app:layout_constraintTop_toTopOf="parent"/>
+
+       <TextView
+           android:id="@+id/cart_shop_item_name_tv"
+           style="@style/constraintLayout_config"
+           android:layout_marginLeft="5dp"
+           android:textColor="@color/javashop_color_cart_shop_item_name_tc"
+           android:gravity="center_vertical"
+           android:text="@{shopItemData.name}"
+           app:layout_constraintBottom_toBottomOf="parent"
+           app:layout_constraintLeft_toRightOf="@id/cart_shop_item_icon_iv"
+           app:layout_constraintTop_toTopOf="parent"
+           app:layout_constraintRight_toLeftOf="@id/ver_line"
+           app:autoSizeMaxTextSize="100sp"
+           app:autoSizeMinTextSize="10sp"
+           app:autoSizeStepGranularity="2sp"
+           app:autoSizeTextType="uniform"
+           tools:ignore="MissingPrefix"
+           app:layout_constraintHeight_default="percent"
+           app:layout_constraintHeight_percent="0.65"
+           />
+
+       <TextView
+           android:id="@+id/cart_shop_item_right_tv"
+           style="@style/constraintLayout_config"
+           app:autoSizeMaxTextSize="100sp"
+           app:autoSizeMinTextSize="10sp"
+           app:autoSizeStepGranularity="2sp"
+           app:autoSizeTextType="uniform"
+           tools:ignore="MissingPrefix"
+           android:gravity="right"
+           android:text="@string/javashop_cart_shop_item_title"
+           android:textColor="@color/javashop_color_navy"
+           app:layout_constraintBottom_toBottomOf="parent"
+           app:layout_constraintHeight_default="percent"
+           app:layout_constraintHeight_percent="0.6"
+           app:layout_constraintLeft_toRightOf="@id/ver_line"
+           app:layout_constraintRight_toRightOf="parent"
+           app:layout_constraintTop_toTopOf="parent"
+           android:visibility="@{shopItemData.hasBouns ?  View.VISIBLE : View.GONE}"
+           android:layout_marginRight="10dp"
+           />
+
+
+   </android.support.constraint.ConstraintLayout>
+</android.support.constraint.ConstraintLayout>
+</layout>

+ 41 - 0
cart/src/main/res/layout/cart_single_promotion_lay.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:app="http://schemas.android.com/apk/res-auto">
+    <android.support.constraint.ConstraintLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <TextView
+            android:gravity="center"
+            android:id="@+id/tag"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            app:layout_constraintHeight_percent="0.7"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintLeft_toLeftOf="parent"
+            android:textSize="15sp"
+            android:layout_marginTop="5dp"
+            android:layout_marginBottom="5dp"
+            android:layout_marginLeft="10dp"
+            android:padding="2dp"
+            android:textColor="@color/javashop_color_price_red"
+            android:background="@drawable/javashop_fillet_red_bg"
+            />
+        <TextView
+            android:id="@+id/content"
+            android:layout_width="0dp"
+            android:gravity="center_vertical"
+            android:layout_height="0dp"
+            android:textSize="15sp"
+            app:layout_constraintLeft_toRightOf="@id/tag"
+            android:layout_marginLeft="10dp"
+            android:layout_marginTop="5dp"
+            android:layout_marginBottom="5dp"
+            android:textColor="@color/javashop_color_navy"
+            android:layout_marginRight="10dp"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintRight_toRightOf="parent"
+            />
+    </android.support.constraint.ConstraintLayout>
+</layout>

+ 3 - 0
cart/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">cart</string>
+</resources>

+ 17 - 0
cart/src/test/java/com/enation/javashop/android/component/cart/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.enation.javashop.android.component.cart;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() throws Exception {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 1 - 0
common/.gitignore

@@ -0,0 +1 @@
+/build

+ 275 - 0
common/build.gradle

@@ -0,0 +1,275 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+android {
+    compileSdkVersion target_sdk_version
+    buildToolsVersion build_tools_version
+
+    defaultConfig {
+        minSdkVersion min_sdk_version
+        targetSdkVersion target_sdk_version
+        versionCode app_version_code
+        versionName app_version
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+        dataBinding {
+            enabled = true
+        }
+//        ndk{
+//            moduleName "JavaShopCommonNDK"       //生成的so文件名字,调用C程序的代码中会用到该名字
+//            abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种平台下的so库
+//        }
+    }
+    lintOptions {
+        abortOnError false
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+//        debug {
+//            jniDebuggable true
+//        }
+    }
+    sourceSets {
+        main.java.srcDirs += 'src/main/code'
+//        main.jni.srcDirs = []
+//        main.jniLibs.srcDir 'src/main/libs'
+    }
+}
+
+dependencies {
+    compile fileTree(include: ['*.jar'], dir: 'libs')
+    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+
+    /**
+     * UI适配
+     */
+    compile 'me.jessyan:autosize:1.1.1'
+
+    /**
+     *  圆形ImageView
+     */
+    compile 'de.hdodenhof:circleimageview:2.2.0'
+
+    /**
+     *  JavaShop_Android 基础工具库
+     */
+    compile 'com.enation.geamtear.util:base:1.1.4'
+
+    /**
+     *  JavaShop_Android 网络库
+     */
+    compile 'com.enation.geamtear.net:engine:1.1.5'
+
+    /**
+     *  JavaShop_Android 图片加载库
+     */
+    compile 'com.enation.geamtear.image:glidepluin:1.0.2'
+
+    /**
+     *  JavaShop_Android 第三方工具库
+     */
+    compile 'com.enation.geamtear.widget:ConnectView:1.1.1'
+
+    /**
+     *  JavaShop_Android 支付工具库
+     */
+    compile 'com.enation.geamtear.pay:payutils:1.0.2'
+
+    /**
+     *  JavaShop_Android 地区选择工具库
+     */
+    compile 'com.enation.geamtear.widget:districtselectorview:1.0.6'
+
+    /**
+     *  JavaShop_Android 导航View
+     */
+    compile 'com.enation.geamtear.widget:NavigationView:1.1.0'
+
+    /**
+     *  JavaShop_Android 路由
+     */
+    compile 'com.enation.geamtear:jrouter-logic:1.0.3'
+
+    /**
+     *  JavaShop_Android 图片选择工具库
+     */
+    compile('com.enation.geamtear.photo:takephoto:1.0.2') {
+        exclude group: 'com.github.bumptech.glide'
+        exclude group: 'io.reactivex.rxjava2'
+    }
+
+    /**
+     *  JavaShop_Android Log日志库
+     */
+    compile 'com.enation.geamtear.util:logger:1.0.7'
+
+    /**
+     *   Android基础依赖库
+     */
+    compile "com.android.support:design:$support_library_version"
+    compile "com.android.support:support-v4:$support_library_version"
+    compile "com.android.support:cardview-v7:$support_library_version"
+    testCompile 'junit:junit:4.12'
+
+    /**
+     *   突破方法数限制
+     */
+    compile 'com.android.support:multidex:1.0.2'
+
+
+    compile 'com.github.1002326270xc:LayoutManager-FlowLayout:v1.7'
+
+    /**
+     *   刷新数据控件
+     */
+    compile 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-18'
+
+    /**
+     *   动画框架 巨牛逼
+     */
+    compile 'com.airbnb.android:lottie:1.5.3'
+
+    /**
+     *  Kotlin依赖
+     */
+    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+    compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.19.3'
+
+    /**
+     *  Databinding
+     */
+    kapt "com.android.databinding:compiler:2.3.3"
+
+    /**
+     *  Dagger依赖
+     */
+    compile 'com.google.dagger:dagger:2.7'
+
+    /**
+     *  Dagger编译依赖
+     */
+    kapt 'com.google.dagger:dagger-compiler:2.7'
+
+    /**
+     *  七巧板框架
+     */
+    compile 'com.alibaba.android:tangram:2.0.0@aar'
+    compile('com.alibaba.android:vlayout:1.2.6.1@aar') {
+        changing = true
+    }
+    compile 'com.alibaba.android:ultraviewpager:1.0.6.5@aar'
+    compile('me.everything:overscroll-decor-android:1.0.1@aar') {
+        transitive true
+        exclude group: 'com.android.support', module: 'recyclerview-v7'
+    }
+    compile('com.alibaba.android:virtualview:1.0.2@aar') {
+        transitive true
+        exclude group: 'com.android.support', module: 'appcompat-v7'
+        exclude group: 'com.tmall.android', module: 'tmallandroid_mui'
+        exclude group: 'com.google.android', module: 'support-v7-recyclerview'
+        exclude group: 'com.android.support', module: 'support-v4'
+        exclude group: 'com.android.support', module: 'support-annotations'
+    }
+
+    //compile 'com.alibaba.android:tangram:2.2.1@aar'
+
+    /**
+     *  Aop埋点
+     */
+    compile "org.aspectj:aspectjrt:$aspectj_version"
+
+    /**
+     *  constraint-layout布局依赖
+     */
+    compile 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
+
+    /**
+     * 指示器
+     */
+    compile 'com.github.hackware1993:magicindicator:1.5.0'
+
+    /**
+     * 汉字辅助
+     */
+    compile files('libs/chinese2py.jar')
+
+    /**
+     * 二维码扫描
+     */
+    compile 'cn.yipianfengye.android:zxing-library:2.2'
+
+    /**
+     * GLIDE 图片处理器
+     */
+    compile ('jp.wasabeef:glide-transformations:2.0.1') {
+        exclude group: 'com.github.bumptech.glide'
+    }
+
+    /**
+     * 时间选择器
+     */
+    compile 'com.contrarywind:Android-PickerView:4.1.6'
+
+    /**
+     * 图片查看器
+     */
+    compile 'com.github.iielse:ImageWatcher:1.1.5'
+
+    /**
+     * 权限控制
+     */
+    compile 'pub.devrel:easypermissions:0.2.0'
+
+
+    compile 'com.github.pinguo-zhouwei:MZBannerView:v2.0.2'
+
+
+    /**
+     * 推送
+     */
+    compile 'com.umeng.sdk:common:1.5.3'
+    compile 'com.umeng.sdk:utdid:1.1.5.3'
+    compile 'com.umeng.sdk:push:4.2.0'
+}
+
+//tasks.withType(JavaCompile) {
+//    compileTask -> compileTask.dependsOn ndkBuild
+//}
+//
+//task ndkBuild(type: Exec) {
+//    workingDir file('src/main/jni')
+//    commandLine getNdkBuildCmd()
+//}
+//
+//task cleanNative(type: Exec){
+//    workingDir file('src/main/jni')
+//    commandLine getNdkBuildCmd(), 'clean'
+//}
+//
+//clean.dependsOn cleanNative
+//
+//def getNdkDir() {
+//    if (System.env.ANDROID_NDK_ROOT != null)
+//        return System.env.ANDROID_NDK_ROOT
+//    Properties properties = new Properties()
+//    properties.load(project.rootProject.file('local.properties').newDataInputStream())
+//    def ndkdir = properties.getProperty('ndk.dir', null)
+//    if (ndkdir == null)
+//        throw new GradleException("NDK location not found. Define location with ndk.dir in the local.properties file or with an ANDROID_NDK_ROOT environment variable.")
+//    return ndkdir
+//}
+//
+//def getNdkBuildCmd() {
+//    def ndkbuild = getNdkDir() + "/ndk-build"
+//    //Window下需要加.cmd后缀,Mac下则不需要
+//    ndkbuild += ""
+//    return ndkbuild
+//}
+
+

BIN
common/libs/chinese2py.jar


+ 17 - 0
common/proguard-rules.pro

@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/Android/MAC_SDK/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}

+ 26 - 0
common/src/androidTest/java/com/enation/javashop/android/lib/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.enation.javashop.android.lib;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.enation.javashop.android.lib.test", appContext.getPackageName());
+    }
+}

+ 18 - 0
common/src/main/AndroidManifest.xml

@@ -0,0 +1,18 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.enation.javashop.android.lib">
+
+    <application android:allowBackup="true"
+                 android:label="@string/app_name"
+                 android:supportsRtl="true"
+    >
+        <receiver android:name=".utils.NetReceiver" >
+            <intent-filter>
+                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+            </intent-filter>
+        </receiver>
+    </application>
+
+    <uses-permission android:name="android.permission.VIBRATE"></uses-permission>
+    <uses-permission android:name="android.permission.FLASHLIGHT"></uses-permission>
+
+</manifest>

+ 156 - 0
common/src/main/code/com/enation/javashop/android/lib/adapter/BaseDelegateAdapter.kt

@@ -0,0 +1,156 @@
+package com.enation.javashop.android.lib.adapter
+
+import android.support.v7.widget.RecyclerView
+import android.widget.ImageView
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.enation.javashop.android.lib.utils.dpToPx
+import com.enation.javashop.android.lib.utils.more
+import com.enation.javashop.imagepluin.R
+import jp.wasabeef.glide.transformations.CropSquareTransformation
+import jp.wasabeef.glide.transformations.RoundedCornersTransformation
+
+/**
+ * @author LDD
+ * @Date   2018/1/30 上午11:46
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   DelegateAdapter基类 添加了点击长按事件
+ */
+abstract class BaseDelegateAdapter<VH : RecyclerView.ViewHolder, out DataType> : DelegateAdapter.Adapter<VH>() {
+
+    /**
+     * @Name  tag
+     * @Type  Any
+     * @Note  标识Adapter的标签 同一个列表内 不可使用重复Tag 否则会造成查找失败
+     */
+    var tag : Any? = null
+
+    /**
+     * @Name  itemClickListener
+     * @Type  ((data:DataType, position:Int)->(Unit))?
+     * @Note  点击事件
+     */
+    private var itemClickListener :((data:DataType, position:Int)->(Unit))? = null
+
+    /**
+     * @Name  itemClickListener
+     * @Type  ((data:DataType, position:Int)->(Unit))?
+     * @Note  长按事件
+     */
+    private var itemLongClickListener :((data:DataType, position:Int)->(Unit))? = null
+
+    /**
+     * @author LDD
+     * @From   BaseDelegateAdapter
+     * @Date   2018/2/6 上午10:40
+     * @Note   数据提供者
+     * @return 数据源
+     */
+    abstract fun dataProvider():Any
+
+    /**
+     * @author LDD
+     * @From   BaseDelegateAdapter
+     * @Date   2018/2/6 上午10:40
+     * @Note   数据源处理器 判断是单个数据 还是数据集合
+     * @return 全部转换为数据集合
+     */
+    private fun dataProcessor():List<DataType>{
+        return if (dataProvider() is List<*> || dataProvider() is ArrayList<*>){
+            dataProvider() as List<DataType>
+        }else{
+            listOf(dataProvider() as DataType)
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseDelegateAdapter
+     * @Date   2018/1/30 上午11:54
+     * @Note   设置item点击事件
+     * @param  itemClickListener 点击回调
+     */
+    fun setOnItemClickListener(itemClickListener:(data:DataType,position:Int)->(Unit)){
+        this.itemClickListener = itemClickListener
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseDelegateAdapter
+     * @Date   2018/1/30 上午11:54
+     * @Note   设置item点击事件
+     * @param  itemLongClickListener 长按回调
+     */
+    fun setOnItemLongClickListener(itemLongClickListener: (data:DataType,position:Int)->(Unit)){
+        this.itemLongClickListener = itemLongClickListener
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseDelegateAdapter
+     * @Date   2018/1/30 上午11:55
+     * @Note   重写该方法 对item进行事件配置
+     */
+    override fun onBindViewHolderWithOffset(holder: VH, position: Int, offsetTotal: Int) {
+        super.onBindViewHolderWithOffset(holder, position, offsetTotal)
+        if (itemFilter(position)){
+            itemClickListener?.more {
+                self ->
+                holder.itemView.setOnClickListener {
+                    self.invoke(dataProcessor()[position],position)
+                }
+            }
+            itemLongClickListener?.more {
+                self ->
+                holder.itemView.setOnLongClickListener {
+                    self.invoke(dataProcessor()[position],position)
+                    return@setOnLongClickListener true
+                }
+            }
+        }else{
+            holder.itemView.setOnLongClickListener{true}
+            holder.itemView.setOnClickListener{}
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseDelegateAdapter
+     * @Date   2018/2/9 下午2:18
+     * @Note   获取item对应数据
+     * @param  item坐标
+     */
+    open fun getItem(position: Int):DataType{
+        return dataProcessor()[position]
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseDelegateAdapter
+     * @Date   2018/1/30 上午11:56
+     * @Note   用来拦截是否为该item配置响应事件
+     * @param  position item坐标
+     */
+    abstract fun itemFilter(position: Int):Boolean
+
+
+    fun loadImage(url :String,imageView :ImageView){
+        Glide.with(imageView.context)
+                .load(url)
+                .thumbnail(0.1f)
+                .diskCacheStrategy(DiskCacheStrategy.ALL)
+                .placeholder(R.drawable.image_loading)
+                .error(R.drawable.image_error)
+                .into(imageView)
+    }
+
+    fun loadImageRound(url :String,imageView: ImageView,cornerType: RoundedCornersTransformation.CornerType = RoundedCornersTransformation.CornerType.ALL){
+        Glide.with(imageView.context)
+                .load(url)
+                .thumbnail(0.1f)
+                .bitmapTransform(RoundedCornersTransformation(imageView.context,3.dpToPx(),0,cornerType))
+                .into(imageView)
+    }
+
+}

+ 114 - 0
common/src/main/code/com/enation/javashop/android/lib/adapter/ListViewBaseAdapter.kt

@@ -0,0 +1,114 @@
+package com.enation.javashop.android.lib.adapter
+
+import android.content.Context
+import android.databinding.ViewDataBinding
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.databinding.DataBindingUtil
+import android.view.LayoutInflater
+
+/**
+ * @author LDD
+ * @Date   2018/1/30 上午11:33
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   listView单一种类Item 快速适配器
+ */
+abstract class ListViewBaseAdapter<DataType, in BindingType:ViewDataBinding>constructor(private val context: Context, private val layout:Int, var datas : List<DataType>) : BaseAdapter() {
+
+    /**
+     * @Name  binding
+     * @Type  BindingType
+     * @Note  databinding工具类
+     */
+    private lateinit var binding : BindingType
+
+    /**
+     * @author LDD
+     * @From   ListViewBaseAdapter
+     * @Date   2018/1/30 上午11:35
+     * @Note   获取View
+     * @param  position 坐标
+     * @param  convertView item
+     * @param  parent  父容器
+     */
+    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+        var currentView = convertView
+        if (currentView == null) {
+            binding = DataBindingUtil.inflate(LayoutInflater.from(context), layout, parent, false)
+            currentView = binding.root
+            reSize(currentView)
+            currentView.tag = binding
+        } else {
+            binding = currentView.tag as BindingType
+        }
+        fillItem(binding,datas.get(position),position)
+        binding.root.setOnClickListener {
+            itemClick(datas.get(position),position)
+        }
+        return currentView!!
+    }
+
+    /**
+     * @author LDD
+     * @From   ListViewBaseAdapter
+     * @Date   2018/1/30 上午11:36
+     * @Note   获取item数据
+     * @param  position 坐标
+     */
+    override fun getItem(position: Int): DataType {
+        return datas.get(position)
+    }
+
+    /**
+     * @author LDD
+     * @From   ListViewBaseAdapter
+     * @Date   2018/1/30 上午11:36
+     * @Note   获取ItemID
+     * @param  position 坐标
+     */
+    override fun getItemId(position: Int): Long {
+        return position.toLong()
+    }
+
+    /**
+     * @author LDD
+     * @From   ListViewBaseAdapter
+     * @Date   2018/1/30 上午11:37
+     * @Note   获取item总数
+     * @return item总数
+     */
+    override fun getCount(): Int {
+        return datas.count()
+    }
+
+    /**
+     * @author LDD
+     * @From   ListViewBaseAdapter
+     * @Date   2018/1/30 上午11:37
+     * @Note   抽象方法 填充数据
+     * @param  binding databinding
+     * @param  data 数据
+     * @param  position 坐标
+     */
+    abstract fun fillItem(binding: BindingType , data:DataType ,position: Int)
+
+    /**
+     * @author LDD
+     * @From   ListViewBaseAdapter
+     * @Date   2018/1/30 上午11:39
+     * @Note   重新设置item大小
+     * @param  convertView item
+     */
+    open fun reSize(convertView: View){}
+
+    /**
+     * @author LDD
+     * @From   ListViewBaseAdapter
+     * @Date   2018/1/30 上午11:39
+     * @Note   item点击事件
+     * @param  data itemData
+     * @param  position 坐标
+     */
+    open fun itemClick(data:DataType ,position: Int){}
+}

+ 171 - 0
common/src/main/code/com/enation/javashop/android/lib/adapter/TextViewDelegateAdapter.kt

@@ -0,0 +1,171 @@
+package com.enation.javashop.android.lib.adapter
+
+import android.graphics.Color
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.enation.javashop.android.lib.R
+import com.enation.javashop.android.lib.databinding.TextAdapterLayBinding
+import com.enation.javashop.android.lib.utils.BaseRecyclerViewHolder
+import com.enation.javashop.android.lib.utils.then
+
+/**
+ * @author LDD
+ * @Date   2018/4/19 下午2:12
+ * @From   com.enation.javashop.android.lib.adapter
+ * @Note   文字视图Item适配器
+ */
+class TextViewDelegateAdapter(val text :String,val textLineCount :Int ,val textColor :Int ,val top : Int = 0 ,val bottom : Int = 0 ,val left : Int = 0 ,val right : Int = 0,val bgColor:Int = Color.WHITE) :BaseDelegateAdapter<BaseRecyclerViewHolder<TextAdapterLayBinding>,Int>(){
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:17
+     * @Note   数据提供者
+     */
+    override fun dataProvider(): Any {
+        return -1
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:17
+     * @Note   item点击过滤
+     * @param  position item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:18
+     * @Note   构建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<TextAdapterLayBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.text_adapter_lay)
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:19
+     * @Note   获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return 1
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:19
+     * @Note   构建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0,1).then {
+            self ->
+            self.setMargin(left,top,right,bottom)
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:20
+     * @Note   绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<TextAdapterLayBinding>?, position: Int) {
+
+        holder?.bind {
+            binding ->
+            binding.count = textLineCount
+            binding.textview.setTextColor(textColor)
+            binding.text = text
+            binding.root.setBackgroundColor(bgColor)
+        }
+
+    }
+
+}
+
+
+
+
+class TextViewListDelegateAdapter(val text :ArrayList<String>,val textLineCount :Int ,val textColor :Int ,val top : Int = 0 ,val bottom : Int = 0 ,val left : Int = 0 ,val right : Int = 0,val bgColor:Int = Color.WHITE) :BaseDelegateAdapter<BaseRecyclerViewHolder<TextAdapterLayBinding>,String>(){
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:17
+     * @Note   数据提供者
+     */
+    override fun dataProvider(): Any {
+        return text
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:17
+     * @Note   item点击过滤
+     * @param  position item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:18
+     * @Note   构建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<TextAdapterLayBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.text_adapter_lay)
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:19
+     * @Note   获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return text.count()
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:19
+     * @Note   构建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0,1).then {
+            self ->
+            self.setMargin(left,top,right,bottom)
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   TextViewDelegateAdapter
+     * @Date   2018/4/19 下午3:20
+     * @Note   绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<TextAdapterLayBinding>?, position: Int) {
+
+        holder?.bind {
+            binding ->
+            binding.count = textLineCount
+            binding.textview.setTextColor(textColor)
+            binding.text = getItem(position)
+            binding.root.setBackgroundColor(bgColor)
+        }
+
+    }
+
+}

+ 74 - 0
common/src/main/code/com/enation/javashop/android/lib/adapter/VlayoutHolderAdapter.kt

@@ -0,0 +1,74 @@
+package com.enation.javashop.android.lib.adapter
+
+import android.support.v7.widget.RecyclerView
+import android.view.View
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.LayoutHelper
+
+const val  VlayoutItemType   = 7321
+
+class VlayoutHolderAdapter(val callBack : HolderCallBack) : DelegateAdapter.Adapter<RecyclerView.ViewHolder>() {
+
+    /**
+     * @author LDD
+     * @From   CategoryPlaceHolderAdapter
+     * @Date   2018/1/30 下午2:42
+     * @Note   ViewHolder创建
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+        return callBack.viewHolderProvider(parent)
+    }
+
+    /**
+     * @author LDD
+     * @From   CategoryPlaceHolderAdapter
+     * @Date   2018/1/30 下午2:42
+     * @Note   Item总数
+     */
+    override fun getItemCount(): Int {
+        return onCreateLayoutHelper().itemCount
+    }
+
+    override fun getItemViewType(position: Int): Int {
+        return VlayoutItemType
+    }
+
+    /**
+     * @author LDD
+     * @From   CategoryPlaceHolderAdapter
+     * @Date   2018/1/30 下午2:42
+     * @Note   提供LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return callBack.layoutHelperProvider()
+    }
+
+    /**
+     * @author LDD
+     * @From   CategoryPlaceHolderAdapter
+     * @Date   2018/1/30 下午2:42
+     * @Note   绑定ViewHolder
+     */
+    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+        callBack.bindView(holder)
+    }
+
+    /**
+     * @author LDD
+     * @Date   2018/1/30 下午2:44
+     * @From   CategoryPlaceHolderAdapter
+     * @Note   viewHolder
+     */
+    class PlaceHolder constructor(view : View) : RecyclerView.ViewHolder(view)
+
+
+    interface HolderCallBack{
+
+        fun bindView(holder: RecyclerView.ViewHolder)
+
+        fun layoutHelperProvider():LayoutHelper
+
+        fun viewHolderProvider(parent: ViewGroup):RecyclerView.ViewHolder
+    }
+}

+ 302 - 0
common/src/main/code/com/enation/javashop/android/lib/base/BaseActivity.kt

@@ -0,0 +1,302 @@
+package com.enation.javashop.android.lib.base
+
+import android.content.Context
+import android.content.Intent
+import android.databinding.DataBindingUtil
+import android.databinding.ViewDataBinding
+import android.os.Bundle
+import android.view.View
+import android.view.inputmethod.InputMethodManager
+import com.enation.javashop.android.jrouter.JRouter
+import com.enation.javashop.android.lib.R
+import com.enation.javashop.android.lib.utils.debugLog
+import com.enation.javashop.android.lib.utils.errorLog
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import com.enation.javashop.utils.base.tool.CommonTool
+import com.enation.javashop.utils.base.widget.LoadingDialog
+import kotlinx.android.synthetic.main.custom_loading.view.*
+import java.lang.reflect.Field
+import javax.inject.Inject
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午9:26
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   Activity基类
+ */
+abstract class BaseActivity<PresenterType : BaseContract.BasePresenter, DataBindingType : ViewDataBinding> : BaseToolActivity(),BaseControl {
+
+    /**
+     * @Name  presenter
+     * @Type  T : BaseContract.BasePresenter
+     * @Note  Activity中Presenter Dagger自动注入
+     */
+    @Inject
+    protected lateinit var presenter: PresenterType
+
+    /**
+     * @Name  presenter
+     * @Type  T2 : ViewDataBinding
+     * @Note  DataBinding对象
+     */
+    protected lateinit var mViewBinding: DataBindingType
+
+    /**
+     * @Name  lifecycleCalls
+     * @Type  ArrayList<((state :Int) ->Unit)>
+     * @Note  回调集合
+     */
+    private val lifecycleCalls by lazy { ArrayList<((state :Int) ->Unit)>() }
+
+    /**
+     * @Name  disposableManager
+     * @Type  DisposableManager
+     * @Note  Rx索引管理
+     */
+    protected val disposableManager by lazy { DisposableManager() }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:30
+     * @Note   Activity创建时进行相关的配置
+     */
+    override fun onCreate(savedInstanceState: Bundle?) {
+        try {
+            JRouter.prepare().inject(this)
+        }catch (e :Exception){
+            debugLog("Init","首页初始化完毕")
+        }
+        /**父类初始化*/
+        super.onCreate(savedInstanceState)
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_CREATE)
+        /**创建根视图*/
+        val rootView = layoutInflater.inflate(getLayId(), null, false)
+        /**初始化Databinding对象*/
+        mViewBinding = DataBindingUtil.bind(rootView)
+        /**设置根视图到Activity*/
+        setContentView(rootView)
+        /**执行抽象方法初始化Dagger相应操作*/
+        bindDagger()
+        /**Presenter绑定View*/
+        attachView()
+        /**执行初始化操作*/
+        init()
+        /**执行绑定event操作*/
+        bindEvent()
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:46
+     * @Note   执行生命周期监听 恢复
+     */
+    override fun onResume() {
+        super.onResume()
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_RESUME)
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:46
+     * @Note   执行生命周期监听 暂停
+     */
+    override fun onPause() {
+        super.onPause()
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_PAUSE)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:34
+     * @Note   Activity销毁回调
+     */
+    override fun onDestroy() {
+        super.onDestroy()
+        /**Presenter解除绑定*/
+        detachView()
+        /**DataBinding解除绑定*/
+        mViewBinding.unbind()
+        /**执行抽象方法destory()*/
+        destory()
+        /**解除RX引用*/
+        disposableManager.unDisposable()
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_DESTORY)
+        /**清除声明周期监听引用*/
+        removeAllCallBack()
+        /**处理android4.4.2 底层内存泄漏*/
+        fixInputMethodManagerLeak(activity)
+        errorLog("PageDestory","页面销毁======>$localClassName")
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:39
+     * @Note   获取Activity_LayoutId
+     */
+    protected abstract fun getLayId(): Int
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:44
+     * @Note   执行绑定Dagger操作
+     */
+    protected abstract fun bindDagger()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:45
+     * @Note   执行初始化操作
+     */
+    protected abstract fun init()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:45
+     * @Note   执行绑定事件操作
+     */
+    protected abstract fun bindEvent()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:46
+     * @Note   执行销毁相关操作
+     */
+    protected abstract fun destory()
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/1/19 下午6:03
+     * @Note   绑定View接口
+     */
+    protected open fun attachView() {
+       presenter.attachView(this )
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/5/10 下午3:17
+     * @Note   解绑View接口
+     */
+    protected open fun detachView(){
+        presenter.detachView()
+    }
+
+
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:37
+     * @Note   添加callBack
+     * @param  listener 监听回调
+     */
+    override fun addLifeCycleListener(listener: (state: Int) -> Unit) {
+        lifecycleCalls.add(listener)
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:43
+     * @Note   清除生命周期监听
+     */
+    private fun removeAllCallBack(){
+        lifecycleCalls.clear()
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:44
+     * @Note   在各个生命周期监听执行
+     * @param  state 生命周期状态
+     */
+    private fun lifeCycleDo(state :Int){
+        lifecycleCalls.forEach {
+            item ->
+            item.invoke(state)
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/5/27 下午1:22
+     * @Note   页面返回数据
+     * @param  resultCode 返回码
+     * @param  data       数据
+     */
+    open fun resultHandle(resultCode: Int,data: Intent?){
+
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/5/27 下午1:22
+     * @Note   页面返回数据回调
+     */
+    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+        super.onActivityResult(requestCode, resultCode, data)
+        resultHandle(resultCode,data)
+    }
+
+//    /**
+//     * 修改默认加载Dialog
+//     */
+//    override fun loadingDialogProvider(): LoadingDialog {
+//        return CommonTool.createLoadingDialog(this, R.layout.custom_loading,R.id.loadding_image)
+//    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:50
+     * @Note   处理4.4.2 Android底层内存泄漏
+     * @param  destContext 上下文
+     */
+    private fun fixInputMethodManagerLeak(destContext: Context?) {
+        if (destContext == null) {
+            return
+        }
+        val imm = destContext!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager ?: return
+        val arr = arrayOf("mCurRootView", "mServedView", "mNextServedView")
+        var f: Field?
+        var obj_get: Any?
+        arr.indices
+                .asSequence()
+                .map { arr[it] }
+                .forEach {
+                    try {
+                        f = imm.javaClass.getDeclaredField(it)
+                        if (f!!.isAccessible === false) {
+                            f!!.isAccessible = true
+                        }
+                        obj_get = f!!.get(imm)
+                        if (obj_get != null && obj_get is View) {
+                            val v_get = obj_get as View?
+                            if (v_get!!.getContext() === destContext) { // 被InputMethodManager持有引用的context是想要目标销毁的
+                                f!!.set(imm, null) // 置空,破坏掉path to gc节点
+                            }
+                        }
+                    } catch (t: Throwable) {
+                        t.printStackTrace()
+                    }
+                }
+    }
+}

+ 99 - 0
common/src/main/code/com/enation/javashop/android/lib/base/BaseApplication.kt

@@ -0,0 +1,99 @@
+package com.enation.javashop.android.lib.base
+
+import android.annotation.SuppressLint
+import android.app.Application
+import android.content.Context
+import android.content.Intent
+import android.support.multidex.MultiDexApplication
+import com.enation.javashop.android.lib.core.framework.Framework
+import com.enation.javashop.android.lib.core.hack.AndroidHack
+import com.enation.javashop.android.lib.core.runtime.ClassNotFoundInterceptor
+import com.enation.javashop.android.lib.utils.AppTool
+import com.enation.javashop.utils.logger.LoggerFactory
+import com.uuzuche.lib_zxing.activity.ZXingLibrary
+
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午9:51
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   Application基类
+ */
+open class BaseApplication : MultiDexApplication() {
+
+    /**
+     * 伴生对象
+     */
+    companion object {
+
+        /**
+         * @Name  appContext
+         * @Type  android.support.multidex.MultiDexApplication()
+         * @Note  应用Application对象(单例)
+         */
+        @SuppressLint("StaticFieldLeak")
+        lateinit var appContext: Application
+
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseApplication
+     * @Data   2017/12/26 上午10:06
+     * @Note   Application创建时调用
+     * @param  ...
+     */
+    override fun onCreate() {
+        super.onCreate()
+        closeAndroidPDialog()
+        AppTool.SystemUI.initStatusBarHeight(applicationContext)
+        /**Logger初始化*/
+        LoggerFactory.create(baseContext)
+                     .diskCache()
+                     .setTag("JavaShopLog")
+                     .build()
+        /**初始化Application对象*/
+        appContext = this
+        /**开始Activity生命周期监听,并启动AutoClearHelper*/
+        Framework.initActivityLifeController(this)
+        /**注入ClassNotFound异常拦截处理器*/
+        Framework.classNotFoundInterceptor = object : ClassNotFoundInterceptor {
+            override fun call(context: Context, intent: Intent?): Intent? {
+
+                return intent
+            }
+        }
+        /**对Instrumentation进行Hook替换成自定义Instrumentation*/
+        AndroidHack.hookInstrumentation()
+
+        /** 初始化Zxing */
+        ZXingLibrary.initDisplayOpinion(this)
+
+    }
+
+
+    private fun closeAndroidPDialog() {
+        try {
+            val aClass = Class.forName("android.content.pm.PackageParser\$Package")
+            val declaredConstructor = aClass.getDeclaredConstructor(String::class.java)
+            declaredConstructor.isAccessible = true
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+
+        try {
+            val cls = Class.forName("android.app.ActivityThread")
+            val declaredMethod = cls.getDeclaredMethod("currentActivityThread")
+            declaredMethod.isAccessible = true
+            val activityThread = declaredMethod.invoke(null)
+            val mHiddenApiWarningShown = cls.getDeclaredField("mHiddenApiWarningShown")
+            mHiddenApiWarningShown.isAccessible = true
+            mHiddenApiWarningShown.setBoolean(activityThread, true)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+
+    }
+
+
+}

+ 84 - 0
common/src/main/code/com/enation/javashop/android/lib/base/BaseContract.kt

@@ -0,0 +1,84 @@
+package com.enation.javashop.android.lib.base
+
+import com.enation.javashop.net.engine.model.NetState
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午10:08
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   基础Mvp控制接口
+ */
+interface BaseContract {
+
+    /**
+     * @author  LDD
+     * @Data   2017/12/26 上午10:08
+     * @From   com.enation.javashop.android.lib.base.BaseContract
+     * @Note   基础Presenter接口
+     */
+    interface BasePresenter {
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.base.BaseContract.BasePresenter
+         * @Data   2017/12/26 上午10:23
+         * @Note   绑定View
+         * @param  view View
+         * @param  api  Api
+         */
+        fun attachView(view: Any)
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.base.BaseContract.BasePresenter
+         * @Data   2017/12/26 上午10:25
+         * @Note   销毁操作
+         */
+        fun detachView()
+    }
+
+    /**
+     * @author  LDD
+     * @Data   2017/12/26 上午10:26
+     * @From   com.enation.javashop.android.lib.base.BaseContract
+     * @Note   View控制类基类
+     */
+    interface BaseView {
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.base.BaseContract.BaseView
+         * @Data   2017/12/26 上午10:27
+         * @Note   展示错误信息
+         * @param  message 错误信息
+         */
+        fun onError(message: String, type :Int = -1)
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.base.BaseContract.BaseView
+         * @Data   2017/12/26 上午10:28
+         * @Note   网络请求完成
+         * @param  message  提示信息
+         */
+        fun complete(message: String = "", type :Int = -1)
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.base.BaseContract.BaseView
+         * @Data   2017/12/26 上午11:00
+         * @Note   网络请求开始
+         */
+        fun start()
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.base.BaseContract.BaseView
+         * @Data   2017/12/26 上午11:01
+         * @Note   网络监听
+         * @param  state 网络状态
+         */
+        fun networkMonitor(state: NetState)
+
+    }
+}

+ 32 - 0
common/src/main/code/com/enation/javashop/android/lib/base/BaseControl.kt

@@ -0,0 +1,32 @@
+package com.enation.javashop.android.lib.base
+
+/**
+ * @author LDD
+ * @Date   2018/3/29 上午11:32
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   基础控制器
+ */
+interface BaseControl {
+
+    /**
+     * @author LDD
+     * @From   BaseControl
+     * @Date   2018/3/29 上午11:33
+     * @Note   添加生命周期监听
+     * @param  listener 监听
+     */
+    fun addLifeCycleListener(listener :((state :Int) ->Unit))
+
+}
+
+/**创建*/
+const val LIFE_CYCLE_CREATE = 1
+
+/**恢复*/
+const val LIFE_CYCLE_RESUME = 2
+
+/**暂停*/
+const val LIFE_CYCLE_PAUSE = 3
+
+/**销毁*/
+const val LIFE_CYCLE_DESTORY = 4

+ 274 - 0
common/src/main/code/com/enation/javashop/android/lib/base/BaseFragment.kt

@@ -0,0 +1,274 @@
+package com.enation.javashop.android.lib.base
+
+import android.databinding.DataBindingUtil
+import android.databinding.ViewDataBinding
+import android.os.Bundle
+import android.support.v4.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.enation.javashop.android.lib.utils.errorLog
+import com.enation.javashop.utils.base.tool.BaseInterface
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import javax.inject.Inject
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午11:26
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   Fragment基类
+ */
+  abstract class BaseFragment<PresenterType : BaseContract.BasePresenter, DataBindingType : ViewDataBinding> : Fragment(),BaseControl {
+
+    /**
+     * @Name  layout
+     * @Type  android.view.View
+     * @Note  View根视图
+     */
+    private var layout: View? = null
+
+    /**
+     * @Name  activity
+     * @Type  com.enation.javashop.android.lib.base.BaseActivity
+     * @Note  Fragment宿主Activity
+     */
+    protected lateinit var activity: BaseToolActivity
+
+    /**
+     * @Name  mViewDataBinding
+     * @Type  T2 : ViewDataBinding
+     * @Note  DataBinding对象
+     */
+    protected lateinit var mViewDataBinding: DataBindingType
+
+    /**
+     * @Name  lifecycleCalls
+     * @Type  ArrayList<((state :Int) ->Unit)>
+     * @Note  回调集合
+     */
+    private val lifecycleCalls by lazy { ArrayList<((state :Int) ->Unit)>() }
+
+    /**
+     * @Name  presenter
+     * @Type  T : BaseContract.BasePresenter
+     * @Note  Fargment的Presenter Dagger自动注入
+     */
+    @Inject
+    protected lateinit var presenter: PresenterType
+
+    /**
+     * @Name  disposableManager
+     * @Type  DisposableManager
+     * @Note  Rx索引管理
+     */
+    protected val disposableManager by lazy { DisposableManager() }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:38
+     * @Note   Fragment创建时调用
+     */
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        /**初始化根视图及DataBinding*/
+        if (layout == null) {
+            layout = inflater.inflate(getLayId(), null)
+            mViewDataBinding = DataBindingUtil.bind(layout)
+        }
+
+        /**初始化宿主Activity*/
+        activity = getActivity() as BaseToolActivity
+        return layout
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:43
+     * @Note   在Fragment视图创建完毕后调用
+     */
+    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_CREATE)
+
+        /**绑定Dagger*/
+        bindDagger()
+
+        /**绑定视图*/
+        attachView()
+
+        /**执行其他初始化操作*/
+        init()
+
+        /**初始化响应事件*/
+        bindEvent()
+
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:46
+     * @Note   执行生命周期监听 恢复
+     */
+    override fun onResume() {
+        super.onResume()
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_RESUME)
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:46
+     * @Note   执行生命周期监听 暂停
+     */
+    override fun onPause() {
+        super.onPause()
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_PAUSE)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:45
+     * @Note   在Fragment销毁时调用
+     */
+    override fun onDestroyView() {
+
+        /**调用父类方法*/
+        super.onDestroyView()
+
+        /**Presenter解除绑定*/
+        detachView()
+
+        /**ViewBinding解除绑定*/
+        mViewDataBinding.unbind()
+
+        /**执行其他销毁操作*/
+        destory()
+
+        /**解除RX引用*/
+        disposableManager.unDisposable()
+
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_DESTORY)
+
+        /**清除生命周期监听引用*/
+        removeAllCallBack()
+
+        errorLog("FragmentDestory","页面销毁======>${javaClass.name}")
+
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:37
+     * @Note   添加callBack
+     * @param  listener 监听回调
+     */
+    override fun addLifeCycleListener(listener: (state: Int) -> Unit) {
+        lifecycleCalls.add(listener)
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:43
+     * @Note   清除生命周期监听
+     */
+    private fun removeAllCallBack(){
+        lifecycleCalls.clear()
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:44
+     * @Note   在各个生命周期监听执行
+     * @param  state 生命周期状态
+     */
+    private fun lifeCycleDo(state :Int){
+        lifecycleCalls.forEach {
+            item ->
+            item.invoke(state)
+        }
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:47
+     * @Note   获取根视图LayoutId
+     * @return LayoutId
+     */
+    protected abstract fun getLayId(): Int
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:47
+     * @Note   绑定Dagger
+     */
+    protected abstract fun bindDagger()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:50
+     * @Note   初始化其他操作
+     */
+    protected abstract fun init()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:50
+     * @Note   绑定事件
+     */
+    protected abstract fun bindEvent()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:50
+     * @Note   其他销毁操作
+     */
+    protected abstract fun destory()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:52
+     * @Note   销毁View操作
+     */
+    protected open fun attachView() {
+        presenter.attachView(this)
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/5/10 下午3:17
+     * @Note   解绑View接口
+     */
+    protected open fun detachView(){
+        presenter.detachView()
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseFragment
+     * @Data   2017/12/26 上午11:57
+     * @Note   获取工具对象
+     * @return 工具对象
+     */
+    protected fun getUtils(): BaseInterface {
+
+        return activity
+    }
+}

+ 41 - 0
common/src/main/code/com/enation/javashop/android/lib/base/BaseLaunch.kt

@@ -0,0 +1,41 @@
+package com.enation.javashop.android.lib.base
+
+import android.content.Context
+import com.enation.javashop.android.jrouter.logic.template.BaseProvider
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午11:59
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   模块初始化类
+ */
+abstract class BaseLaunch :BaseProvider {
+
+    /**
+     * @Name  context
+     * @Type  android.content.Context
+     * @Note  上下文
+     */
+    protected var context :Context? = null
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseLaunch
+     * @Data   2017/12/26 下午12:02
+     * @Note   执行初始化操作
+     * @param  context 上下文
+     */
+    override fun init(context: Context) {
+        this.context = context
+        moduleInit()
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseLaunch
+     * @Data   2017/12/26 下午12:03
+     * @Note   子类初始化操作
+     */
+    abstract fun moduleInit()
+
+}

+ 49 - 0
common/src/main/code/com/enation/javashop/android/lib/base/DisposableManager.kt

@@ -0,0 +1,49 @@
+package com.enation.javashop.android.lib.base
+
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.disposables.Disposable
+
+/**
+ * @author LDD
+ * @Date   2018/4/11 下午4:33
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   RX引用管理器
+ */
+open class DisposableManager {
+
+    /**
+     * @Name  compositeDisposable
+     * @Type  io.reactivex.disposables.CompositeDisposable
+     * @Note  Disposable管理器
+     */
+    protected var compositeDisposable: CompositeDisposable? = null
+
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.DisposableManager
+     * @Data   2017/12/26 下午12:28
+     * @Note   移除监听
+     */
+    fun unDisposable() {
+        if (compositeDisposable != null) {
+            compositeDisposable!!.dispose()
+        }
+
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.DisposableManager
+     * @Data   2017/12/26 下午12:29
+     * @Note   添加Disposable
+     * @param  disposable 监听引用
+     */
+    fun addDisposable(disposable: Disposable) {
+        if (compositeDisposable == null) {
+            compositeDisposable = CompositeDisposable()
+        }
+        compositeDisposable!!.add(disposable)
+    }
+
+}

+ 384 - 0
common/src/main/code/com/enation/javashop/android/lib/base/GalleryActivity.kt

@@ -0,0 +1,384 @@
+package com.enation.javashop.android.lib.base
+
+import android.content.Context
+import android.content.Intent
+import android.databinding.DataBindingUtil
+import android.databinding.ViewDataBinding
+import android.os.Bundle
+import android.view.View
+import android.view.inputmethod.InputMethodManager
+import com.enation.javashop.android.jrouter.JRouter
+import com.enation.javashop.android.lib.utils.debugLog
+import com.enation.javashop.photoutils.app.TakePhoto
+import com.enation.javashop.photoutils.app.TakePhotoImpl
+import com.enation.javashop.photoutils.model.InvokeParam
+import com.enation.javashop.photoutils.model.TContextWrap
+import com.enation.javashop.photoutils.model.TResult
+import com.enation.javashop.photoutils.permission.InvokeListener
+import com.enation.javashop.photoutils.permission.PermissionManager
+import com.enation.javashop.photoutils.permission.TakePhotoInvocationHandler
+import com.enation.javashop.photoutils.uitl.TakePhotoinf
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import java.lang.reflect.Field
+import javax.inject.Inject
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 下午12:07
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   带有相册功能的Activity基类
+ */
+ abstract class GalleryActivity<PresenterType : BaseContract.BasePresenter, DataBindingType : ViewDataBinding>: BaseToolActivity(),BaseControl , TakePhoto.TakeResultListener, InvokeListener, TakePhotoinf {
+
+
+    /**
+     * @Name  takePhoto
+     * @Type  com.enation.javashop.photoutils.app.TakePhoto
+     * @Note  TakePhoto对象
+     */
+    private  var takePhoto : TakePhoto? = null
+
+    /**
+     * @Name  invokeparam
+     * @Type  com.enation.javashop.photoutils.model.InvokeParam
+     * @Note  invokeparam
+     */
+    private  var invokeparam: InvokeParam? = null
+
+    /**
+     * @Name  presenter
+     * @Type  T : BaseContract.BasePresenter
+     * @Note  Activity中Presenter Dagger自动注入
+     */
+    @Inject
+    protected lateinit var presenter: PresenterType
+
+    /**
+     * @Name  presenter
+     * @Type  T2 : ViewDataBinding
+     * @Note  DataBinding对象
+     */
+    protected lateinit var mViewBinding: DataBindingType
+
+    /**
+     * @Name  lifecycleCalls
+     * @Type  ArrayList<((state :Int) ->Unit)>
+     * @Note  回调集合
+     */
+    private val lifecycleCalls by lazy { ArrayList<((state :Int) ->Unit)>() }
+
+    /**
+     * @Name  disposableManager
+     * @Type  DisposableManager
+     * @Note  Rx索引管理
+     */
+    protected val disposableManager by lazy { DisposableManager() }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:30
+     * @Note   Activity创建时进行相关的配置
+     */
+    override fun onCreate(savedInstanceState: Bundle?) {
+        getTakePhoto()!!.onCreate(savedInstanceState)
+        try {
+            JRouter.prepare().inject(this)
+        }catch (e :Exception){
+            debugLog("Init","首页初始化完毕")
+        }
+        /**父类初始化*/
+        super.onCreate(savedInstanceState)
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_CREATE)
+        /**创建根视图*/
+        val rootView = layoutInflater.inflate(getLayId(), null, false)
+        /**初始化Databinding对象*/
+        mViewBinding = DataBindingUtil.bind(rootView)
+        /**设置根视图到Activity*/
+        setContentView(rootView)
+        /**执行抽象方法初始化Dagger相应操作*/
+        bindDagger()
+        /**Presenter绑定View*/
+        attachView()
+        /**执行初始化操作*/
+        init()
+        /**执行绑定event操作*/
+        bindEvent()
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:46
+     * @Note   执行生命周期监听 恢复
+     */
+    override fun onResume() {
+        super.onResume()
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_RESUME)
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:46
+     * @Note   执行生命周期监听 暂停
+     */
+    override fun onPause() {
+        super.onPause()
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_PAUSE)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:34
+     * @Note   Activity销毁回调
+     */
+    override fun onDestroy() {
+        super.onDestroy()
+        /**初始化相机*/
+        takePhoto = null
+        /**Presenter解除绑定*/
+        detachView()
+        /**DataBinding解除绑定*/
+        mViewBinding.unbind()
+        /**执行抽象方法destory()*/
+        destory()
+        /**解除RX引用*/
+        disposableManager.unDisposable()
+        /**执行生命周期监听*/
+        lifeCycleDo(LIFE_CYCLE_DESTORY)
+        /**清除声明周期监听引用*/
+        removeAllCallBack()
+        /**处理android4.4.2 底层内存泄漏*/
+        fixInputMethodManagerLeak(activity)
+        debugLog("PageDestory","页面销毁======>$localClassName")
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:39
+     * @Note   获取Activity_LayoutId
+     */
+    protected abstract fun getLayId(): Int
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:44
+     * @Note   执行绑定Dagger操作
+     */
+    protected abstract fun bindDagger()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:45
+     * @Note   执行初始化操作
+     */
+    protected abstract fun init()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:45
+     * @Note   执行绑定事件操作
+     */
+    protected abstract fun bindEvent()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:46
+     * @Note   执行销毁相关操作
+     */
+    protected abstract fun destory()
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/1/19 下午6:03
+     * @Note   绑定View接口
+     */
+    protected open fun attachView() {
+        presenter.attachView(this )
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/5/10 下午3:17
+     * @Note   解绑View接口
+     */
+    protected open fun detachView(){
+        presenter.detachView()
+    }
+
+
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:37
+     * @Note   添加callBack
+     * @param  listener 监听回调
+     */
+    override fun addLifeCycleListener(listener: (state: Int) -> Unit) {
+        lifecycleCalls.add(listener)
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:43
+     * @Note   清除生命周期监听
+     */
+    private fun removeAllCallBack(){
+        lifecycleCalls.clear()
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/3/29 上午11:44
+     * @Note   在各个生命周期监听执行
+     * @param  state 生命周期状态
+     */
+    private fun lifeCycleDo(state :Int){
+        lifecycleCalls.forEach {
+            item ->
+            item.invoke(state)
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/5/27 下午1:22
+     * @Note   页面返回数据
+     * @param  resultCode 返回码
+     * @param  data       数据
+     */
+    open fun resultHandle(resultCode: Int,data: Intent?){
+
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseActivity
+     * @Date   2018/5/27 下午1:22
+     * @Note   页面返回数据回调
+     */
+    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+        super.onActivityResult(requestCode, resultCode, data)
+        getTakePhoto()!!.onActivityResult(requestCode, resultCode, data)
+        resultHandle(resultCode,data)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.BaseActivity
+     * @Data   2017/12/26 上午9:50
+     * @Note   处理4.4.2 Android底层内存泄漏
+     * @param  destContext 上下文
+     */
+    private fun fixInputMethodManagerLeak(destContext: Context?) {
+        if (destContext == null) {
+            return
+        }
+        val imm = destContext.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+                ?: return
+        val arr = arrayOf("mCurRootView", "mServedView", "mNextServedView")
+        var f: Field?
+        var obj_get: Any?
+        arr.indices
+                .asSequence()
+                .map { arr[it] }
+                .forEach {
+                    try {
+                        f = imm.javaClass.getDeclaredField(it)
+                        if (!f!!.isAccessible) {
+                            f!!.isAccessible = true
+                        }
+                        obj_get = f!!.get(imm)
+                        if (obj_get != null && obj_get is View) {
+                            val v_get = obj_get as View?
+                            if (v_get!!.context === destContext) { // 被InputMethodManager持有引用的context是想要目标销毁的
+                                f!!.set(imm, null) // 置空,破坏掉path to gc节点
+                            }
+                        }
+                    } catch (t: Throwable) {
+                        t.printStackTrace()
+                    }
+                }
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryActivity
+     * @Data   2017/12/26 下午12:12
+     * @Note   保存参数,防止丢失
+     */
+    override fun onSaveInstanceState(outState: Bundle?) {
+        getTakePhoto()!!.onSaveInstanceState(outState)
+        super.onSaveInstanceState(outState)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryActivity
+     * @Data   2017/12/26 下午12:12
+     * @Note   获取相机返回数据
+     */
+    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+        val type = PermissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults)
+        PermissionManager.handlePermissionsResult(this, type, invokeparam, this)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryActivity
+     * @Data   2017/12/26 下午12:15
+     * @Note   鉴权
+     */
+    override fun invoke(invokeParam: InvokeParam?): PermissionManager.TPermissionType {
+        val type = PermissionManager.checkPermission(TContextWrap.of(this), invokeParam!!.getMethod())
+        if (PermissionManager.TPermissionType.WAIT == type) {
+            this.invokeparam = invokeParam
+        }
+        return type
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryActivity
+     * @Data   2017/12/26 下午12:15
+     * @Note   获取TakePhoto实例
+     */
+    override fun getTakePhoto(): TakePhoto? {
+        if (takePhoto == null) {
+            takePhoto = TakePhotoInvocationHandler.of(this).bind(TakePhotoImpl(this, this)) as TakePhoto
+        }
+        return takePhoto
+    }
+
+    /**
+     * 实现获取照片成功接口 子类自由复写
+     */
+    override fun takeSuccess(result: TResult) {}
+
+    /**
+     * 实现获取照片取消接口 子类自由复写
+     */
+    override fun takeCancel() {}
+
+    /**
+     * 实现获取照片失败接口 子类自由复写
+     */
+    override fun takeFail(result: TResult?, msg: String?) {}
+}

+ 136 - 0
common/src/main/code/com/enation/javashop/android/lib/base/GalleryFragment.kt

@@ -0,0 +1,136 @@
+package com.enation.javashop.android.lib.base
+
+import android.content.Intent
+import android.databinding.ViewDataBinding
+import android.os.Bundle
+import com.enation.javashop.photoutils.app.TakePhoto
+import com.enation.javashop.photoutils.app.TakePhotoImpl
+import com.enation.javashop.photoutils.model.InvokeParam
+import com.enation.javashop.photoutils.model.TContextWrap
+import com.enation.javashop.photoutils.model.TResult
+import com.enation.javashop.photoutils.permission.InvokeListener
+import com.enation.javashop.photoutils.permission.PermissionManager
+import com.enation.javashop.photoutils.permission.TakePhotoInvocationHandler
+import com.enation.javashop.photoutils.uitl.TakePhotoinf
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 下午12:07
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   带有相册功能的Fragment基类
+ */
+ abstract class GalleryFragment<PresenterType : BaseContract.BasePresenter, DataBindingType : ViewDataBinding> : BaseFragment<PresenterType,DataBindingType>(), TakePhoto.TakeResultListener, InvokeListener, TakePhotoinf {
+
+    /**
+     * @Name  takePhoto
+     * @Type  com.enation.javashop.photoutils.app.TakePhoto
+     * @Note  TakePhoto对象
+     */
+    private  var takePhoto : TakePhoto? = null
+
+    /**
+     * @Name  invokeparam
+     * @Type  com.enation.javashop.photoutils.model.InvokeParam
+     * @Note  invokeparam
+     */
+    private  var invokeparam: InvokeParam? = null
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryFragment
+     * @Data   2017/12/26 下午12:09
+     * @Note   Activity创建时调用 相册对象注册初始化生命周期
+     */
+    override fun onCreate(savedInstanceState: Bundle?) {
+        getTakePhoto()!!.onCreate(savedInstanceState)
+        super.onCreate(savedInstanceState)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryFragment
+     * @Data   2017/12/26 下午12:12
+     * @Note   保存参数,防止丢失
+     */
+    override fun onSaveInstanceState(outState: Bundle?) {
+        getTakePhoto()!!.onSaveInstanceState(outState)
+        super.onSaveInstanceState(outState)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryFragment
+     * @Data   2017/12/26 下午12:12
+     * @Note   获取相机返回数据
+     */
+    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+        getTakePhoto()!!.onActivityResult(requestCode, resultCode, data)
+        super.onActivityResult(requestCode, resultCode, data)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryFragment
+     * @Data   2017/12/26 下午12:12
+     * @Note   获取相机返回数据
+     */
+    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+        val type = PermissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults)
+        PermissionManager.handlePermissionsResult(getActivity(), type, invokeparam, this)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryFragment
+     * @Data   2017/12/26 下午12:13
+     * @Note   Activity销毁时调用
+     */
+    override fun onDestroyView() {
+        takePhoto=null
+        super.onDestroyView()
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryFragment
+     * @Data   2017/12/26 下午12:15
+     * @Note   获取TakePhoto实例
+     */
+    override fun getTakePhoto(): TakePhoto? {
+        if (takePhoto == null) {
+            takePhoto = TakePhotoInvocationHandler.of(this).bind(TakePhotoImpl(this, this)) as TakePhoto
+        }
+        return takePhoto
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.GalleryFragment
+     * @Data   2017/12/26 下午12:15
+     * @Note   鉴权
+     */
+    override fun invoke(invokeParam: InvokeParam?): PermissionManager.TPermissionType {
+        val type = PermissionManager.checkPermission(TContextWrap.of(this), invokeParam!!.getMethod())
+        if (PermissionManager.TPermissionType.WAIT == type) {
+            this.invokeparam = invokeParam!!
+        }
+        return type
+    }
+
+
+    /**
+     * 实现获取照片成功接口 子类自由复写
+     */
+    override fun takeSuccess(result: TResult?) {}
+
+    /**
+     * 实现获取照片取消接口 子类自由复写
+     */
+    override fun takeCancel() {}
+
+    /**
+     * 实现获取照片失败接口 子类自由复写
+     */
+    override fun takeFail(result: TResult?, msg: String?) {}
+}

+ 81 - 0
common/src/main/code/com/enation/javashop/android/lib/base/RxPresenter.kt

@@ -0,0 +1,81 @@
+package com.enation.javashop.android.lib.base
+
+import com.enation.javashop.android.lib.utils.errorLog
+import com.enation.javashop.android.lib.utils.getEventCenter
+import com.enation.javashop.android.lib.utils.to
+import com.enation.javashop.android.lib.vo.NetStateEvent
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.disposables.Disposable
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 下午12:22
+ * @From   com.enation.javashop.android.lib.base
+ * @Note   Presenter基类
+ */
+abstract class RxPresenter<out ViewType : BaseContract.BaseView> : DisposableManager() , BaseContract.BasePresenter {
+
+     /**
+      * @Name  mView
+      * @Type  T : BaseContract.BaseView
+      * @Note  View接口
+      */
+     private var mView: ViewType? = null
+
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.RxPresenter
+     * @Data   2017/12/26 下午12:31
+     * @Note   注入View接口和API 注册网络状态Event
+     * @param  view View接口
+     * @param  api  API
+     */
+    override fun attachView(view: Any) {
+        bindDagger()
+        /**注入View接口*/
+        try {
+            this.mView = view.to()
+        }catch (e :Exception){
+            errorLog("Interface Not Implement","Fragment/Activity 没有实现对应BaseView接口")
+            throw java.lang.Exception("Interface Not Implement : Fragment/Activity 没有实现对应BaseView接口")
+        }
+        /**注册网络状态事件*/
+        var disposable = getEventCenter().register(NetStateEvent::class.java) {
+            result ->
+            this.mView!!.networkMonitor(result.state)
+        }
+        addDisposable(disposable)
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.base.RxPresenter
+     * @Data   2017/12/26 下午12:35
+     * @Note   销毁操作
+     */
+    override fun detachView() {
+        this.mView = null
+        unDisposable()
+    }
+
+    /**
+     * @author LDD
+     * @Date   2018/1/19 下午6:16
+     * @From   com.enation.javashop.android.lib.base.RxPresenter
+     * @Note   依赖注入初始化
+     */
+    abstract fun bindDagger()
+
+    /**
+     * @author LDD
+     * @From   RxPresenter
+     * @Date   2018/1/19 下午6:16
+     * @Note   View接口提供者
+     * @return View接口
+     */
+    fun providerView():ViewType{
+        return mView!!
+    }
+
+}

+ 103 - 0
common/src/main/code/com/enation/javashop/android/lib/bind/BaseBindingHelper.kt

@@ -0,0 +1,103 @@
+package com.enation.javashop.android.lib.bind
+
+import android.databinding.BindingAdapter
+import android.os.Build
+import android.support.constraint.ConstraintLayout
+import android.text.SpannableStringBuilder
+import android.text.Spanned
+import android.text.style.AbsoluteSizeSpan
+import android.util.TypedValue
+import android.view.View
+import android.widget.ImageView
+import android.widget.TextView
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.enation.javashop.android.lib.base.BaseApplication
+import com.enation.javashop.android.lib.utils.errorLog
+import com.enation.javashop.android.lib.utils.getColorCompatible
+import com.enation.javashop.android.lib.utils.then
+import com.enation.javashop.imagepluin.R
+import com.enation.javashop.utils.base.tool.ScreenTool
+
+/**
+ * @author LDD
+ * @Date   2018/1/19 下午3:20
+ * @From   com.enation.javashop.android.lib.bind
+ * @Note   databinding辅助类
+ */
+object BaseBindingHelper {
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.binding.BindingHelper
+     * @Data   2017/12/26 上午9:23
+     * @Note   加载图片
+     * @param  imageView 需要加载图片的ImageView
+     * @param  url       图片Url
+     */
+    @BindingAdapter(value = "bind:url",requireAll = false)
+    @JvmStatic fun loadImage(imageView: ImageView?, url: String?) {
+        if(imageView == null || url == null ||url == ""){
+            return
+        }
+        Glide.with(imageView.context).load(url).thumbnail(0.1f).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.image_loading).error(R.drawable.image_error).into(imageView)
+    }
+
+    @BindingAdapter(value = "bind:url_without_holder",requireAll = false)
+    @JvmStatic fun loadImageWithoutHoldlder(imageView: ImageView?, url: String?) {
+        if(imageView == null || url == null ||url == ""){
+            return
+        }
+        Glide.with(imageView.context).load(url).thumbnail(0.1f).diskCacheStrategy(DiskCacheStrategy.ALL).error(R.drawable.image_error).into(imageView)
+    }
+    /**
+     * @author LDD
+     * @From   BaseBindingHelper
+     * @Date   2018/2/24 下午2:22
+     * @Note   显示价格大小
+     * @param  value 价格
+     */
+    @BindingAdapter(value = "bind:price_text", requireAll = false)
+    @JvmStatic
+    fun setPriceText(view: TextView, value: Double) {
+        view.text = SpannableStringBuilder("¥$value").then { self ->
+            self.setSpan(AbsoluteSizeSpan(ScreenTool.dip2px(view.context, 12f)), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
+            self.setSpan(AbsoluteSizeSpan(ScreenTool.dip2px(view.context, 15f)), 1, self.indexOf("."), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
+            self.setSpan(AbsoluteSizeSpan(ScreenTool.dip2px(view.context, 12f)), self.indexOf("."), self.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
+        }
+    }
+    /**
+     * @author LDD
+     * @From   HomeFragmentBindHelper
+     * @Date   2018/1/30 下午3:05
+     * @Note   透明渐变
+     */
+    @BindingAdapter(value = "bind:alpha",requireAll = false)
+    @JvmStatic fun backgroundGradient(view: ConstraintLayout, value:Int){
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            var alpha = value
+            if (alpha > 255) {
+                alpha = 255
+                if (view.background.alpha == 255) {
+                    return
+                }
+            }
+            view.background.alpha = alpha
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseBindingHelper
+     * @Date   2018/2/28 上午9:34
+     * @Note   解决ConstraintLayout 无法上色
+     */
+    @BindingAdapter(value = "bind:backgroundColor",requireAll = false)
+    @JvmStatic fun setBackgroundColor(view : View, value: Int){
+        view.setBackgroundColor(value)
+    }
+
+    @BindingAdapter(value = "bind:text_count_for_line",requireAll = true)
+    @JvmStatic fun setTextSize(tv :TextView , textCount :Int){
+        tv.setTextSize(TypedValue.COMPLEX_UNIT_PX,ScreenTool.getScreenWidth(BaseApplication.appContext)/textCount)
+    }
+}

+ 97 - 0
common/src/main/code/com/enation/javashop/android/lib/core/framework/ActivityLifeController.kt

@@ -0,0 +1,97 @@
+package com.enation.javashop.android.lib.core.framework
+
+import android.app.Activity
+import android.app.Application
+import android.os.Bundle
+import com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask
+import com.enation.javashop.android.lib.utils.AutoClearHelper
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午7:45
+ * @From   com.enation.javashop.android.lib.core.framework
+ * @Note   Activity生命周期回调
+ */
+class ActivityLifeController :Application.ActivityLifecycleCallbacks {
+
+    /**
+     * @Name  autoClearHelper
+     * @Type  com.enation.javashop.android.lib.utils.AutoClearHelper
+     * @Note  变量清理辅助类
+     */
+    private var isOpenAutoClear = false
+
+    /**
+     * @author  LDD
+     * @From    ActivityLifeController
+     * @Data   2017/12/26 上午7:48
+     * @Note   开启
+     */
+    fun withAutoValueHelper():ActivityLifeController{
+        isOpenAutoClear = true
+        return this
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework ActivityLifeController
+     * @Data   2017/12/26 上午8:22
+     * @Note   Activity处于不显示或者半透明状态
+     * @return Activity
+     */
+    override fun onActivityPaused(p0: Activity?) {
+
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework ActivityLifeController
+     * @Data   2017/12/26 上午8:22
+     * @Note   Activity处于完全显示状态
+     * @return Activity
+     */
+    override fun onActivityResumed(p0: Activity?) {
+
+    }
+
+    override fun onActivityStarted(p0: Activity?) {
+
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework ActivityLifeController
+     * @Data   2017/12/26 上午8:20
+     * @Note   Activity销毁方法
+     * @return 销毁的Activity
+     */
+    override fun onActivityDestroyed(p0: Activity?) {
+        if (p0 != null && isOpenAutoClear) {
+            AutoClearHelper.intance.destory(p0.localClassName)
+        }
+        if (p0 != null) {
+            JavaShopActivityTask.instance.popFromActivityStack(p0)
+        }
+    }
+
+    override fun onActivitySaveInstanceState(p0: Activity?, p1: Bundle?) {
+
+    }
+
+    override fun onActivityStopped(p0: Activity?) {
+
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework ActivityLifeController
+     * @Data   2017/12/26 上午8:25
+     * @Note   Activity创建回调
+     * @param  p0 创建的Activity
+     */
+    override fun onActivityCreated(p0: Activity?, p1: Bundle?) {
+        if (p0 != null) {
+            JavaShopActivityTask.instance.pushToActivityStack(p0)
+        }
+    }
+}

+ 67 - 0
common/src/main/code/com/enation/javashop/android/lib/core/framework/Framework.kt

@@ -0,0 +1,67 @@
+package com.enation.javashop.android.lib.core.framework
+
+import android.app.Application
+import com.enation.javashop.android.lib.core.runtime.ClassNotFoundInterceptor
+import com.enation.javashop.android.lib.core.split.ComponentManager
+import com.enation.javashop.android.lib.core.split.ComponentManagerImpl
+import com.enation.javashop.android.lib.utils.Do
+import java.io.File
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午8:28
+ * @From   com.enation.javashop.android.lib.core.framework
+ * @Note   JavaShop FrameWork层入口
+ */
+ class Framework {
+
+    /**
+     * @author  LDD
+     * @Data   2017/12/26 上午8:29
+     * @From   com.enation.javashop.android.lib.core.framework Framework
+     * @Note   Framework伴生对象
+     */
+    companion object {
+
+        /**
+         * @Name  com.enation.javashop.android.lib.core.framework.Framework.Companion.classNotFoundInterceptor
+         * @Type  com.enation.javashop.android.lib.core.runtime.ClassNotFoundInterceptor
+         * @Note  Class拦截器在Class文件查找失败时执行
+         */
+        var classNotFoundInterceptor : ClassNotFoundInterceptor? = null
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.core.framework.Framework Companion
+         * @Data   2017/12/26 上午8:32
+         * @Note   初始化Activity生命周期监听器
+         * @param  app  应用Application对象
+         */
+        fun initActivityLifeController(app:Application){
+            app.registerActivityLifecycleCallbacks(ActivityLifeController().withAutoValueHelper())
+        }
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.core.framework.Framework Companion
+         * @Data   2017/12/26 上午8:35
+         * @Note   Moudle安装
+         * @param  pakeageName    模块包名
+         * @param  moudleLocation 模块物理路径
+         */
+        fun installMoudle(pakeageName:String, moudleLocation:File){
+            ComponentManager.get().installMoudle(pakeageName,moudleLocation)
+        }
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.core.framework.Framework Companion
+         * @Data   2017/12/26 上午8:36
+         * @Note   Moudle卸载
+         * @param  pakeageName 根据包名进行卸载
+         */
+        fun unstallMoudle(pakeageName:String){
+            ComponentManager.get().unstallMoudle(pakeageName)
+        }
+    }
+}

+ 161 - 0
common/src/main/code/com/enation/javashop/android/lib/core/framework/InstallResourceHelper.kt

@@ -0,0 +1,161 @@
+package com.enation.javashop.android.lib.core.framework
+
+import android.content.Context
+
+
+/**
+ * @author LDD
+ * @Date   2018/1/17 上午10:15
+ * @From   com.enation.javashop.android.middleware.resource
+ * @Note   加载已安装资源
+ */
+class InstallResourceHelper {
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:15
+     * @Note   私有构造方法 防止外部实例化
+     */
+    private constructor()
+
+    /**
+     * @Name  install
+     * @Type  ResourceManager.Installed
+     * @Note  已安装资源
+     */
+    private lateinit var install :ResourceManager.Installed
+
+    /**
+     * @Name  CurrentPackageName
+     * @Type  String
+     * @Note  资源包名
+     */
+    private lateinit var CurrentPackageName : String
+
+    /**
+     * @author LDD
+     * @Date   2018/1/17 上午10:16
+     * @From   InstallResourceHelper
+     * @Note   伴生对象 实现单例
+     */
+    companion object {
+        /**
+         * @Name  com.enation.javashop.android.lib.core.framework.InstallResourceHelper.Companion.instance
+         * @Type  com.enation.javashop.android.lib.core.framework.InstallResourceHelper
+         * @Note  单例对象 懒加载
+         */
+        private val instance by lazy { InstallResourceHelper() }
+
+        /**
+         * @author LDD
+         * @From   Companion
+         * @Date   2018/1/17 上午10:17
+         * @Note   获取单例对象
+         * @return 已安装文件资源
+         */
+        fun get(): InstallResourceHelper {
+            return instance
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:18
+     * @Note   初始化
+     * @param  context 上下文 一般为Application
+     * @param  packageName 需要加在资源的包名
+     */
+    fun initInstalled(context :Context,packageName:String?){
+        CurrentPackageName = if (packageName == null) {context.applicationContext.packageName} else {packageName}
+        ResourceManager.init(context)
+        install = ResourceManager.installed()
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:19
+     * @Note   初始化 该方法一般用于加载本地资源 用于资源获取出错时使用
+     * @param  context 上下文 一般为Application
+     */
+    fun initInstalled(context: Context){
+        initInstalled(context,null)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取mipmap资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getMipmapId(name : String):Int{
+        return install.getResourceID(CurrentPackageName,"mipmap",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取drawble资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getDrawableId(name : String):Int{
+        return install.getResourceID(CurrentPackageName,"drawble",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取color资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getColorId(name : String):Int{
+
+        return install.getResourceID(CurrentPackageName,"color",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取style资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getStyleId(name : String):Int{
+
+        return install.getResourceID(CurrentPackageName,"style",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取string资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getStringId(name : String):Int{
+        return install.getResourceID(CurrentPackageName,"string",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取anim资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getAnimId(name : String):Int{
+        return install.getResourceID(CurrentPackageName,"anim",name)
+    }
+
+}

+ 75 - 0
common/src/main/code/com/enation/javashop/android/lib/core/framework/JavaShopInstrumentationHook.java

@@ -0,0 +1,75 @@
+package com.enation.javashop.android.lib.core.framework;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import java.lang.reflect.Method;
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午8:38
+ * @From   com.enation.javashop.android.lib.core.framework
+ * @Note   Instrumentation 的自定义Hook
+ */
+public class JavaShopInstrumentationHook extends Instrumentation {
+
+    /**
+     * @Name  oldInstrumentation
+     * @Type  android.app.Instrumentation
+     * @Note  系统原始Instrumentation
+     */
+    public Instrumentation oldInstrumentation;
+
+    /**
+     * @Name  EXEC_START_ACTIVITY
+     * @Type  java.lang.String
+     * @Note  execStartActivity方法名 反射时使用
+     */
+    public static final String EXEC_START_ACTIVITY = "execStartActivity";
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework JavaShopInstrumentationHook
+     * @Data   2017/12/26 上午8:43
+     * @Note   构造方法 传入原始 Instrumentation
+     * @param  oldInstrumentation 原始 Instrumentation
+     */
+    public JavaShopInstrumentationHook(Instrumentation oldInstrumentation) {
+        this.oldInstrumentation = oldInstrumentation;
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework
+     * @Data   2017/12/26 上午8:42
+     * @Note   这个方法是由于原始方法里面的Instrumentation有execStartActivity方法来定的
+     */
+    public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
+                                            Intent intent, int requestCode, Bundle options) {
+        Method execStartActivity = null;
+        //由于这个方法是隐藏的,所以需要反射来调用,先找到这方法
+        try {
+            execStartActivity = Instrumentation.class.getDeclaredMethod(
+                    EXEC_START_ACTIVITY,
+                    Context.class, IBinder.class, IBinder.class, Activity.class,
+                    Intent.class, int.class, Bundle.class);
+            //因为该属性为私有 设置权限
+            execStartActivity.setAccessible(true);
+            return (ActivityResult) execStartActivity.invoke(oldInstrumentation, who,
+                    contextThread, token, target, intent, requestCode, options);
+        } catch (Exception e) {
+
+            try {
+                return (ActivityResult) execStartActivity.invoke(oldInstrumentation, who,
+                        contextThread, token, target, Framework.Companion.getClassNotFoundInterceptor().call(target,intent), requestCode, options);
+            } catch (Exception e1) {
+                Log.e("StartActivityError",e1.getMessage());
+                return null;
+            }
+        }
+    }
+}

+ 269 - 0
common/src/main/code/com/enation/javashop/android/lib/core/framework/ResourceManager.java

@@ -0,0 +1,269 @@
+package com.enation.javashop.android.lib.core.framework;
+
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import dalvik.system.DexClassLoader;
+
+public class ResourceManager {
+
+    private static final String TAG = "ResourceManager";
+
+    private ResourceManager() {
+    }
+
+    public static void init(Context context) {
+        UnInstalled.sManager.init(context);
+        Installed.sManager.init(context);
+    }
+
+    public static UnInstalled unInstalled() {
+        return UnInstalled.sManager;
+    }
+
+    public static Installed installed() {
+        return Installed.sManager;
+    }
+
+    /**
+     * 针对于未安装应用
+     */
+    public static class UnInstalled {
+
+        static final UnInstalled sManager = new UnInstalled();
+
+        private Context mContext;
+        private Map<String, LoadedResource> mRescources = new HashMap<String, LoadedResource>();
+        private String mDexDir;
+
+        private UnInstalled() {
+
+        }
+
+        /**
+         * 初始化
+         *
+         * @param context
+         */
+        public void init(Context context) {
+            mContext = context.getApplicationContext();
+            File dexDir = mContext.getDir("dex", Context.MODE_PRIVATE);
+            if (!dexDir.exists()) {
+                dexDir.mkdir();
+            }
+            mDexDir = dexDir.getAbsolutePath();
+        }
+
+        /**
+         * 获取未安装应用资源的ID
+         *
+         * @param packageName
+         * @param fieldName
+         * @return
+         */
+        public int getResourceID(String packageName, String type, String fieldName) {
+            int resID = 0;
+            LoadedResource recource = getUnInstalledRecource(packageName);
+            String rClassName = packageName + ".R$" + type;
+            Log.w(TAG, "resource class:" + rClassName + ",fieldName:" + fieldName);
+            try {
+                Class cls = recource.classLoader.loadClass(rClassName);
+                resID = (Integer) cls.getField(fieldName).get(null);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            return resID;
+        }
+
+        /**
+         * 获取未安装应用Drawable
+         *
+         * @param packageName
+         * @param fieldName
+         * @return
+         */
+        public Drawable getDrawable(String packageName, String fieldName) {
+            Drawable drawable = null;
+            int resourceID = getResourceID(packageName, "drawable", fieldName);
+            LoadedResource recource = getUnInstalledRecource(packageName);
+            if (recource != null) {
+                drawable = recource.resources.getDrawable(resourceID);
+            }
+            return drawable;
+        }
+
+        /**
+         * 加载未安装应用资源包
+         *
+         * @param resourcePath
+         * @return
+         */
+        public LoadedResource loadResource(String resourcePath) {
+
+            LoadedResource loadResource = null;
+
+            PackageInfo info = queryPackageInfo(resourcePath);    //    获取未安装APK的PackageInfo
+            if (info != null) {    //   获取成功
+                loadResource = mRescources.get(info.packageName);    // 先从缓存中取, 存在则直接返回, 不重复添加. 否则就搜索添加
+                if (loadResource == null) {
+                    try {
+                        AssetManager assetManager = AssetManager.class.newInstance();    // 创建AssetManager实例
+                        Class cls = AssetManager.class;
+                        Method method = cls.getMethod("addAssetPath", String.class);
+                        method.invoke(assetManager, resourcePath);    // 反射设置资源加载路径
+                        Resources resources = new Resources(assetManager, mContext.getResources().getDisplayMetrics(),
+                                mContext.getResources().getConfiguration());    // 构造出正确的Resource
+                        loadResource = new LoadedResource();
+                        loadResource.resources = resources;
+                        loadResource.packageName = info.packageName;
+                        loadResource.classLoader = new DexClassLoader(resourcePath, mDexDir, null,
+                                mContext.getClassLoader());    //    设置正确的类加载器, 因为需要去加载R文件
+                        mRescources.put(info.packageName, loadResource);    // 缓存
+                        Log.w(TAG, "build resource:" + resourcePath);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+
+            Log.w(TAG, "load resource:" + resourcePath);
+            return loadResource;
+
+        }
+
+        /**
+         * 获取未安装应用PackageInfo
+         *
+         * @param resourcePath
+         * @return
+         */
+        private PackageInfo queryPackageInfo(String resourcePath) {
+            return mContext.getPackageManager().getPackageArchiveInfo(resourcePath, PackageManager.GET_ACTIVITIES);
+        }
+
+        /**
+         * 获取未安装应用LoadResource
+         *
+         * @param packageName
+         * @return
+         */
+        public LoadedResource getUnInstalledRecource(String packageName) {
+            LoadedResource loadResource = mRescources.get(packageName);
+            if (loadResource == null) {
+                Log.w(TAG, "resource " + packageName + " not founded");
+            }
+            return loadResource;
+        }
+
+    }
+
+    /**
+     * 针对于已安装应用
+     */
+    public static class Installed {
+        static final Installed sManager = new Installed();
+
+        private Context mContext;
+        private Map<String, LoadedResource> mResources = new HashMap<String, LoadedResource>();
+
+        private Installed() {
+
+        }
+
+        /**
+         * 初始化
+         *
+         * @param context
+         */
+        public void init(Context context) {
+            mContext = context.getApplicationContext();
+        }
+
+        /**
+         * 获取已安装应用资源
+         *
+         * @param packageName
+         */
+        public LoadedResource getInstalledResource(String packageName) {
+
+            LoadedResource resource = mResources.get(packageName);    // 先从缓存中取, 没有就去加载
+
+            if (resource == null) {
+                try {
+                    Context context = mContext.createPackageContext(packageName,
+                            Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+                    resource = new LoadedResource();
+                    resource.packageName = packageName;
+                    resource.resources = context.getResources();
+                    resource.classLoader = context.getClassLoader();
+                    mResources.put(packageName, resource);    // 得到结果缓存起来
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+
+            return resource;
+        }
+
+        /**
+         * 获取资源ID
+         *
+         * @param packageName
+         * @param type
+         * @param fieldName
+         * @return
+         */
+        public int getResourceID(String packageName, String type, String fieldName) {
+
+            int resID = 0;
+            LoadedResource installedResource = getInstalledResource(packageName);    // 获取已安装APK的资源
+            if (installedResource != null) {
+                String rClassName = packageName + ".R$" + type;    // 根据匿名内部类的命名, 拼写出R文件的包名+类名
+                try {
+                    Class cls = installedResource.classLoader.loadClass(rClassName);    //  加载R文件
+                    resID = (Integer) cls.getField(fieldName).get(null);    //  反射获取R文件对应资源名的ID
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            } else {
+                Log.w(TAG, "resource is null:" + packageName);
+            }
+            return resID;
+        }
+
+        /**
+         * 获取已加载应用Drawable
+         *
+         * @param packageName
+         * @param fieldName
+         * @return
+         */
+        public Drawable getDrawable(String packageName, String fieldName) {
+            Drawable drawable = null;
+            int resourceID = getResourceID(packageName, "drawable", fieldName);
+            LoadedResource installedResource = getInstalledResource(packageName);
+            if (installedResource != null) {
+                drawable = installedResource.resources.getDrawable(resourceID);
+            }
+            return drawable;
+        }
+    }
+    public static class LoadedResource {
+        public Resources resources;
+        public String packageName;
+        public ClassLoader classLoader;
+    }
+}
+
+
+

+ 141 - 0
common/src/main/code/com/enation/javashop/android/lib/core/framework/UnInstallResourceHelper.kt

@@ -0,0 +1,141 @@
+package com.enation.javashop.android.lib.core.framework
+
+import android.content.Context
+
+/**
+ * @author LDD
+ * @Date   2018/1/17 上午10:26
+ * @From   com.enation.javashop.android.middleware.resource
+ * @Note   加载未安装apk的资源文件
+ */
+class UnInstallResourceHelper {
+
+    /**
+     * @Name  resource
+     * @Type  ResourceManager.LoadedResource
+     * @Note  加载完成的资源
+     */
+    private lateinit var resource : ResourceManager.LoadedResource
+
+    /**
+     * @Name  packageName
+     * @Type  String
+     * @Note  资源包名
+     */
+    private lateinit var packageName : String
+
+    /**
+     * @author LDD
+     * @Date   2018/1/17 上午10:23
+     * @From   com.enation.javashop.android.middleware.resource
+     * @Note   伴生对象
+     */
+    companion object {
+
+        /**
+         * @Name  com.enation.javashop.android.lib.core.framework.UnInstallResourceHelper.Companion.instance
+         * @Type  com.enation.javashop.android.lib.core.framework.UnInstallResourceHelper
+         * @Note  单例
+         */
+        private val instance by lazy { UnInstallResourceHelper() }
+
+        /**
+         * @author LDD
+         * @From   Companion
+         * @Date   2018/1/17 上午10:25
+         * @Note   获取单例对象
+         * @return 未安装资源
+         */
+        fun get(): UnInstallResourceHelper {
+            return instance
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   UnInstallResourceHelper
+     * @Date   2018/1/17 上午10:22
+     * @Note   初始化
+     * @param  context 用户上下文
+     * @param  path    外部资源路径
+     */
+    fun init(context: Context,path:String){
+        ResourceManager.init(context)
+        resource = ResourceManager.unInstalled().loadResource(path)
+        packageName = resource.packageName
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取mipmap资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getMipmapId(name : String):Int{
+        return ResourceManager.unInstalled().getResourceID(packageName,"mipmap",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取drawable资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getDrawableId(name : String):Int{
+        return ResourceManager.unInstalled().getResourceID(packageName,"drawble",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取color资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getColorId(name : String):Int{
+
+        return ResourceManager.unInstalled().getResourceID(packageName,"color",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取style资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getStyleId(name : String):Int{
+
+        return ResourceManager.unInstalled().getResourceID(packageName,"style",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取string资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getStringId(name : String):Int{
+        return ResourceManager.unInstalled().getResourceID(packageName,"string",name)
+    }
+
+    /**
+     * @author LDD
+     * @From   InstallResourceHelper
+     * @Date   2018/1/17 上午10:20
+     * @Note   获取anim资源ID
+     * @param  name 资源名
+     * @return 资源ID
+     */
+    fun getAnimId(name : String):Int{
+        return ResourceManager.unInstalled().getResourceID(packageName,"anim",name)
+    }
+}

+ 68 - 0
common/src/main/code/com/enation/javashop/android/lib/core/hack/AndroidHack.kt

@@ -0,0 +1,68 @@
+package com.enation.javashop.android.lib.core.hack
+
+import android.app.Instrumentation
+import android.util.Log
+import com.enation.javashop.android.lib.core.framework.JavaShopInstrumentationHook
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午8:49
+ * @From   com.enation.javashop.android.lib.core.hack
+ * @Note   JavaShop Hack入口
+ */
+class AndroidHack {
+
+    /**
+     * 伴生对象
+     */
+    companion object {
+
+            /**
+             * @author  LDD
+             * @From   com.enation.javashop.android.lib.core.hack.AndroidHack Companion
+             * @Data   2017/12/26 上午8:50
+             * @Note   替换系统 hookInstrumentation 为null时自动进行JavaShopInstrumentationHook
+             * @param  instrumentationHook 需要进行hook的自定义Instrumentation
+             */
+            fun hookInstrumentation(instrumentationHook: Instrumentation?){
+
+                try {
+                    val mMainThreadClass = Class.forName("android.app.ActivityThread")
+
+                    //获取主线程
+                    val getMainThread = mMainThreadClass.getDeclaredMethod("currentActivityThread")
+                    //私有属性 设置访问权限
+                    getMainThread.isAccessible = true
+                    val currentActivityThread = getMainThread.invoke(null)
+
+                    // 获取mInstrumentation对象
+                    val mInstrumentationField = mMainThreadClass.getDeclaredField("mInstrumentation")
+                    //私有属性 设置访问权限
+                    mInstrumentationField.isAccessible = true
+                    //获取系统Instrumentation
+                    val instrumentation = mInstrumentationField.get(currentActivityThread) as Instrumentation
+                    // Hook Instrumentation 替换成我们自定义Instrumentation
+                    if (instrumentationHook==null){
+                        mInstrumentationField.set(currentActivityThread, JavaShopInstrumentationHook(instrumentation))
+                    }else{
+                        mInstrumentationField.set(currentActivityThread,instrumentationHook)
+                    }
+
+                    Log.i("InstrumentationHook", "JavaShop hook instrumentation success!")
+                } catch (ex: Exception) {
+                    Log.e("InstrumentationHook", "JavaShop hook instrumentation failed! [" + ex.message + "]")
+                }
+
+            }
+
+            /**
+             * @author  LDD
+             * @From   com.enation.javashop.android.lib.core.hack.AndroidHack Companion
+             * @Data   2017/12/26 上午8:53
+             * @Note   执行1参hookInstrumentation方法 直接使用JavaShopInstrumentationHook
+             */
+            fun hookInstrumentation(){
+                hookInstrumentation(null)
+            }
+        }
+}

+ 23 - 0
common/src/main/code/com/enation/javashop/android/lib/core/runtime/ClassNotFoundInterceptor.kt

@@ -0,0 +1,23 @@
+package com.enation.javashop.android.lib.core.runtime
+
+import android.content.Context
+import android.content.Intent
+
+/**
+ * @author  LDD
+ * @Data   2017/12/26 上午8:56
+ * @From   com.enation.javashop.android.lib.core.runtime
+ * @Note   拦截器接口
+ */
+interface ClassNotFoundInterceptor {
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.runtime ClassNotFoundInterceptor
+     * @Data   2017/12/26 上午8:57
+     * @Note   拦截器回调方法
+     * @param  context 上下文
+     * @param  intent  Intent
+     */
+    fun call(context:Context,intent :Intent?):Intent?
+}

+ 136 - 0
common/src/main/code/com/enation/javashop/android/lib/core/runtime/JavaShopActivityTask.kt

@@ -0,0 +1,136 @@
+package com.enation.javashop.android.lib.core.runtime
+
+import android.app.Activity
+import java.lang.ref.WeakReference
+import java.util.ArrayList
+
+ /**
+  * @author  LDD
+  * @Data   2017/12/26 上午9:00
+  * @From   com.enation.javashop.android.lib.core.runtime
+  * @Note   Activity栈
+  */
+ class JavaShopActivityTask {
+
+     /**
+      * @Name  activityList
+      * @Type  java.util.ArrayList
+      * @Note  Activity序列
+      */
+    private var activityList = ArrayList<WeakReference<Activity>>()
+
+     /**
+      * 伴生对象
+      */
+    companion object {
+         /**
+          * @Name  com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask.Companion.instance
+          * @Type  com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask
+          * @Note  单例
+          */
+         val instance = JavaShopActivityTask()
+    }
+
+     /**
+      * 构造方法私有化
+      */
+     private constructor()
+
+     /**
+      * @author  LDD
+      * @From   com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask
+      * @Data   2017/12/26 上午9:08
+      * @Note   获取当前应用Activity栈
+      * @return 当前应用Activity栈
+      */
+    fun getActivityArray(): ArrayList<WeakReference<Activity>>{
+        return activityList
+    }
+
+     /**
+      * @author  LDD
+      * @From   com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask
+      * @Data   2017/12/26 上午9:09
+      * @Note   获取当前栈顶Activity
+      * @return 当前栈顶Activity
+      */
+    fun peekTopActivity(): Activity? {
+        if (activityList != null && activityList.size > 0) {
+            val ref = activityList.get(activityList.size - 1)
+            if (ref != null && ref!!.get() != null) {
+                return ref!!.get()
+            }
+        }
+        return null
+    }
+
+     /**
+      * @author  LDD
+      * @From   com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask
+      * @Data   2017/12/26 上午9:13
+      * @Note   Activity创建时调用 添加activity到栈中
+      * @param  activity 新创建的Activity
+      */
+    fun pushToActivityStack(activity: Activity) {
+        activityList.add(WeakReference(activity))
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask
+     * @Data   2017/12/26 上午9:14
+     * @Note   activity销毁时调用 在栈中移除销毁的Activity
+     * @param  activity 销毁的Activity
+     */
+    fun popFromActivityStack(activity: Activity) {
+        for (x in activityList.indices) {
+            val ref = activityList.get(x)
+            if (ref != null && ref!!.get() != null && ref!!.get() === activity) {
+                activityList.remove(ref)
+                return
+            }
+        }
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask
+     * @Data   2017/12/26 上午9:16
+     * @Note   清除当前Activity栈
+     */
+    fun clearActivityStack() {
+        try {
+            for (ref in activityList) {
+                if (ref != null && ref!!.get() != null && !ref!!.get()!!.isFinishing()) {
+                    ref!!.get()!!.finish()
+                }
+            }
+        } catch (e: Throwable) {
+
+        } finally {
+            activityList.clear()
+        }
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask
+     * @Data   2017/12/26 上午9:17
+     * @Note   判断当前Activity栈是否为空
+     * @return Boolean 是否为空
+     */
+    fun isActivityStackEmpty(): Boolean {
+        return sizeOfActivityStack() == 0
+    }
+
+     /**
+      * @author  LDD
+      * @From   com.enation.javashop.android.lib.core.runtime.JavaShopActivityTask
+      * @Data   2017/12/26 上午9:18
+      * @Note   获取当前Activity栈大小
+      * @return 当前Activity栈大小
+      */
+    fun sizeOfActivityStack(): Int {
+        return activityList.size
+    }
+}

+ 59 - 0
common/src/main/code/com/enation/javashop/android/lib/core/split/ComponentManager.kt

@@ -0,0 +1,59 @@
+package com.enation.javashop.android.lib.core.split
+
+import java.io.File
+
+/**
+ * @author  LDD
+ * @Date   2018/1/15 下午4:10
+ * @From   com.enation.javashop.android.lib.core.split
+ * @Note   组件控制器协议
+ */
+interface ComponentManager {
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework.Framework Companion
+     * @Data   2017/12/26 上午8:35
+     * @Note   Moudle安装
+     * @param  pakeageName    模块包名
+     * @param  moudleLocation 模块绝对路径
+     */
+    fun installMoudle(pakeageName:String, moudleLocation: File)
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework.Framework Companion
+     * @Data   2017/12/26 上午8:36
+     * @Note   Moudle卸载
+     * @param  pakeageName 根据包名进行卸载
+     */
+    fun unstallMoudle(pakeageName:String)
+
+
+    /**
+     * @author  LDD
+     * @Date   2018/1/15 下午4:08
+     * @From   ComponentManager
+     * @Note   伴生对象
+     */
+    companion object {
+
+        /**
+         * @Name  com.enation.javashop.android.lib.core.split.ComponentManagerImpl.Companion.INSTANCE
+         * @Type  com.enation.javashop.android.lib.core.split.ComponentManager
+         * @Note  组件控制器单例
+         */
+        private val INSTANCE:ComponentManager by lazy { ComponentManagerImpl() }
+
+        /**
+         * @author LDD
+         * @From   Companion
+         * @Date   2018/1/15 下午4:22
+         * @Note   获取单例
+         * @return 单例
+         */
+        fun get() :ComponentManager{
+            return INSTANCE
+        }
+    }
+}

+ 36 - 0
common/src/main/code/com/enation/javashop/android/lib/core/split/ComponentManagerImpl.kt

@@ -0,0 +1,36 @@
+package com.enation.javashop.android.lib.core.split
+
+import java.io.File
+
+/**
+ * @author  LDD
+ * @Date   2018/1/15 下午4:10
+ * @From   com.enation.javashop.android.lib.core.split
+ * @Note   组件控制器单例
+ */
+class ComponentManagerImpl : ComponentManager{
+
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework.Framework Companion
+     * @Date   2017/12/26 上午8:35
+     * @Note   Moudle安装
+     * @param  pakeageName    模块包名
+     * @param  moudleLocation 模块绝对路径
+     */
+    override fun installMoudle(pakeageName:String, moudleLocation: File){
+
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.core.framework.Framework Companion
+     * @Date   2017/12/26 上午8:36
+     * @Note   Moudle卸载
+     * @param  pakeageName 根据包名进行卸载
+     */
+    override fun unstallMoudle(pakeageName:String){
+
+    }
+}

+ 15 - 0
common/src/main/code/com/enation/javashop/android/lib/jni/CommonJNI.kt

@@ -0,0 +1,15 @@
+package com.enation.javashop.android.lib.jni
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午5:29
+ * @From   com.enation.javashop.android.lib.jni
+ * @Note   JavaShop通用JNI入口
+ */
+class CommonJNI {
+    init {
+        System.loadLibrary("JavaShopCommonNDK")
+    }
+
+    external fun sayHello(): String
+}

+ 466 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/AppTool.kt

@@ -0,0 +1,466 @@
+package com.enation.javashop.android.lib.utils
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Color
+import android.os.Build
+import android.os.Handler
+import android.provider.Settings
+import android.support.v4.widget.DrawerLayout
+import android.support.v7.app.AppCompatActivity
+import android.view.View
+import android.view.ViewGroup
+import android.view.WindowManager
+import android.view.animation.AlphaAnimation
+import android.view.animation.Animation
+import android.view.animation.AnimationSet
+import android.view.animation.TranslateAnimation
+import android.view.inputmethod.InputMethodManager
+import android.widget.LinearLayout
+import com.enation.javashop.android.lib.base.BaseApplication
+import com.enation.javashop.net.engine.utils.ThreadFromUtils
+import com.enation.javashop.utils.base.tool.ScreenTool
+import io.reactivex.BackpressureStrategy
+import io.reactivex.Flowable
+import io.reactivex.Observable
+import io.reactivex.disposables.Disposable
+import java.io.IOException
+import java.io.InputStream
+import java.net.HttpURLConnection
+import java.net.MalformedURLException
+import java.net.URL
+import java.nio.charset.Charset
+import java.text.NumberFormat
+import java.util.concurrent.TimeUnit
+
+/**
+ * @author  LDD
+ * @Date   2018/1/10 下午5:46
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   App通用工具类
+ */
+object AppTool {
+
+    /**
+     * @author LDD
+     * @Date   2018/3/15 上午11:03
+     * @From   AppTool
+     * @Note   动画工具类
+     */
+    object Anim {
+
+        /**
+         * @author LDD
+         * @From   Anim
+         * @Date   2018/3/15 上午11:04
+         * @Note   构建popwindow进入动画
+         * @param  context 上下文
+         * @param  fromYDelta 开始y点
+         * @param  duration 动画时间
+         */
+        @JvmStatic
+        fun createPopInAnimation(context: Context, fromYDelta: Float, duration: Long): Animation {
+            val set = AnimationSet(context, null)
+            set.setFillAfter(true)
+            val animation = TranslateAnimation(0f, 0f, fromYDelta, 0f)
+            animation.setDuration(duration)
+            set.addAnimation(animation)
+            val alphaAnimation = AlphaAnimation(0f, 1f)
+            alphaAnimation.setDuration(duration)
+            set.addAnimation(alphaAnimation)
+            return set
+        }
+
+        /**
+         * @author LDD
+         * @From   Anim
+         * @Date   2018/3/15 上午11:04
+         * @Note   构建popwindow进入动画
+         * @param  context 上下文
+         * @param  toYDelta 结束y点
+         * @param  duration 动画时间
+         */
+        @JvmStatic
+        fun createPopOutAnimation(context: Context, toYDelta: Float, duration: Long): Animation {
+            val set = AnimationSet(context, null)
+            set.setFillAfter(true)
+            val animation = TranslateAnimation(0f, 0f, 0f, toYDelta)
+            animation.duration = duration
+            set.addAnimation(animation)
+            val alphaAnimation = AlphaAnimation(1f, 0f)
+            alphaAnimation.duration = duration
+            set.addAnimation(alphaAnimation)
+            return set
+        }
+    }
+
+    /**
+     * @author  LDD
+     * @Date   2018/1/10 下午5:46
+     * @From   com.enation.javashop.android.lib.utils.AppTool
+     * @Note   网络工具类
+     */
+    object Net {
+
+        /**
+         * @author LDD
+         * @From   Net
+         * @Date   2018/1/16 下午1:07
+         * @Note   验证网速 并toast
+         * @param  bits 网速
+         */
+        @JvmStatic
+        fun verifyNetSpeed(bits: Double) {
+            if (bits < 100) {
+                showMessage("当前网络质量差")
+            }
+        }
+
+        /**
+         * @author LDD
+         * @From   Net
+         * @Date   2018/1/16 下午1:07
+         * @Note   验证网速 网络不好时执行回调  由使用者决定是否显示Toast信息
+         * @param  bits 网速
+         */
+        @JvmStatic
+        fun verifyNetSpeed(bits: Double, callBack: (() -> (Unit)) -> (Unit)) {
+            val toastCallBack = {
+                showMessage("当前网络质量差")
+            }
+            if (bits < 100) {
+                callBack.invoke(toastCallBack)
+            }
+        }
+    }
+
+    /**
+     * @author  LDD
+     * @Date   2018/1/10 下午5:46
+     * @From   com.enation.javashop.android.lib.utils.AppTool
+     * @Note   RxJava工具类
+     */
+    object Rx {
+
+    }
+
+    /**
+     * @author LDD
+     * @Date   2018/5/18 上午11:27
+     * @From   com.enation.javashop.android.lib.utils.AppTool
+     * @Note   文件工具类
+     */
+    object File {
+
+        /**
+         * @author LDD
+         * @From   File
+         * @Date   2018/5/18 上午11:33
+         * @Note   读取Assets文件夹下的配置信息
+         * @param  context  上下文
+         * @param  fileName 文件名
+         */
+        @JvmStatic
+        fun readAssetsText(context: Context, fileName: String): String {
+            try {
+                val ins = context.assets.open(fileName)
+                val size = ins.available()
+                var buffer = ByteArray(size)
+                ins.read(buffer)
+                ins.close()
+                var text = String(buffer, Charset.forName("utf-8"))
+                return text
+            } catch (e :IOException) {
+                return "读取错误,请检查文件名"
+            }
+        }
+
+    }
+
+    /**
+     * @author LDD
+     * @Date   2018/3/15 下午3:07
+     * @From   AppTool
+     * @Note   关于时间的操作
+     */
+    object Time {
+        private val handler by lazy { Handler() }
+
+        /**
+         * @author LDD
+         * @From   com.enation.javashop.android.lib.utils.AppTool.Rx
+         * @Date   2018/1/10 下午5:41
+         * @Note   Observable扩展方法 延时执行
+         * @param  milliSeconds 延时毫秒数
+         * @param  handlerProcessor     处理回调
+         */
+        @JvmStatic
+        fun delay(milliSeconds: Long, handlerProcessor: () -> (Unit)) {
+            handler.postDelayed(handlerProcessor, milliSeconds)
+        }
+    }
+
+    object Calculation{
+
+        /**
+         * @author LDD
+         * @From   Calculation
+         * @Date   2018/5/21 下午3:21
+         * @Note   获取百分比
+         * @param  total 总数
+         * @param  current 当前
+         */
+        @JvmStatic
+        fun getPercentage(total: Int, current: Int): Int {
+            val numberFormat = NumberFormat.getInstance()
+            // 设置精确到小数点后2位
+            numberFormat.maximumFractionDigits = 0
+            val result = numberFormat.format(current.toFloat() / total.toFloat() * 100)
+            return Integer.valueOf(result)!!
+        }
+
+    }
+
+
+    /**
+     * @author LDD
+     * @Date   2018/1/11 上午10:31
+     * @From   com.enation.javashop.android.lib.utils.AppTool
+     * @Note   关于设置
+     */
+    object Setting {
+
+        /**
+         * @author  LDD
+         * @From    com.enation.javashop.android.lib.utils.AppTool.Setting
+         * @Date    2018/1/11 上午10:31
+         * @Note    跳转网络设置
+         * @param   activity 调用页面
+         */
+        @JvmStatic
+        fun systemNetSetting(activity: AppCompatActivity) {
+            activity.startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS))
+        }
+
+        /**
+         * @author  LDD
+         * @From    com.enation.javashop.android.lib.utils.AppTool.Setting
+         * @Date    2018/1/11 上午10:31
+         * @Note    跳转WIFI设置
+         * @param   activity 调用页面
+         */
+        @JvmStatic
+        fun systemWifiSetting(activity: AppCompatActivity) {
+            activity.startActivity(Intent(Settings.ACTION_WIFI_SETTINGS))
+        }
+
+        /**
+         * @author  LDD
+         * @From    com.enation.javashop.android.lib.utils.AppTool.Setting
+         * @Date    2018/1/11 上午10:31
+         * @Note    跳转Mobile设置
+         * @param   activity 调用页面
+         */
+        @JvmStatic
+        fun systemMobileSetting(activity: AppCompatActivity) {
+            activity.startActivity(Intent(Settings.ACTION_DATA_ROAMING_SETTINGS))
+        }
+    }
+
+    /**
+     * @author LDD
+     * @Date   2018/4/2 下午3:12
+     * @From   AppTool
+     * @Note   图片工具类
+     */
+    object Image {
+
+        /**
+         * @author LDD
+         * @From   Image
+         * @Date   2018/4/2 下午3:23
+         * @Note   url获取Bitmap
+         * @param  url 图片URL
+         */
+        @JvmStatic
+        fun urlToBitmap(url: String): Observable<Bitmap> {
+            return Observable.create { subscriber ->
+                var fileUrl: URL? = null
+                val bitmap: Bitmap
+
+                try {
+                    fileUrl = URL(url)
+                } catch (e: MalformedURLException) {
+                    subscriber.onError(e)
+                }
+
+
+                try {
+                    val conn = fileUrl!!.openConnection() as HttpURLConnection
+                    conn.doInput = true
+                    conn.connect()
+                    val inStream = conn.inputStream
+                    bitmap = BitmapFactory.decodeStream(inStream)
+                    inStream.close()
+                    subscriber.onNext(bitmap)
+                } catch (e: IOException) {
+                    subscriber.onError(e)
+                }
+            }
+        }
+    }
+
+    /**
+     * @author LDD
+     * @Date   2018/4/2 下午3:12
+     * @From   AppTool
+     * @Note   系统UI工具类
+     */
+    object SystemUI {
+
+        private var statusBarHeight : Int = 0
+
+        @JvmStatic fun getStatusBarHeight() : Int{
+            return statusBarHeight
+        }
+
+        @JvmStatic fun initStatusBarHeight(context: Context){
+            val resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android")
+            if (resourceId > 0) {
+                statusBarHeight = context.getResources().getDimensionPixelSize(resourceId)
+            }
+        }
+
+
+        /**
+         * @author  LDD
+         * @From   SystemUI
+         * @Date   2018/1/12 下午4:09
+         * @Note   设置状态栏透明  4.4.2及以下 不可设置导航栏变色
+         * @param  activity 需要状态栏透明的页面
+         * @param  bottomColor  导航栏变色
+         */
+        @JvmStatic
+        fun ImmersiveWithBottomBarColor(activity: Activity, bottomColor: Int) {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+                    //5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
+                    var window = activity.window
+                    var decorView = window.decorView
+                    //两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
+                    var option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                    decorView.systemUiVisibility = option
+                    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
+                    window.statusBarColor = Color.TRANSPARENT
+                    //导航栏颜色也可以正常设置
+                    window.navigationBarColor = bottomColor
+                } else {
+                    var window = activity.window
+                    var attributes = window.attributes
+                    var flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+                    attributes.flags = flagTranslucentStatus
+                    window.attributes = attributes
+                }
+            }
+        }
+
+        /**
+         * @author LDD
+         * @From   SystemUI
+         * @Date   2018/1/15 下午2:07
+         * @Note   设置当页面有drawlayout时,让drawlayout也实现变色
+         * @param  activity  需要设置的也米娜
+         * @param  rid       当页内容视图
+         */
+        @JvmStatic
+        fun KitkatNavigationViewImmersive(activity: Activity, rid: Int) {
+            //要在内容布局增加状态栏,否则会盖在侧滑菜单上
+            val rootView = activity.findViewById<ViewGroup>(android.R.id.content) as ViewGroup
+            //DrawerLayout 则需要在第一个子视图即内容试图中添加padding
+            val parentView = rootView.getChildAt(0)
+            val linearLayout = LinearLayout(activity)
+            linearLayout.orientation = LinearLayout.VERTICAL
+            //侧滑菜单
+            val drawer = parentView as DrawerLayout
+            //内容视图
+            val content = activity.findViewById<View>(rid)
+            //将内容视图从 DrawerLayout 中移除
+            drawer.removeView(content)
+            //添加内容视图
+            linearLayout.addView(content, content.layoutParams)
+            //将带有占位状态栏的新的内容视图设置给 DrawerLayout
+            drawer.addView(linearLayout, 0)
+
+            if (parentView != null && Build.VERSION.SDK_INT >= 14) {
+                parentView.fitsSystemWindows = true
+                //布局预留状态栏高度的 padding
+                if (parentView is DrawerLayout) {
+                    //将主页面顶部延伸至status bar;虽默认为false,但经测试,DrawerLayout需显示设置
+                    parentView.clipToPadding = false
+                }
+            }
+        }
+
+
+        /**
+         * @author LDD
+         * @From   SystemUI
+         * @Date   2018/1/29 下午8:28
+         * @Note   显示或隐藏导航栏
+         * @param  activity 需要操作的activity
+         * @param  isShow   显示还是隐藏
+         */
+        @JvmStatic
+        fun showNavigationBar(activity: Activity, isShow: Boolean) {
+            if (isShow) {
+                activity.window.decorView.setOnSystemUiVisibilityChangeListener(null)
+                activity.window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
+            } else {
+                activity.window.decorView.setOnSystemUiVisibilityChangeListener {
+                    activity.window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN)
+                }
+                activity.window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN)
+            }
+        }
+
+        /**
+         * @author LDD
+         * @From   SystemUI
+         * @Date   2018/4/17 下午1:44
+         * @Note   dp转px
+         * @param  dp dp大小
+         */
+        @JvmStatic
+        fun dpToPx(dp: Float): Int {
+            return ScreenTool.dip2px(BaseApplication.appContext, dp)
+        }
+
+        @JvmStatic
+        fun getNavigationBarHeight(activity: Activity): Int {
+            val resources = activity.getResources()
+            val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
+            val height = resources.getDimensionPixelSize(resourceId)
+            return height
+        }
+
+        /**
+         * @author LDD
+         * @From   SystemUI
+         * @Date   2018/5/15 下午4:47
+         * @Note   关闭软键盘
+         * @param  context 页面
+         */
+        @JvmStatic
+        fun hideKeyBoard(context: Activity) {
+            val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+            if (imm.isActive && context.currentFocus != null) {
+                if (context.currentFocus.windowToken != null) {
+                    imm.hideSoftInputFromWindow(context.currentFocus.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
+                }
+            }
+        }
+    }
+}

+ 47 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/AutoClearHelper.kt

@@ -0,0 +1,47 @@
+package com.enation.javashop.android.lib.utils
+
+import android.util.Log
+import java.util.IdentityHashMap
+
+
+/**
+ * @author  LDD
+ * @Data   2017/12/21 下午5:25
+ * @Note   自动清除数据辅助类 在Activity销毁时,自动处理其中参数,作用于该类
+ * {@link com.enation.javashop.android.lib.utils.AutoClearValue}
+ */
+class AutoClearHelper {
+
+    companion object {
+        val intance:AutoClearHelper by lazy {  AutoClearHelper() }
+    }
+
+    private constructor()
+
+    /**
+     * 储存
+     */
+    private var valueMap : IdentityHashMap<String, () -> Unit> = IdentityHashMap()
+
+    /**
+     * 创建
+     */
+    fun create(key:String,value:()->Unit){
+        valueMap.put(key,value)
+    }
+
+    /**
+     * Activity销毁时调用
+     */
+    fun destory(name :String){
+        valueMap.keys.filter { it == name }.forEach { valueMap[it]!!.invoke() }
+        valueMap.clear()
+    }
+
+    /**
+     * 获取当前AutoValuemap中Value总数
+     */
+    fun valueCount():Int{
+        return valueMap.size
+    }
+}

+ 69 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/AutoClearValue.kt

@@ -0,0 +1,69 @@
+package com.enation.javashop.android.lib.utils
+
+import android.app.Activity
+import android.support.v4.app.Fragment
+import android.support.v4.app.FragmentManager
+import android.util.Log
+
+/**
+ * @author  LDD
+ * @Data   2017/12/21 下午5:53
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   自动清理变量
+ */
+class AutoClearValue<ValueType> {
+
+    /**
+     * @Name  value
+     * @Type  ValueType
+     * @Note  自动处理的V安略
+     */
+    private var value : ValueType? = null
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils AutoClearValue
+     * @Data   2017/12/22 下午3:40
+     * @Note   在Fragment中使用的构造方法构造方法
+     * @param  fragment 所在的Fragment
+     */
+    constructor(fragment :Fragment , value: ValueType?) {
+        fragment.fragmentManager.registerFragmentLifecycleCallbacks(object : FragmentManager.FragmentLifecycleCallbacks(){
+            override fun onFragmentDestroyed(fm: FragmentManager?, f: Fragment?) {
+                if (f == fragment) {
+                    this@AutoClearValue.value = null
+                    if (fm != null) {
+                        fm.unregisterFragmentLifecycleCallbacks(this)
+                    }
+                }
+            }
+        },false)
+        get()
+        this.value = value
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils AutoClearValue
+     * @Data   2017/12/22 下午3:41
+     * @Note   在Activity中使用的构造方法
+     * @param  activity 所在的Activity
+     */
+    constructor(activity: Activity,value:ValueType?){
+        AutoClearHelper.intance.create(activity.localClassName,{
+            this.value = null
+        })
+
+        this.value = value
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils AutoClearValue
+     * @Data   2017/12/21 下午5:53
+     * @Note   获取value
+     */
+    fun get() : ValueType?{
+        return value
+    }
+}

+ 53 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/BaseRecyclerViewHolder.kt

@@ -0,0 +1,53 @@
+package com.enation.javashop.android.lib.utils
+
+import android.databinding.DataBindingUtil
+import android.databinding.ViewDataBinding
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.ViewGroup
+
+/**
+ * @author LDD
+ * @Date   2018/2/2 下午4:02
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   RecyclerView ViewHolder 基类
+ */
+class BaseRecyclerViewHolder<out BindType:ViewDataBinding>(val databinding:BindType) :RecyclerView.ViewHolder(databinding.root) {
+
+    companion object {
+        /**
+         * @author LDD
+         * @From   BaseRecyclerViewHolder
+         * @Date   2018/4/10 上午11:18
+         * @Note   快速构建
+         * @param  parent   父容器
+         * @param  layoutId 布局ID
+         */
+        fun <BindType:ViewDataBinding>build(parent: ViewGroup?,layoutId : Int) : BaseRecyclerViewHolder<BindType>{
+            return BaseRecyclerViewHolder(DataBindingUtil.bind(LayoutInflater.from(parent?.context).inflate(layoutId,parent,false)))
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseRecyclerViewHolder
+     * @Date   2018/2/2 下午4:03
+     * @Note   获取viewbinding
+     * @return ViewDataBinding
+     */
+    fun getBinding():BindType{
+        return databinding
+    }
+
+    /**
+     * @author LDD
+     * @From   BaseRecyclerViewHolder
+     * @Date   2018/2/2 下午4:05
+     * @Note   绑定数据
+     * @param  block 绑定回调
+     */
+    inline fun bind(block :(binding : BindType)-> Unit){
+        block(databinding)
+    }
+
+}

+ 46 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/ChinaeseSortHelper.kt

@@ -0,0 +1,46 @@
+package com.enation.javashop.android.lib.utils
+
+import net.sourceforge.pinyin4j.PinyinHelper
+import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType
+import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat
+import net.sourceforge.pinyin4j.format.HanyuPinyinToneType
+import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination
+
+
+/**
+ * @author LDD
+ * @Date   2018/3/27 下午5:46
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   获取汉字首字母
+ */
+object ChinaeseSortHelper {
+    fun getFirstSpell(string: String): String {
+        val pybf = StringBuffer()
+        val arr = string.toCharArray()
+        val defaultFormat = HanyuPinyinOutputFormat()
+        defaultFormat.caseType = HanyuPinyinCaseType.LOWERCASE
+        defaultFormat.toneType = HanyuPinyinToneType.WITHOUT_TONE
+        for (i in arr.indices) {
+            if (arr[i].toInt() > 128) { //如果已经是字母就不用转换了
+                try {
+                    //获取当前汉字的全拼
+                    val temp = PinyinHelper.toHanyuPinyinStringArray(
+                            arr[i], defaultFormat)
+                    if (temp != null) {
+                        pybf.append(temp[0][0])// 取首字母
+                    }
+                } catch (e: BadHanyuPinyinOutputFormatCombination) {
+                    e.printStackTrace()
+                }
+
+            } else {
+                if (arr[i] in 'a'..'z') {
+                    arr[i].minus(32)
+                }
+                pybf.append(arr[i])
+            }
+        }
+        return pybf.toString().substring(0,1).toUpperCase()
+    }
+
+}

+ 144 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/ConnectionObserver.kt

@@ -0,0 +1,144 @@
+package com.enation.javashop.android.lib.utils
+
+import android.content.Context
+import com.enation.javashop.android.lib.base.BaseApplication
+import com.enation.javashop.net.engine.plugin.connection.ConnectionQuality
+import com.enation.javashop.net.engine.plugin.exception.ExceptionHandle
+import com.enation.javashop.net.engine.utils.VoiNetTool
+import io.reactivex.Observer
+import io.reactivex.disposables.Disposable
+import org.json.JSONObject
+import retrofit2.HttpException
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午3:43
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   可以监听网络状态的观察者
+ */
+abstract class ConnectionObserver<T> : BaseObserver<T>(BaseApplication.appContext) {
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionObserver
+     * @Data   2017/12/22 下午3:44
+     * @Note   实现onStar方法 在此开始执行网络监听 并执行onStartWithConnection抽象方法
+     */
+    override fun onStart() {
+        ConnectionQualityMonitor.INSTANCE.startSample()
+        onStartWithConnection()
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionObserver
+     * @Data   2017/12/22 下午3:46
+     * @Note   实现onNext方法 在此停止网络监听 并执行onNextWithConnection
+     *           connectionBitsOfSecond方法 传递网络状态,网络速率
+     */
+    override fun onNext(p0: T) {
+        ConnectionQualityMonitor.INSTANCE.stopSample()
+        onNextWithConnection(p0,ConnectionQualityMonitor.INSTANCE.getConnectionQuanlity())
+        connectionBitsOfSecond(ConnectionQualityMonitor.INSTANCE.getConnectionBits())
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionObserver
+     * @Data   2017/12/22 下午3:50
+     * @Note   实现onError方法 传递网络状态,网络速率
+     */
+    override fun onError(p0: ExceptionHandle.ResponeThrowable) {
+        ConnectionQualityMonitor.INSTANCE.stopSample()
+        onErrorWithConnection(p0,ConnectionQualityMonitor.INSTANCE.getConnectionQuanlity())
+        connectionBitsOfSecond(ConnectionQualityMonitor.INSTANCE.getConnectionBits())
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionObserver
+     * @Data   2017/12/22 下午3:51
+     * @Note   传递当前网络速率 需要继承者重写
+     * @param  bits 网络速率
+     */
+    open fun connectionBitsOfSecond(bits: Double){}
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionObserver
+     * @Data   2017/12/22 下午3:53
+     * @Note   抽象方法,子类可以监听网络请求开始,并可以获得当前网络状态
+     */
+    abstract fun onStartWithConnection()
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionObserver
+     * @Data   2017/12/22 下午3:55
+     * @Note   抽象方法,子类可以监听网络请求成功,并获取当前网络状态
+     * @param  result 网络请求结果
+     * @param  connectionQuality 网络状态
+     */
+    abstract fun onNextWithConnection(result:T,connectionQuality :ConnectionQuality)
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionObserver
+     * @Data   2017/12/22 下午3:56
+     * @Note   抽象方法,子类可以监听网络请求失败,并获取当前网络状态
+     * @param  error 自定义网络错误
+     * @param  connectionQuality 当前网络状态
+     */
+    abstract fun onErrorWithConnection(error: ExceptionHandle.ResponeThrowable,connectionQuality :ConnectionQuality)
+}
+
+abstract class BaseObserver<T>(private val context: Context) : Observer<T> {
+
+    override fun onSubscribe(disposable: Disposable) {
+        if (VoiNetTool.getAPNType(this.context) == VoiNetTool.netType.noneNet) {
+            disposable.dispose()
+            this.onNoneNet()
+        } else {
+            this.onStart()
+            this.attachSubscribe(disposable)
+        }
+
+    }
+
+    override fun onError(e: Throwable) {
+        if (e is HttpException) {
+            var errorJSon = e.response().errorBody()!!.getJsonString()
+            if (errorJSon.contains("html")){
+                this.onError(ExceptionHandle.handleException(e))
+                return
+            }
+            val obj = JSONObject(errorJSon)
+            if (obj.has("code")){
+                val result = ExceptionHandle.ResponeThrowable(e,420)
+                result.customMessage = obj.getString("message")
+                this.onError(result)
+            }else{
+                this.onError(ExceptionHandle.handleException(e))
+            }
+        } else {
+            this.onError(ExceptionHandle.ResponeThrowable(e, 1000).then {
+                if (e.message == null) {
+                    it.customMessage = "加载失败!"
+                } else {
+                    it.customMessage = e.message
+                }
+            })
+        }
+
+    }
+
+    abstract fun onError(var1: ExceptionHandle.ResponeThrowable)
+
+    abstract fun onStart()
+
+    abstract fun attachSubscribe(var1: Disposable)
+
+    open fun onNoneNet() {}
+
+    override fun onComplete() {}
+}

+ 66 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/ConnectionQualityMonitor.kt

@@ -0,0 +1,66 @@
+package com.enation.javashop.android.lib.utils
+
+import android.util.Log
+import com.enation.javashop.net.engine.plugin.connection.ConnectionQuality
+import com.enation.javashop.net.engine.plugin.connection.ConnectionClassManager
+import com.enation.javashop.net.engine.plugin.connection.DeviceBandwidthSampler
+
+
+/**
+ * @Coder  LDD
+ * @Data   2017/12/22 下午3:58
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   网络状态监听
+ */
+class ConnectionQualityMonitor {
+
+    /**伴生对象,其中的方法相当于Java的静态方法*/
+    companion object {
+        /**单利设计模式 懒汉式*/
+        val INSTANCE:ConnectionQualityMonitor by lazy { ConnectionQualityMonitor() }
+    }
+
+    /**
+     * @Coder  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionQualityMonitor
+     * @Data   2017/12/22 下午3:59
+     * @Note   开始网络取样
+     */
+    fun startSample(){
+        DeviceBandwidthSampler.getInstance().startSampling()
+    }
+
+    /**
+     * @Coder  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionQualityMonitor
+     * @Data   2017/12/22 下午3:59
+     * @Note   停止网络取样
+     */
+    fun stopSample(){
+        DeviceBandwidthSampler.getInstance().stopSampling()
+    }
+
+    /**
+     * @Coder  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionQualityMonitor
+     * @Data   2017/12/22 下午4:00
+     * @Note   获取当前网络状态
+     * @return 当前网络状态
+     */
+    fun getConnectionQuanlity() :ConnectionQuality{
+        val quanlity = ConnectionClassManager.getInstance().currentBandwidthQuality
+        return quanlity
+    }
+
+    /**
+     * @Coder  LDD
+     * @From   com.enation.javashop.android.lib.utils ConnectionQualityMonitor
+     * @Data   2017/12/22 下午4:00
+     * @Note   获取当前网络速率
+     * @return 当前网络速率
+     */
+    fun getConnectionBits() :Double{
+      return  ConnectionClassManager.getInstance().downloadKBitsPerSecond
+    }
+
+}

+ 374 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/Do.kt

@@ -0,0 +1,374 @@
+package com.enation.javashop.android.lib.utils
+
+import android.os.Looper
+import java.util.concurrent.Executors
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午4:06
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   快速切换线程工具类 保证线程执行顺序
+ */
+  class Do :SendResultInterface,NomalResultInterface {
+
+    /**
+     * 伴生对象
+     */
+    companion object {
+
+        /**
+         * @author  LDD
+         * @From   com.enation.javashop.android.lib.utils.Do Companion
+         * @Data   2017/12/22 下午4:09
+         * @Note   初始化
+         */
+        fun prepare(): NomalResultInterface {
+            return Do()
+        }
+    }
+
+    /**
+     * @Name  threadPool
+     * @Type  ExecutorService
+     * @Note  可缓存线程池,用于处理非UI线程任务
+     */
+    private var threadPool = Executors.newFixedThreadPool(1)
+
+    /**
+     * @Name  threadQueue
+     * @Type  ArrayList<Any>
+     * @Note  任务序列
+     */
+    private var threadQueue : ArrayList<Any> = ArrayList()
+
+    /**
+     * @Name  onUI
+     * @Type  Int
+     * @Note  UI线程处理标记
+     */
+    private val onUI = 1
+
+    /**
+     * @Name  onThread
+     * @Type  Int
+     * @Note  非UI线程处理标记
+     */
+    private val onThread = 2
+
+    /**
+     * @Name  threadPool
+     * @Type  Handler
+     * @Note  UI任务处理Hander
+     */
+    private val uiThread = android.os.Handler(Looper.getMainLooper())
+
+    /**
+     * @Name  index
+     * @Type  int
+     * @Note  处理标记,编辑当前处理到第几个任务
+     */
+    private var index= 0
+
+    /**
+     * @Name  runFlag
+     * @Type  boolean
+     * @Note  标识当前任务序列是否执行完成
+     */
+    private var runFlag = false
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:16
+     * @Note   开始执行方法 递归处理事件队列
+     */
+    override fun execute(){
+        if (threadQueue.size>0){
+            val data = threadQueue[index]
+            if (runFlag){
+                execute()
+                return
+            }
+            runFlag = true
+            when (data) {
+                is DoModel -> {
+                    nomalDo()
+                }
+                is DoSendModel -> {
+                    sendDo()
+                }
+            }
+        }
+    }
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:17
+     * @Note   常规事件执行方法
+     */
+    private fun nomalDo(){
+        val data:DoModel = threadQueue[index] as DoModel
+        if (data.thread == onUI){
+            uiThread.post{
+                data.call.invoke {
+                    index+=1
+                    if (threadQueue.size > index){
+                        when (threadQueue[index]) {
+                            is DoModel -> {
+                                nomalDo()
+                            }
+                            is DoSendModel -> {
+                                sendDo()
+                            }
+                        }
+                    }else{
+                        clear()
+                    }
+                }
+            }
+        }else if(data.thread == onThread){
+            threadPool.execute {
+                data.call.invoke {
+                    index+=1
+                    if (threadQueue.size > index){
+                        when (threadQueue[index]) {
+                            is DoModel -> {
+                                nomalDo()
+                            }
+                            is DoSendModel -> {
+                                sendDo()
+                            }
+                        }
+                    }else{
+                        clear()
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:18
+     * @Note   发送参数事件处理方法
+     */
+    private fun sendDo(){
+        val data:DoSendModel = threadQueue[index] as DoSendModel
+        if (data.thread == onUI){
+            uiThread.post{
+                data.call.invoke {
+                    value ->
+                    index +=1
+                    if (threadQueue.size > index){
+                        when (threadQueue[index]) {
+                            is DoResultModel ->{
+                                resultDo(value)
+                            }
+                        }
+                    }else{
+                        clear()
+                    }
+                }
+            }
+        }else if(data.thread == onThread){
+            threadPool.execute {
+                data.call.invoke {
+                    value ->
+                    index +=1
+                    if (threadQueue.size > index){
+                        when (threadQueue[index]) {
+                            is DoResultModel ->{
+                                resultDo(value)
+                            }
+                        }
+                    }else{
+                        clear()
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:19
+     * @Note   接受参数事件处理方法
+     * @param  value 所接受的参数
+     */
+    private fun resultDo(value :Any){
+        val data:DoResultModel = threadQueue[index] as DoResultModel
+        if (data.thread == onUI){
+            uiThread.post{
+                data.call.invoke(value) {
+                    index +=1
+                    if (threadQueue.size > index){
+                        when (threadQueue[index]) {
+                            is DoModel -> {
+                                nomalDo()
+                            }
+                            is DoSendModel -> {
+                                sendDo()
+                            }
+                        }
+                    }else{
+                        clear()
+                    }
+                }
+            }
+        }else if(data.thread == onThread){
+            threadPool.execute {
+                data.call.invoke(value) {
+                    index +=1
+                    if (threadQueue.size > index){
+                        when (threadQueue[index]) {
+                            is DoModel -> {
+                                nomalDo()
+                            }
+                            is DoSendModel -> {
+                                sendDo()
+                            }
+                        }
+                    }else{
+                        clear()
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:20
+     * @Note   清除线程池 索引 复原运行标记
+     */
+    private fun clear(){
+        index = 0
+        threadQueue.clear()
+        runFlag = false
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:20
+     * @Note   在UI主线程执行普通方法
+     * @param  call 方法回调
+     */
+    override fun doOnUI(call: (call :() -> Unit) -> Unit):NomalResultInterface{
+        threadQueue.add(DoModel(onUI,call))
+        return this
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:33
+     * @Note   在非UI线程执行普通方法
+     * @param  call 方法回调
+     */
+    override fun doOnBack(call: (call :() -> Unit) -> Unit):NomalResultInterface{
+        threadQueue.add(DoModel(onThread,call))
+        return this
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:37
+     * @Note   在UI线程执行传递参数方法
+     * @param  call 方法回调
+     */
+    override fun onUISend(call: ((value :Any) -> Unit) -> Unit):SendResultInterface{
+        threadQueue.add(DoSendModel(onUI,call))
+        return this
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:37
+     * @Note   在非UI线程执行传递参数方法
+     * @param  call 方法回调
+     */
+    override fun onBackSend(call: ((value :Any) -> Unit) -> Unit):SendResultInterface{
+        threadQueue.add(DoSendModel(onThread,call))
+        return this
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:38
+     * @Note   在主线程执行接受参数方法
+     * @param  call 方法回调
+     */
+    override fun onUIResult(call: (Any,() -> Unit) -> Unit):NomalResultInterface{
+        threadQueue.add(DoResultModel(onUI,call))
+        return this
+    }
+
+    /**
+     * @author  LDD
+     * @From   com.enation.javashop.android.lib.utils Do
+     * @Data   2017/12/22 下午4:39
+     * @Note   在非UI线程执行结束参数方法
+     * @param  call 方法回调
+     */
+    override fun onBackResult(call: (Any,() -> Unit) -> Unit):NomalResultInterface{
+        threadQueue.add(DoResultModel(onThread,call))
+        return this
+    }
+
+}
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午4:42
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   执行完发送参数方法后 返回对应接口
+ */
+interface SendResultInterface {
+    fun onBackResult (call: (Any,() -> Unit) -> Unit):NomalResultInterface
+    fun onUIResult(call: (Any,() -> Unit) -> Unit):NomalResultInterface
+}
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午4:42
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   执行完普通方法和接受参数方法后 返回对应接口
+ */
+interface NomalResultInterface{
+    fun onBackSend(call: ((value :Any) -> Unit) -> Unit):SendResultInterface
+    fun onUISend(call: ((value :Any) -> Unit) -> Unit):SendResultInterface
+    fun doOnBack(call: (call :() -> Unit) -> Unit):NomalResultInterface
+    fun doOnUI(call: (call :() -> Unit) -> Unit):NomalResultInterface
+    fun execute()
+}
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午4:43
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   普通方法 Model
+ */
+data class DoModel constructor(var thread :Int, var call :(() -> Unit) -> Unit)
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午4:43
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   发送参数方法 Model
+ */
+data class DoSendModel constructor(var thread :Int, var call :((value : Any) -> Unit) -> Unit)
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午4:43
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   接收参数方法 Model
+ */
+data class DoResultModel constructor(var thread :Int, var call :(result :Any,() -> Unit) -> Unit)

+ 113 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/EcodeHelper.kt

@@ -0,0 +1,113 @@
+package com.enation.javashop.android.lib.utils
+
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import com.google.zxing.BarcodeFormat
+import com.google.zxing.EncodeHintType
+import com.google.zxing.WriterException
+import com.google.zxing.qrcode.QRCodeWriter
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
+import io.reactivex.Observable
+
+/**
+ * Created by LDD on 2018/11/9.
+ */
+class EcodeHelper {
+
+
+    fun rxCreateQRImage(content: String, heightPix: Int, logoBm: Bitmap?) :Observable<Bitmap>{
+        return Observable.create { observableEmitter ->
+            observableEmitter.onNext(createQRImage(content,heightPix,logoBm)!!)
+        }
+    }
+
+    fun createQRImage(content: String, heightPix: Int, logoBm: Bitmap?): Bitmap? {
+        try {
+            // if (content == null || "".equals(content)) {
+            // return false;
+            // }
+
+            //配置参数
+            val hints = HashMap<EncodeHintType, Any>()
+            hints.put(EncodeHintType.CHARACTER_SET, "utf-8")
+            //容错级别
+            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H)
+            //设置空白边距的宽度
+            // hints.put(EncodeHintType.MARGIN, 2); //default is 4
+
+            // 图像数据转换,使用了矩阵转换
+            val bitMatrix = QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, heightPix, heightPix, hints)
+            val pixels = IntArray(heightPix * heightPix)
+            // 下面这里按照二维码的算法,逐个生成二维码的图片,
+            // 两个for循环是图片横列扫描的结果
+            for (y in 0 until heightPix) {
+                for (x in 0 until heightPix) {
+                    if (bitMatrix.get(x, y)) {
+                        pixels[y * heightPix + x] = -0x1000000
+                    } else {
+                        pixels[y * heightPix + x] = -0x1
+                    }
+                }
+            }
+
+            // 生成二维码图片的格式,使用ARGB_8888
+            var bitmap: Bitmap? = Bitmap.createBitmap(heightPix, heightPix, Bitmap.Config.ARGB_8888)
+            bitmap!!.setPixels(pixels, 0, heightPix, 0, 0, heightPix, heightPix)
+
+            if (logoBm != null) {
+                bitmap = addLogo(bitmap, logoBm)
+            }
+
+            //必须使用compress方法将bitmap保存到文件中再进行读取。直接返回的bitmap是没有任何压缩的,内存消耗巨大!
+            return bitmap
+        } catch (e: WriterException) {
+            e.printStackTrace()
+        }
+
+        return null
+    }
+
+    /**
+     * 在二维码中间添加Logo图案
+     */
+    private fun addLogo(src: Bitmap?, logo: Bitmap?): Bitmap? {
+        if (src == null) {
+            return null
+        }
+
+        if (logo == null) {
+            return src
+        }
+
+        //获取图片的宽高
+        val srcWidth = src.width
+        val srcHeight = src.height
+        val logoWidth = logo.width
+        val logoHeight = logo.height
+
+        if (srcWidth == 0 || srcHeight == 0) {
+            return null
+        }
+
+        if (logoWidth == 0 || logoHeight == 0) {
+            return src
+        }
+
+        //logo大小为二维码整体大小的1/5
+        val scaleFactor = srcWidth * 1.0f / 5f / logoWidth.toFloat()
+        var bitmap: Bitmap? = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888)
+        try {
+            val canvas = Canvas(bitmap)
+            canvas.drawBitmap(src, 0f, 0f, null)
+            canvas.scale(scaleFactor, scaleFactor, (srcWidth / 2).toFloat(), (srcHeight / 2).toFloat())
+            canvas.drawBitmap(logo, ((srcWidth - logoWidth) / 2).toFloat(), ((srcHeight - logoHeight) / 2).toFloat(), null)
+            canvas.save()
+            canvas.restore()
+        } catch (e: Exception) {
+            bitmap = null
+            e.stackTrace
+        }
+
+        return bitmap
+    }
+}

+ 743 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/ExtendMethods.kt

@@ -0,0 +1,743 @@
+package com.enation.javashop.android.lib.utils
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午4:45
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   扩展方法Koltin文件
+ */
+
+import android.app.Activity
+import android.app.Fragment
+import android.content.Context
+import android.content.Intent
+import android.databinding.ObservableField
+import android.os.Looper
+import android.support.v4.content.ContextCompat
+import android.support.v7.app.AppCompatActivity
+import android.view.View
+import android.view.ViewGroup
+import android.view.animation.Animation
+import android.widget.Toast
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.enation.javashop.android.jrouter.JRouter
+import com.enation.javashop.android.jrouter.logic.datainfo.Postcard
+import com.enation.javashop.android.lib.R
+import com.enation.javashop.android.lib.adapter.BaseDelegateAdapter
+import com.enation.javashop.android.lib.base.BaseApplication
+import com.enation.javashop.android.lib.base.DisposableManager
+import com.enation.javashop.net.engine.plugin.rxbus.RxBus
+import com.enation.javashop.utils.base.tool.CommonTool
+import com.enation.javashop.utils.base.tool.ScreenTool
+import com.enation.javashop.utils.logger.LoggerFactory
+import io.reactivex.disposables.Disposable
+import okhttp3.ResponseBody
+import org.json.JSONArray
+import org.json.JSONObject
+import java.lang.RuntimeException
+import java.lang.ref.WeakReference
+import java.nio.charset.Charset
+import java.util.*
+import kotlin.collections.ArrayList
+
+/**
+ * 绑定字段 指定泛型
+ */
+typealias ObserableString = ObservableField<String>
+
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:47
+ * @Note   debug日志打印
+ * @param  tag 标记
+ * @param  message 日志信息
+ */
+fun debugLog(tag: String?, message: String?) {
+    val st = Throwable().stackTrace[1]
+    LoggerFactory.getLogger().i("【Tag -> $tag】 >>>>>>>>>>", "Message -> $message >>>>>>>>>>>>>>>>>>>>>>>>>> 【Location ->Class:${st.className} - Method:${st.methodName} - Line:${st.lineNumber}】 ")
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:47
+ * @Note   error日志打印
+ * @param  tag 标记
+ * @param  message 日志信息
+ */
+fun errorLog(tag: String, message: String) {
+    val st = Throwable().stackTrace[1]
+    LoggerFactory.getLogger().e("【Tag -> $tag】 >>>>>>>>>>", "Message -> $message >>>>>>>>>>>>>>>>>>>>>>>>>> 【Location ->Class:${st.className} - Method:${st.methodName} - Line:${st.lineNumber}】 ")
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:47
+ * @Note   显示Toast信息
+ * @param  message 需要显示的信息
+ */
+fun showMessage(message: String) {
+    if (message == ""){
+        return
+    }
+    val messageCallback = {
+        Toast.makeText(BaseApplication.appContext, message, Toast.LENGTH_SHORT).show()
+    }
+    try {
+        messageCallback.invoke()
+    } catch (runtime: RuntimeException) {
+        Looper.prepare()
+        messageCallback.invoke()
+    }
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:48
+ * @Note   数据类型转换
+ * @return 转换后的值
+ */
+fun <T> Any.to(): T {
+    return this as T
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:49
+ * @Note   通过JRouter框架检索对象,并实例化
+ * @param  path 对象注册到JRouter的路径
+ */
+fun <T> acquireInstance(path: String): T {
+    return JRouter.prepare().create(path).seek().to()
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:51
+ * @Note   跳转页面Activity扩展方法
+ * @param  path Activity注册到JRouter中的路径
+ * @param  _block 更多操作
+ * @param  requstCode 返回码
+ */
+fun AppCompatActivity.push(path: String, _block: ((Postcard) -> Unit)? = null, requstCode: Int = -1 , isNeedLogin :Boolean = false) {
+    if (isNeedLogin){
+        JRouter.prepare().create("/member/login/main").withTransition(R.anim.push_left_in, R.anim.push_left_out).then { postcard ->
+            _block?.invoke(postcard)
+        }.seek(this)
+        return
+    }
+    val engine = JRouter.prepare().create(path).withTransition(R.anim.push_left_in, R.anim.push_left_out).then { postcard ->
+        _block?.invoke(postcard)
+    }
+    if (requstCode == -1) {
+        engine.seek(this)
+    } else {
+        engine.seek(this, requstCode)
+    }
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:51
+ * @Note   跳转页面Activity扩展方法
+ * @param  path Activity注册到JRouter中的路径
+ * @param  _block 更多操作
+ * @param  requstCode 返回码
+ */
+fun Activity.push(path: String, _block: ((Postcard) -> Unit)? = null, requstCode: Int = -1 , isNeedLogin :Boolean = false) {
+    if (isNeedLogin){
+        JRouter.prepare().create("/member/login/main").withTransition(R.anim.push_left_in, R.anim.push_left_out).then { postcard ->
+            _block?.invoke(postcard)
+        }.seek(this)
+        return
+    }
+    val engine = JRouter.prepare().create(path).withTransition(R.anim.push_left_in, R.anim.push_left_out).then { postcard ->
+        _block?.invoke(postcard)
+    }
+    if (requstCode == -1) {
+        engine.seek(this)
+    } else {
+        engine.seek(this, requstCode)
+    }
+}
+
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:51
+ * @Note   跳转页面 V4 Fragment扩展方法
+ * @param  path Activity注册到JRouter中的路径
+ * @param  _block 更多操作
+ */
+fun android.support.v4.app.Fragment.push(path: String, _block: ((Postcard) -> Unit)? = null , isNeedLogin :Boolean = false) {
+    if (isNeedLogin){
+        JRouter.prepare().create("/member/login/main").withTransition(R.anim.push_left_in, R.anim.push_left_out).then { postcard ->
+            _block?.invoke(postcard)
+        }.seek(activity)
+        return
+    }
+    JRouter.prepare().create(path).withTransition(R.anim.push_left_in, R.anim.push_left_out).then { postcard ->
+        _block?.invoke(postcard)
+    }.seek(activity)
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:51
+ * @Note   跳转页面 V7 Fragment扩展方法
+ * @param  _block 更多操作
+ * @param  path Activity注册到JRouter中的路径
+ */
+fun Fragment.push(path: String, _block: ((Postcard) -> Unit)? = null , isNeedLogin :Boolean = false) {
+    if (isNeedLogin){
+        JRouter.prepare().create("/member/login/main").withTransition(R.anim.push_left_in, R.anim.push_left_out).then { postcard ->
+            _block?.invoke(postcard)
+        }.seek(activity)
+        return
+    }
+    JRouter.prepare().create(path).withTransition(R.anim.push_left_in, R.anim.push_left_out).then { postcard ->
+        _block?.invoke(postcard)
+    }.seek(activity)
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:53
+ * @Note   Activity 退出扩展方法
+ */
+fun AppCompatActivity.pop() {
+    finish()
+    overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out)
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午4:53
+ * @Note   用于代码规范化 有助于代码美观 一般用于配置对象时对代码格式化
+ *         示例: val linearLayout = LinearLayout(context).then {
+ *                  lay ->
+ *                  lay.orientation = LinearLayout.HORIZONTAL
+ *                  lay.setBackgroundColor(Color.RED)
+ *              }.removeAllViews()
+ * @param  _block 回调
+ */
+inline fun <T : Any> T.then(_block: (T) -> Unit): T {
+    _block.invoke(this)
+    return this
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午5:04
+ * @Note   用于代码格式化 与then不同的是 该方法不继续传递self 一般用于格式化对象初始化代码
+ *         示例: val view = View(context).more {
+ *                  self ->
+ *                  self.setBackgroundColor(Color.BLUE)
+ *                  self.setFadingEdgeLength(1)
+ *                  self.setOnClickListener{}
+ *              }
+ * @param  _block 回调
+ */
+inline fun <T : Any> T.more(_block: (T) -> Unit) {
+    _block.invoke(this)
+}
+
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午5:10
+ * @Note   获取事件序列中心
+ * @return RxBus事件中心
+ */
+fun getEventCenter(): RxBus {
+    return RxBus.getDefault()
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午5:13
+ * @Note   当变量为空时执行
+ * @param  _block 回调
+ */
+inline fun Any?.haventDo(_block: () -> Unit) {
+    if (this == null) {
+        _block.invoke()
+        return
+    } else if (this is String) {
+        if (this == "") {
+            _block.invoke()
+        }
+    }
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午5:15
+ * @Note   当一个序列 都为空时 执行该回调
+ * @param  array 需要判断空的序列
+ * @param  _block 回调
+ */
+inline fun haventDo(vararg array: Any?, _block: () -> Unit) {
+    var has = false
+    for (any in array) {
+        if (any != null) {
+            has = true
+            if (any is String) {
+                if (any == "") {
+                    has = false
+                }
+            }
+        } else {
+            has = false
+        }
+    }
+    if (!has) {
+        _block.invoke()
+    }
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午5:13
+ * @Note   当变量不为空时执行
+ * @param  _block 回调
+ */
+inline fun Any?.haveDo(_block: () -> Unit) {
+    if (this != null) {
+        if (this is String) {
+            if (this == "") {
+                return
+            }
+        }
+        _block.invoke()
+    }
+}
+
+/**
+ * @author  LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Data   2017/12/22 下午5:15
+ * @Note   当一个序列 都不为空时 执行该回调
+ * @param  array 需要判断空的序列
+ * @param  _block 回调
+ */
+inline fun haveDo(vararg array: Any?, _block: () -> Unit) {
+    var has = true
+    for (any in array) {
+        if (any == null) {
+            has = false
+        } else if (any is String) {
+            if (any == "") {
+                has = false
+            }
+        }
+    }
+    if (has) {
+        _block.invoke()
+    }
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/1/19 下午3:46
+ * @Note   通过context获取颜色
+ * @param  rid  颜色索引ID
+ */
+fun Context.getColorCompatible(rid: Int): Int {
+    return ContextCompat.getColor(this, rid)
+}
+
+/**
+ * @author LDD
+ * @Date   2018/1/19 下午3:51
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Note   非入侵式,setOnScrollListener兼容低版本实现
+ * @param  call 滑动回调
+ */
+inline fun View.setOnScrollObserver(crossinline call: (scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) -> (Unit)) {
+    var oldScrollX = 0
+    var oldScrollY = 0
+    this.viewTreeObserver.addOnScrollChangedListener {
+        call.invoke(scrollX, scrollY, oldScrollX, oldScrollY)
+        oldScrollX = scrollX
+        oldScrollY = scrollY
+    }
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/1/29 下午4:00
+ * @Note   快速判断语法糖
+ * @param  trueDo  为true时调用
+ * @param  falseDo 为false时调用
+ */
+fun Boolean.judge(trueDo: (() -> (Unit))? = null, falseDo: (() -> (Unit))? = null) {
+    if (this) {
+        trueDo?.invoke()
+    } else {
+        falseDo?.invoke()
+    }
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/1/31 下午2:25
+ * @Note   快速判断语法糖
+ * @param  trueValue  为true时抛出
+ * @param  falseValue 为false时抛出
+ */
+fun <T> Boolean.judge(trueValue: T, falseValue: T): T {
+    return if (this) {
+        trueValue
+    } else {
+        falseValue
+    }
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/3/12 下午4:24
+ * @Note   快速重新定义LayoutParams重新布局
+ * @param  layout 重新布局回调
+ */
+inline fun <T : ViewGroup.LayoutParams> View.reLayout(layout: ((params: T) -> (Unit))) {
+    var params = (this.layoutParams as T)
+    layout(params)
+    this.layoutParams = params
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/3/13 上午11:09
+ * @Note   顺序执行补间动画 且可拦截
+ * @param  animList 动画列表
+ * @param  interceptor 拦截器
+ */
+fun View.animSequentialStart(animList: ArrayList<Animation>, interceptor: ((index: Int, state: Int) -> (Boolean))? = null) {
+
+    var index = 0
+
+    var listener = object : Animation.AnimationListener {
+        override fun onAnimationRepeat(animation: Animation?) {
+            val flag = interceptor?.invoke(index, 1)
+            flag?.judge(trueDo = {
+                animation?.cancel()
+            })
+        }
+
+        override fun onAnimationEnd(animation: Animation?) {
+            if (index != animList.size - 1) {
+                animList[index].cancel()
+            }
+            val flag = interceptor?.invoke(index, 2)
+            index += 1
+            flag?.judge(trueDo = {
+                animation?.cancel()
+            }, falseDo = {
+                if (index < animList.size) {
+                    animList[index].setAnimationListener(this)
+                    startAnimation(animList[index])
+                }
+            })
+        }
+
+        override fun onAnimationStart(animation: Animation?) {
+            val flag = interceptor?.invoke(index, 3)
+            flag?.judge(trueDo = {
+                animation?.cancel()
+            })
+        }
+    }
+    animList[index].setAnimationListener(listener)
+    startAnimation(animList[index])
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/3/15 下午3:57
+ * @Note   根据标记查找Adapter
+ * @param  tag 标记
+ */
+fun <T : BaseDelegateAdapter<*, *>> ArrayList<DelegateAdapter.Adapter<*>>.getAdapterByTag(tag: Any): T? {
+    this.forEach { item ->
+        if (item is BaseDelegateAdapter<*, *>) {
+            if (item.tag == tag) {
+                return item as T
+            }
+        }
+    }
+    return null
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/3/15 下午3:58
+ * @Note   根据标记移除Adapter
+ * @param  tag 标记
+ */
+fun <T : BaseDelegateAdapter<*, *>> ArrayList<DelegateAdapter.Adapter<*>>.removeAdapterByTag(tag: Any) {
+    remove(getAdapterByTag<T>(tag) as DelegateAdapter.Adapter<*>)
+}
+
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/3/15 下午4:25
+ * @Note   Vlayout获取屏幕上可见第一个Item的位置
+ */
+fun VirtualLayoutManager.getScollYDistance(): Int {
+    val position = findFirstVisibleItemPosition()
+    val firstVisiableChildView = findViewByPosition(position)
+    val itemHeight = firstVisiableChildView?.height
+    return position * (itemHeight ?: 0) - (firstVisiableChildView?.top ?: 0)
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/3/21 上午9:55
+ * @Note   转换弱引用
+ */
+fun <T : Any> T.weak(): WeakReference<T> {
+    return WeakReference(this)
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/4/12 上午8:56
+ * @Note   加入管理器
+ * @param  manager 管理器
+ */
+fun Disposable.joinManager(manager: DisposableManager) {
+    manager.addDisposable(this)
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/4/19 下午2:50
+ * @Note   dp转px
+ */
+fun Int.dpToPx(): Int {
+    return ScreenTool.dip2px(BaseApplication.appContext, this.toFloat())
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/4/19 下午2:50
+ * @Note   px转dp
+ */
+fun Int.pxToDp(): Int {
+    return ScreenTool.px2dip(BaseApplication.appContext, this.toFloat())
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/4/19 下午2:50
+ * @Note   dp转px
+ */
+fun Double.dpToPx(): Int {
+    return ScreenTool.dip2px(BaseApplication.appContext, this.toFloat())
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/4/19 下午2:50
+ * @Note   px转dp
+ */
+fun Double.pxToDp(): Int {
+    return ScreenTool.px2dip(BaseApplication.appContext, this.toFloat())
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/5/29 上午10:01
+ * @Note   获取对象
+ * @param  key
+ * @param  cls class对象
+ */
+fun <T> Intent.getObjectForGson(key: String, cls: Class<T>): T? {
+    return if (hasExtra(key)) {
+        val json = getStringExtra(key)
+        try {
+            JsonTranforHelper.toObject(json, cls)
+        } catch (e: Exception) {
+            null
+        }
+    } else {
+        null
+    }
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/5/29 上午10:03
+ * @Note   设置对象根据Gson
+ * @param  key 索引
+ * @param  value 值
+ */
+fun Intent.setObjectForGson(key: String, value: Any) {
+    putExtra(key, JsonTranforHelper.toJson(value))
+
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/5/29 下午4:13
+ * @Note   快速转换databinding字段
+ */
+fun <T> T.bindingParams(): ObservableField<T> {
+    return ObservableField(this)
+}
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.lib.utils ExtendMethods.kt
+ * @Date   2018/8/13 上午10:13
+ * @Note   以流的方式获取Json的字符串
+ */
+fun ResponseBody.getJsonString() : String{
+    source().request(Long.MAX_VALUE)
+    val buffer = source().buffer()
+    return buffer.clone().readString(Charset.forName("UTF-8"))
+}
+
+fun ResponseBody.toJsonObject() :JSONObject{
+    val jsonString = getJsonString()
+    return if (jsonString.isEmpty()){
+        JSONObject()
+    }else{
+        JSONObject(jsonString)
+    }
+}
+
+fun ResponseBody.toJsonArray() :JSONArray{
+    val jsonString = getJsonString()
+    return if (jsonString.isEmpty()){
+        JSONArray()
+    }else{
+        JSONArray(jsonString)
+    }
+}
+
+
+/** 参数获取扩展方法 防止空值 */
+
+fun JSONObject.valueString(key: String) :String{
+    return if (has(key) &&  !isNull(key)){
+        getString(key)
+    }else{
+        ""
+    }}
+
+fun JSONObject.valueInt(key :String) :Int{
+    return if (has(key) &&  !isNull(key)){
+        getInt(key)
+    }else{
+        -1
+    }}
+
+fun JSONObject.valueBool(key: String) :Boolean{
+    return if (has(key) &&  !isNull(key)){
+        getBoolean(key)
+    }else{
+        false
+    }}
+
+fun JSONObject.valueDouble(key: String) :Double{
+    return if (has(key) &&  !isNull(key)){
+        getDouble(key)
+    }else{
+        -1.0
+    }
+}
+
+fun JSONObject.valueDate(key:String) :String{
+    return if(has(key) && !isNull(key)){
+        CommonTool.toString(Date(valueLong(key)*1000),null)
+    }else{
+        ""
+    }
+}
+
+fun JSONObject.valueLong(key: String) :Long{
+    return if (has(key) &&  !isNull(key)){
+        getLong(key)
+    }else{
+        -1
+    }
+}
+
+fun JSONObject.valueJsonObject(key :String) :JSONObject{
+    return if (has(key) &&  !isNull(key)){
+        getJSONObject(key)
+    }else{
+        JSONObject()
+    }
+}
+
+fun JSONObject.valueJsonArray(key :String) :JSONArray{
+    return if (has(key) &&  !isNull(key)){
+        getJSONArray(key)
+    }else{
+        JSONArray()
+    }
+}
+
+fun JSONArray.arrayObjects() : ArrayList<JSONObject>{
+
+    var result = ArrayList<JSONObject>()
+
+    for (i in 0..(this.length() - 1)){
+        result.add(getJSONObject(i))
+    }
+
+    return  result
+
+}
+
+/**=================================================*/
+
+fun View.visable(){
+    this.visibility = View.VISIBLE
+}
+
+fun View.gone(){
+    this.visibility = View.GONE
+}
+
+fun View.invisable(){
+    this.visibility = View.INVISIBLE
+}

+ 314 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/GalleryHelper.kt

@@ -0,0 +1,314 @@
+package com.enation.javashop.android.lib.utils
+
+import android.content.Context
+import android.media.Image
+import android.os.Handler
+import android.support.v4.view.PagerAdapter
+import android.support.v4.view.ViewPager
+import android.util.AttributeSet
+import android.util.SparseArray
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.enation.javashop.imagepluin.R
+import com.enation.javashop.imagepluin.utils.GlideUtils
+import java.lang.ref.WeakReference
+
+
+/**
+ * @author LDD
+ * @Date   2018/3/29 下午2:09
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   轮播辅助类
+ */
+class GalleryHelper<DataType> {
+
+    /**
+     * @Name  galleryList
+     * @Type  DataType  相册数据泛型
+     * @Note  相册数据
+     */
+    private lateinit var galleryList :ArrayList<DataType>
+
+    /**
+     * @Name  viewPager
+     * @Type  ViewPager弱引用
+     * @Note  ViewPager
+     */
+    private lateinit var viewPager :WeakReference<ViewPager>
+
+    /**
+     * @Name  autoScroll
+     * @Type  Boolean
+     * @Note  是否开启轮播
+     */
+    private var autoScroll = true
+
+    /**
+     * @Name  scrooIndex
+     * @Type  Int
+     * @Note  当前position
+     */
+    private var scrooIndex = 0
+
+    /**
+     * @Name  itemCallback
+     * @Type  block
+     * @Note  点击回调
+     */
+    private var itemCallback :((position :Int , imageView :ImageView) ->Unit)? = null
+
+    /**
+     * @Name  itemCallback
+     * @Type  block
+     * @Note  点击回调
+     */
+    private var itemCallback2 :((position :Int , imageView :ImageView , imageViews : SparseArray<ImageView>) ->Unit)? = null
+
+    /**
+     * @Name  dataTransform
+     * @Type  block
+     * @Note  数据转换回调
+     */
+    private lateinit var dataTransform :((data :DataType) ->String)
+
+    /**
+     * @Name  handler
+     * @Type  Hander
+     * @Note  处理器
+     */
+    private val handler by lazy { Handler(Handler.Callback { msg ->
+        if (!autoScroll){
+            return@Callback false
+        }
+        if (scrooIndex >= galleryList.size){
+            scrooIndex = 0
+            viewPager.get()?.setCurrentItem(scrooIndex,false)
+        }else{
+            viewPager.get()?.currentItem = scrooIndex
+        }
+        if (autoScroll){
+            pageScroll()
+        }
+        return@Callback false
+    }) }
+
+    /**
+     * @Name  galleryAdapter
+     * @Type  PagerAdapter
+     * @Note  相册适配器
+     */
+    private val galleryAdapter by lazy {
+        object : PagerAdapter() {
+
+            private var images = SparseArray<ImageView>()
+
+            override fun isViewFromObject(view: View?, data: Any?): Boolean {
+                return view === data as View
+            }
+
+            override fun getCount(): Int {
+                return galleryList.size
+            }
+
+            override fun destroyItem(container: ViewGroup?, position: Int, view: Any?) {
+                images.remove(position)
+                container?.removeView(view as View)
+            }
+
+            override fun instantiateItem(container: ViewGroup?, position: Int): Any {
+                val imageView = SquareImageView(viewPager.get()?.context!!)
+                imageView.scaleType = ImageView.ScaleType.CENTER_CROP
+                Glide.with(viewPager.get()?.context)
+                        .load(dataTransform.invoke(galleryList[position]))
+                        .diskCacheStrategy(DiskCacheStrategy.ALL)
+                        .placeholder(R.drawable.image_loading)
+                        .error(R.drawable.image_error)
+                        .into(imageView)
+                itemCallback?.more { call -> imageView.setOnClickListener(OnClickListenerAntiViolence({
+                    call.invoke(position,imageView)
+                }))}
+                itemCallback2?.more { call -> imageView.setOnClickListener(OnClickListenerAntiViolence({
+                    call.invoke(position,imageView,images)
+                }))}
+                container?.addView(imageView, 0)
+                images.append(position,imageView)
+                return imageView
+            }
+        }
+    }
+
+    companion object {
+
+        /**
+         * @author LDD
+         * @From   GalleryHelper
+         * @Date   2018/3/29 下午2:39
+         * @Note   构建入口
+         * @param  viewPager ViewPager弱引用
+         */
+        fun <DataType>build(viewPager :WeakReference<ViewPager>):GalleryHelper<DataType>{
+            return GalleryHelper(viewPager)
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:40
+     * @Note   私有构造方法 防止外部直接实例化
+     * @param  viewPager ViewPager弱引用
+     */
+    private constructor(viewPager :WeakReference<ViewPager>){
+        this.viewPager = viewPager
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:40
+     * @Note   设置相册数据
+     * @param  galleryList 相册数据
+     */
+    fun setGallery(galleryList :ArrayList<DataType>):GalleryHelper<DataType>{
+        this.galleryList = galleryList
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:40
+     * @Note   设置item点击回调
+     * @param  itemCallback 点击回调
+     */
+    fun setItemCallBack(itemCallback :((position :Int, imageView :ImageView) ->Unit)):GalleryHelper<DataType>{
+        this.itemCallback = itemCallback
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:40
+     * @Note   设置item点击回调
+     * @param  itemCallback 点击回调
+     */
+    fun setItemCallBack(itemCallback :((position :Int, imageView :ImageView,imageViews : SparseArray<ImageView>) ->Unit)):GalleryHelper<DataType>{
+        this.itemCallback2 = itemCallback
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:41
+     * @Note   设置滑动回调
+     * @param  scrollCallBack 滑动回调
+     */
+    fun setScrollCallBack(scrollCallBack :((position :Int) ->Unit)):GalleryHelper<DataType>{
+        scrollCallBack.invoke(0)
+        viewPager.get()?.addOnPageChangeListener(object :ViewPager.OnPageChangeListener{
+            override fun onPageScrollStateChanged(state: Int) {
+
+            }
+
+            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
+
+            }
+
+            override fun onPageSelected(position: Int) {
+                initPageScroll()
+                scrollCallBack.invoke(position)
+            }
+        })
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:41
+     * @Note   设置数据转换器
+     * @param  dataTransform 数据转换器
+     */
+    fun setDataTransform(dataTransform :((data :DataType) ->String)):GalleryHelper<DataType>{
+        this.dataTransform = dataTransform
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:43
+     * @Note   开启自动轮播
+     * @param  context
+     */
+    fun autoScroll():GalleryHelper<DataType>{
+        autoScroll = true
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:47
+     * @Note   执行
+     */
+    fun execute(){
+        this.viewPager.get()?.adapter = galleryAdapter
+        if (autoScroll){
+            pageScroll()
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:51
+     * @Note   关闭滑动
+     */
+    fun offAutoScroll(){
+        autoScroll = false
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:52
+     * @Note   自动滑动
+     */
+    private fun pageScroll(){
+        initPageScroll()
+        handler.postDelayed({
+            handler.sendEmptyMessage(scrooIndex)
+        },3000)
+    }
+
+    /**
+     * @author LDD
+     * @From   GalleryHelper
+     * @Date   2018/3/29 下午2:52
+     * @Note   初始化滑动坐标
+     */
+    private fun initPageScroll(){
+        scrooIndex = viewPager.get()?.currentItem!! + 1
+    }
+
+}
+
+class SquareImageView: ImageView {
+
+    constructor(context: Context) : this(context,null)
+
+    constructor(context :Context,attrs : AttributeSet?) : super(context,attrs)
+
+    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
+
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        val widthSize = View.MeasureSpec.getSize(widthMeasureSpec)
+        setMeasuredDimension(widthSize, widthSize)
+    }
+}

+ 31 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/ImageWatchLoader.kt

@@ -0,0 +1,31 @@
+package com.enation.javashop.android.lib.utils
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.net.Uri
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.resource.drawable.GlideDrawable
+import com.bumptech.glide.request.RequestListener
+import com.enation.javashop.net.engine.utils.ThreadFromUtils
+import com.enation.javashop.net.engine.utils.ThreadUtils
+import com.github.ielse.imagewatcher.ImageWatcher
+import com.tmall.wireless.tangram.util.ImageUtils
+
+class ImageWatchLoader : ImageWatcher.Loader{
+    override fun load(p0: Context, p1: Uri, call: ImageWatcher.LoadCallback) {
+        call.onLoadStarted(null)
+        Glide.with(p0).load(p1).listener(object : RequestListener<Uri, GlideDrawable> {
+            override fun onException(p0: Exception, p1: Uri, p2:         com.bumptech.glide.request.target.Target
+            <GlideDrawable>, p3: Boolean): Boolean {
+                call.onLoadFailed(null)
+                return true
+            }
+
+            override fun onResourceReady(p0: GlideDrawable, p1: Uri, p2:         com.bumptech.glide.request.target.Target
+            <GlideDrawable>, p3: Boolean, p4: Boolean): Boolean {
+               call.onResourceReady(p0)
+                return true
+            }
+        }).into(1000,1000)
+    }
+}

+ 45 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/JsonTranforHelper.kt

@@ -0,0 +1,45 @@
+package com.enation.javashop.android.lib.utils
+
+import android.util.Log
+import com.google.gson.Gson
+
+/**
+ * @author LDD
+ * @Date   2018/5/8 上午11:51
+ * @From   com.enation.javashop.android.middleware.router
+ * @Note   Json转换辅助类
+ */
+object JsonTranforHelper {
+
+    /**
+     * @Name  com.enation.javashop.android.lib.utils.JsonTranforHelper.gson
+     * @Type  Gson
+     * @Note  静态Gson单例
+     */
+    @JvmStatic
+    private val gson = Gson()
+
+    /**
+     * @author LDD
+     * @From   JsonTranforHelper
+     * @Date   2018/5/8 上午11:53
+     * @Note   对象转Json
+     * @param  instance 对象
+     */
+    fun toJson(instance: Any): String {
+        return gson.toJson(instance)
+    }
+
+    /**
+     * @author LDD
+     * @From   JsonTranforHelper
+     * @Date   2018/5/8 上午11:53
+     * @Note   Json转对象
+     * @param  json json字符
+     * @param  cls  需要转换的对象的class
+     */
+    fun <T> toObject(json: String, cls: Class<T>): T {
+        return gson.fromJson(json, cls)
+    }
+
+}

+ 47 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/MD5Util.kt

@@ -0,0 +1,47 @@
+package com.enation.javashop.android.lib.utils
+
+import java.security.MessageDigest
+
+/**
+ *  Md5加密
+ */
+object MD5Util {
+
+
+    private val hexDigits = arrayOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f")
+
+    private fun byteArrayToHexString(b: ByteArray): String {
+        val resultSb = StringBuffer()
+        for (i in b.indices)
+            resultSb.append(byteToHexString(b[i]))
+
+        return resultSb.toString()
+    }
+
+    private fun byteToHexString(b: Byte): String {
+        var n = b.toInt()
+        if (n < 0)
+            n += 256
+        val d1 = n / 16
+        val d2 = n % 16
+        return hexDigits[d1] + hexDigits[d2]
+    }
+
+    fun MD5Encode(origin: String, charsetname: String?): String? {
+        var resultString: String? = null
+        try {
+            resultString = origin
+            val md = MessageDigest.getInstance("MD5")
+            if (charsetname == null || "" == charsetname)
+                resultString = byteArrayToHexString(md.digest(resultString!!
+                        .toByteArray()))
+            else
+                resultString = byteArrayToHexString(md.digest(resultString!!
+                        .toByteArray(charset(charsetname))))
+        } catch (exception: Exception) {
+        }
+
+        return resultString
+    }
+
+}

+ 51 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/NetReceiver.kt

@@ -0,0 +1,51 @@
+package com.enation.javashop.android.lib.utils
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.net.ConnectivityManager
+import com.enation.javashop.android.lib.vo.NetStateEvent
+import com.enation.javashop.net.engine.model.NetState
+import com.enation.javashop.net.engine.utils.VoiNetTool
+
+/**
+ * @author  LDD
+ * @Data   2017/12/22 下午5:19
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   监听网络变化的 广播接收者
+ */
+class NetReceiver : BroadcastReceiver() {
+
+    companion object {
+        private var lastType :VoiNetTool.netType? = null
+    }
+
+    override fun onReceive(p0: Context, p1: Intent) {
+        // 如果相等的话就说明网络状态发生了变化
+        if (p1.action == ConnectivityManager.CONNECTIVITY_ACTION) {
+            val netWorkState  = VoiNetTool.getAPNType(p0)
+            if (lastType != null){
+                if (lastType != netWorkState){
+                    postEvent(netWorkState)
+                }
+            }else{
+                postEvent(netWorkState)
+            }
+        }
+    }
+
+    private fun postEvent(netType :VoiNetTool.netType){
+        lastType = netType
+        when (netType) {
+            VoiNetTool.netType.noneNet -> {
+                getEventCenter().post(NetStateEvent(NetState.NONE))
+            }
+            VoiNetTool.netType.wifi -> {
+                getEventCenter().post(NetStateEvent(NetState.WIFI))
+            }
+            else -> {
+                getEventCenter().post(NetStateEvent(NetState.MOBILE))
+            }
+        }
+    }
+}

+ 614 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/NoAlphaItemAnimator.kt

@@ -0,0 +1,614 @@
+package com.enation.javashop.android.lib.utils
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.TimeInterpolator
+import android.animation.ValueAnimator
+import android.support.v4.view.ViewCompat
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.SimpleItemAnimator
+import java.util.ArrayList
+
+/**
+ * @author LDD
+ * @Date   2018/3/21 上午8:59
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   ...
+ */
+class NoAlphaItemAnimator : SimpleItemAnimator() {
+    private val DEBUG = false
+
+    private var sDefaultInterpolator: TimeInterpolator? = null
+
+    private val mPendingRemovals = ArrayList<RecyclerView.ViewHolder>()
+    private val mPendingAdditions = ArrayList<RecyclerView.ViewHolder>()
+    private val mPendingMoves = ArrayList<MoveInfo>()
+    private val mPendingChanges = ArrayList<ChangeInfo>()
+
+    internal var mAdditionsList = ArrayList<ArrayList<RecyclerView.ViewHolder>>()
+    internal var mMovesList = ArrayList<ArrayList<MoveInfo>>()
+    internal var mChangesList = ArrayList<ArrayList<ChangeInfo>>()
+
+    internal var mAddAnimations = ArrayList<RecyclerView.ViewHolder>()
+    internal var mMoveAnimations = ArrayList<RecyclerView.ViewHolder>()
+    internal var mRemoveAnimations = ArrayList<RecyclerView.ViewHolder>()
+    internal var mChangeAnimations = ArrayList<RecyclerView.ViewHolder>()
+
+    class MoveInfo internal constructor(var holder: RecyclerView.ViewHolder, var fromX: Int, var fromY: Int, var toX: Int, var toY: Int)
+
+    class ChangeInfo private constructor(var oldHolder: RecyclerView.ViewHolder?, var newHolder: RecyclerView.ViewHolder?) {
+        var fromX: Int = 0
+        var fromY: Int = 0
+        var toX: Int = 0
+        var toY: Int = 0
+
+        internal constructor(oldHolder: RecyclerView.ViewHolder, newHolder: RecyclerView.ViewHolder,
+                             fromX: Int, fromY: Int, toX: Int, toY: Int) : this(oldHolder, newHolder) {
+            this.fromX = fromX
+            this.fromY = fromY
+            this.toX = toX
+            this.toY = toY
+        }
+
+        override fun toString(): String {
+            return ("ChangeInfo{"
+                    + "oldHolder=" + oldHolder
+                    + ", newHolder=" + newHolder
+                    + ", fromX=" + fromX
+                    + ", fromY=" + fromY
+                    + ", toX=" + toX
+                    + ", toY=" + toY
+                    + '}'.toString())
+        }
+    }
+
+    override fun runPendingAnimations() {
+        val removalsPending = !mPendingRemovals.isEmpty()
+        val movesPending = !mPendingMoves.isEmpty()
+        val changesPending = !mPendingChanges.isEmpty()
+        val additionsPending = !mPendingAdditions.isEmpty()
+        if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
+            // nothing to animate
+            return
+        }
+        // First, remove stuff
+        for (holder in mPendingRemovals) {
+            animateRemoveImpl(holder)
+        }
+        mPendingRemovals.clear()
+        // Next, move stuff
+        if (movesPending) {
+            val moves = ArrayList<MoveInfo>()
+            moves.addAll(mPendingMoves)
+            mMovesList.add(moves)
+            mPendingMoves.clear()
+            val mover = Runnable {
+                for (moveInfo in moves) {
+                    animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
+                            moveInfo.toX, moveInfo.toY)
+                }
+                moves.clear()
+                mMovesList.remove(moves)
+            }
+            if (removalsPending) {
+                val view = moves[0].holder.itemView
+                ViewCompat.postOnAnimationDelayed(view, mover, removeDuration)
+            } else {
+                mover.run()
+            }
+        }
+        // Next, change stuff, to run in parallel with move animations
+        if (changesPending) {
+            val changes = ArrayList<ChangeInfo>()
+            changes.addAll(mPendingChanges)
+            mChangesList.add(changes)
+            mPendingChanges.clear()
+            val changer = Runnable {
+                for (change in changes) {
+                    animateChangeImpl(change)
+                }
+                changes.clear()
+                mChangesList.remove(changes)
+            }
+            if (removalsPending) {
+                val holder = changes[0].oldHolder
+                ViewCompat.postOnAnimationDelayed(holder!!.itemView, changer, removeDuration)
+            } else {
+                changer.run()
+            }
+        }
+        // Next, add stuff
+        if (additionsPending) {
+            val additions = ArrayList<RecyclerView.ViewHolder>()
+            additions.addAll(mPendingAdditions)
+            mAdditionsList.add(additions)
+            mPendingAdditions.clear()
+            val adder = Runnable {
+                for (holder in additions) {
+                    animateAddImpl(holder)
+                }
+                additions.clear()
+                mAdditionsList.remove(additions)
+            }
+            if (removalsPending || movesPending || changesPending) {
+                val removeDuration = if (removalsPending) removeDuration else 0
+                val moveDuration = if (movesPending) moveDuration else 0
+                val changeDuration = if (changesPending) changeDuration else 0
+                val totalDelay = removeDuration + Math.max(moveDuration, changeDuration)
+                val view = additions[0].itemView
+                ViewCompat.postOnAnimationDelayed(view, adder, totalDelay)
+            } else {
+                adder.run()
+            }
+        }
+    }
+
+    override fun animateRemove(holder: RecyclerView.ViewHolder): Boolean {
+        resetAnimation(holder)
+        mPendingRemovals.add(holder)
+        return true
+    }
+
+    private fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
+        val view = holder.itemView
+        val animation = view.animate()
+        mRemoveAnimations.add(holder)
+        animation.setDuration(removeDuration).alpha(0f).setListener(
+                object : AnimatorListenerAdapter() {
+                    override fun onAnimationStart(animator: Animator) {
+                        dispatchRemoveStarting(holder)
+                    }
+
+                    override fun onAnimationEnd(animator: Animator) {
+                        animation.setListener(null)
+                        view.alpha = 1f
+                        dispatchRemoveFinished(holder)
+                        mRemoveAnimations.remove(holder)
+                        dispatchFinishedWhenDone()
+                    }
+                }).start()
+    }
+
+    override fun animateAdd(holder: RecyclerView.ViewHolder): Boolean {
+        resetAnimation(holder)
+        mPendingAdditions.add(holder)
+        return true
+    }
+
+    /**
+     * 关闭默认局部刷新动画
+     */
+    fun closeDefaultAnimator() :NoAlphaItemAnimator {
+        addDuration = 0
+        changeDuration = 0
+        moveDuration = 0
+        removeDuration = 0
+        (this as SimpleItemAnimator).supportsChangeAnimations = false
+        return this
+    }
+
+    internal fun animateAddImpl(holder: RecyclerView.ViewHolder) {
+        val view = holder.itemView
+        val animation = view.animate()
+        mAddAnimations.add(holder)
+        animation.setDuration(addDuration)
+                .setListener(object : AnimatorListenerAdapter() {
+                    override fun onAnimationStart(animator: Animator) {
+                        dispatchAddStarting(holder)
+                    }
+
+                    override fun onAnimationCancel(animator: Animator) {
+
+                    }
+
+                    override fun onAnimationEnd(animator: Animator) {
+                        animation.setListener(null)
+                        dispatchAddFinished(holder)
+                        mAddAnimations.remove(holder)
+                        dispatchFinishedWhenDone()
+                    }
+                }).start()
+    }
+
+    override fun animateMove(holder: RecyclerView.ViewHolder, fromX: Int, fromY: Int,
+                             toX: Int, toY: Int): Boolean {
+        var fromX = fromX
+        var fromY = fromY
+        val view = holder.itemView
+        fromX += holder.itemView.translationX.toInt()
+        fromY += holder.itemView.translationY.toInt()
+        resetAnimation(holder)
+        val deltaX = toX - fromX
+        val deltaY = toY - fromY
+        if (deltaX == 0 && deltaY == 0) {
+            dispatchMoveFinished(holder)
+            return false
+        }
+        if (deltaX != 0) {
+            view.translationX = (-deltaX).toFloat()
+        }
+        if (deltaY != 0) {
+            view.translationY = (-deltaY).toFloat()
+        }
+        mPendingMoves.add(MoveInfo(holder, fromX, fromY, toX, toY))
+        return true
+    }
+
+    internal fun animateMoveImpl(holder: RecyclerView.ViewHolder, fromX: Int, fromY: Int, toX: Int, toY: Int) {
+        val view = holder.itemView
+        val deltaX = toX - fromX
+        val deltaY = toY - fromY
+        if (deltaX != 0) {
+            view.animate().translationX(0f)
+        }
+        if (deltaY != 0) {
+            view.animate().translationY(0f)
+        }
+        // TODO: make EndActions end listeners instead, since end actions aren't called when
+        // vpas are canceled (and can't end them. why?)
+        // need listener functionality in VPACompat for this. Ick.
+        val animation = view.animate()
+        mMoveAnimations.add(holder)
+        animation.setDuration(moveDuration).setListener(object : AnimatorListenerAdapter() {
+            override fun onAnimationStart(animator: Animator) {
+                dispatchMoveStarting(holder)
+            }
+
+            override fun onAnimationCancel(animator: Animator) {
+                if (deltaX != 0) {
+                    view.translationX = 0f
+                }
+                if (deltaY != 0) {
+                    view.translationY = 0f
+                }
+            }
+
+            override fun onAnimationEnd(animator: Animator) {
+                animation.setListener(null)
+                dispatchMoveFinished(holder)
+                mMoveAnimations.remove(holder)
+                dispatchFinishedWhenDone()
+            }
+        }).start()
+    }
+
+    override fun animateChange(oldHolder: RecyclerView.ViewHolder, newHolder: RecyclerView.ViewHolder?,
+                               fromX: Int, fromY: Int, toX: Int, toY: Int): Boolean {
+        if (oldHolder === newHolder) {
+            // Don't know how to run change animations when the same view holder is re-used.
+            // run a move animation to handle position changes.
+            return animateMove(oldHolder, fromX, fromY, toX, toY)
+        }
+        val prevTranslationX = oldHolder.itemView.translationX
+        val prevTranslationY = oldHolder.itemView.translationY
+        val prevAlpha = oldHolder.itemView.alpha
+        resetAnimation(oldHolder)
+        val deltaX = (toX.toFloat() - fromX.toFloat() - prevTranslationX).toInt()
+        val deltaY = (toY.toFloat() - fromY.toFloat() - prevTranslationY).toInt()
+        // recover prev translation state after ending animation
+        oldHolder.itemView.translationX = prevTranslationX
+        oldHolder.itemView.translationY = prevTranslationY
+        oldHolder.itemView.alpha = prevAlpha
+        if (newHolder != null) {
+            // carry over translation values
+            resetAnimation(newHolder)
+            newHolder.itemView.translationX = (-deltaX).toFloat()
+            newHolder.itemView.translationY = (-deltaY).toFloat()
+            newHolder.itemView.alpha = 0f
+        }
+        mPendingChanges.add(ChangeInfo(oldHolder, newHolder!!, fromX, fromY, toX, toY))
+        return true
+    }
+
+    internal fun animateChangeImpl(changeInfo: ChangeInfo) {
+        val holder = changeInfo.oldHolder
+        val view = holder?.itemView
+        val newHolder = changeInfo.newHolder
+        val newView = newHolder?.itemView
+        if (view != null) {
+            val oldViewAnim = view.animate().setDuration(
+                    changeDuration)
+            mChangeAnimations.add(changeInfo.oldHolder!!)
+            oldViewAnim.translationX((changeInfo.toX - changeInfo.fromX).toFloat())
+            oldViewAnim.translationY((changeInfo.toY - changeInfo.fromY).toFloat())
+            oldViewAnim.setListener(object : AnimatorListenerAdapter() {
+                override fun onAnimationStart(animator: Animator) {
+                    dispatchChangeStarting(changeInfo.oldHolder, true)
+                }
+
+                override fun onAnimationEnd(animator: Animator) {
+                    oldViewAnim.setListener(null)
+                    view.alpha = 1f
+                    view.translationX = 0f
+                    view.translationY = 0f
+                    dispatchChangeFinished(changeInfo.oldHolder, true)
+                    mChangeAnimations.remove(changeInfo.oldHolder!!)
+                    dispatchFinishedWhenDone()
+                }
+            }).start()
+        }
+        if (newView != null) {
+            val newViewAnimation = newView.animate()
+            mChangeAnimations.add(changeInfo.newHolder!!)
+            newViewAnimation.translationX(0f).translationY(0f).setDuration(changeDuration)
+                    .setListener(object : AnimatorListenerAdapter() {
+                        override fun onAnimationStart(animator: Animator) {
+                            dispatchChangeStarting(changeInfo.newHolder, false)
+                        }
+
+                        override fun onAnimationEnd(animator: Animator) {
+                            newViewAnimation.setListener(null)
+                            newView.alpha = 1f
+                            newView.translationX = 0f
+                            newView.translationY = 0f
+                            dispatchChangeFinished(changeInfo.newHolder, false)
+                            mChangeAnimations.remove(changeInfo.newHolder!!)
+                            dispatchFinishedWhenDone()
+                        }
+                    }).start()
+        }
+    }
+
+    private fun endChangeAnimation(infoList: MutableList<ChangeInfo>, item: RecyclerView.ViewHolder) {
+        for (i in infoList.indices.reversed()) {
+            val changeInfo = infoList[i]
+            if (endChangeAnimationIfNecessary(changeInfo, item)) {
+                if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
+                    infoList.remove(changeInfo)
+                }
+            }
+        }
+    }
+
+    private fun endChangeAnimationIfNecessary(changeInfo: ChangeInfo) {
+        if (changeInfo.oldHolder != null) {
+            endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder)
+        }
+        if (changeInfo.newHolder != null) {
+            endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder)
+        }
+    }
+
+    private fun endChangeAnimationIfNecessary(changeInfo: ChangeInfo, item: RecyclerView.ViewHolder?): Boolean {
+        var oldItem = false
+        if (changeInfo.newHolder === item) {
+            changeInfo.newHolder = null
+        } else if (changeInfo.oldHolder === item) {
+            changeInfo.oldHolder = null
+            oldItem = true
+        } else {
+            return false
+        }
+        item!!.itemView.alpha = 1f
+        item.itemView.translationX = 0f
+        item.itemView.translationY = 0f
+        dispatchChangeFinished(item, oldItem)
+        return true
+    }
+
+    override fun endAnimation(item: RecyclerView.ViewHolder) {
+        val view = item.itemView
+        // this will trigger end callback which should set properties to their target values.
+        view.animate().cancel()
+        // TODO if some other animations are chained to end, how do we cancel them as well?
+        for (i in mPendingMoves.indices.reversed()) {
+            val moveInfo = mPendingMoves[i]
+            if (moveInfo.holder === item) {
+                view.translationY = 0f
+                view.translationX = 0f
+                dispatchMoveFinished(item)
+                mPendingMoves.removeAt(i)
+            }
+        }
+        endChangeAnimation(mPendingChanges, item)
+        if (mPendingRemovals.remove(item)) {
+            view.alpha = 1f
+            dispatchRemoveFinished(item)
+        }
+        if (mPendingAdditions.remove(item)) {
+            view.alpha = 1f
+            dispatchAddFinished(item)
+        }
+
+        for (i in mChangesList.indices.reversed()) {
+            val changes = mChangesList[i]
+            endChangeAnimation(changes, item)
+            if (changes.isEmpty()) {
+                mChangesList.removeAt(i)
+            }
+        }
+        for (i in mMovesList.indices.reversed()) {
+            val moves = mMovesList[i]
+            for (j in moves.indices.reversed()) {
+                val moveInfo = moves[j]
+                if (moveInfo.holder === item) {
+                    view.translationY = 0f
+                    view.translationX = 0f
+                    dispatchMoveFinished(item)
+                    moves.removeAt(j)
+                    if (moves.isEmpty()) {
+                        mMovesList.removeAt(i)
+                    }
+                    break
+                }
+            }
+        }
+        for (i in mAdditionsList.indices.reversed()) {
+            val additions = mAdditionsList[i]
+            if (additions.remove(item)) {
+                view.alpha = 1f
+                dispatchAddFinished(item)
+                if (additions.isEmpty()) {
+                    mAdditionsList.removeAt(i)
+                }
+            }
+        }
+
+        // animations should be ended by the cancel above.
+        //noinspection PointlessBooleanExpression,ConstantConditions
+        if (mRemoveAnimations.remove(item) && DEBUG) {
+            throw IllegalStateException("after animation is cancelled, item should not be in " + "mRemoveAnimations list")
+        }
+
+        //noinspection PointlessBooleanExpression,ConstantConditions
+        if (mAddAnimations.remove(item) && DEBUG) {
+            throw IllegalStateException("after animation is cancelled, item should not be in " + "mAddAnimations list")
+        }
+
+        //noinspection PointlessBooleanExpression,ConstantConditions
+        if (mChangeAnimations.remove(item) && DEBUG) {
+            throw IllegalStateException("after animation is cancelled, item should not be in " + "mChangeAnimations list")
+        }
+
+        //noinspection PointlessBooleanExpression,ConstantConditions
+        if (mMoveAnimations.remove(item) && DEBUG) {
+            throw IllegalStateException("after animation is cancelled, item should not be in " + "mMoveAnimations list")
+        }
+        dispatchFinishedWhenDone()
+    }
+
+    private fun resetAnimation(holder: RecyclerView.ViewHolder) {
+        if (sDefaultInterpolator == null) {
+            sDefaultInterpolator = ValueAnimator().interpolator
+        }
+        holder.itemView.animate().interpolator = sDefaultInterpolator
+        endAnimation(holder)
+    }
+
+    override fun isRunning(): Boolean {
+        return (!mPendingAdditions.isEmpty()
+                || !mPendingChanges.isEmpty()
+                || !mPendingMoves.isEmpty()
+                || !mPendingRemovals.isEmpty()
+                || !mMoveAnimations.isEmpty()
+                || !mRemoveAnimations.isEmpty()
+                || !mAddAnimations.isEmpty()
+                || !mChangeAnimations.isEmpty()
+                || !mMovesList.isEmpty()
+                || !mAdditionsList.isEmpty()
+                || !mChangesList.isEmpty())
+    }
+
+    /**
+     * Check the state of currently pending and running animations. If there are none
+     * pending/running, call [.dispatchAnimationsFinished] to notify any
+     * listeners.
+     */
+    internal fun dispatchFinishedWhenDone() {
+        if (!isRunning) {
+            dispatchAnimationsFinished()
+        }
+    }
+
+    override fun endAnimations() {
+        var count = mPendingMoves.size
+        for (i in count - 1 downTo 0) {
+            val item = mPendingMoves[i]
+            val view = item.holder.itemView
+            view.translationY = 0f
+            view.translationX = 0f
+            dispatchMoveFinished(item.holder)
+            mPendingMoves.removeAt(i)
+        }
+        count = mPendingRemovals.size
+        for (i in count - 1 downTo 0) {
+            val item = mPendingRemovals[i]
+            dispatchRemoveFinished(item)
+            mPendingRemovals.removeAt(i)
+        }
+        count = mPendingAdditions.size
+        for (i in count - 1 downTo 0) {
+            val item = mPendingAdditions[i]
+            item.itemView.alpha = 1f
+            dispatchAddFinished(item)
+            mPendingAdditions.removeAt(i)
+        }
+        count = mPendingChanges.size
+        for (i in count - 1 downTo 0) {
+            endChangeAnimationIfNecessary(mPendingChanges[i])
+        }
+        mPendingChanges.clear()
+        if (!isRunning) {
+            return
+        }
+
+        var listCount = mMovesList.size
+        for (i in listCount - 1 downTo 0) {
+            val moves = mMovesList[i]
+            count = moves.size
+            for (j in count - 1 downTo 0) {
+                val moveInfo = moves[j]
+                val item = moveInfo.holder
+                val view = item.itemView
+                view.translationY = 0f
+                view.translationX = 0f
+                dispatchMoveFinished(moveInfo.holder)
+                moves.removeAt(j)
+                if (moves.isEmpty()) {
+                    mMovesList.remove(moves)
+                }
+            }
+        }
+        listCount = mAdditionsList.size
+        for (i in listCount - 1 downTo 0) {
+            val additions = mAdditionsList[i]
+            count = additions.size
+            for (j in count - 1 downTo 0) {
+                val item = additions[j]
+                val view = item.itemView
+                view.alpha = 1f
+                dispatchAddFinished(item)
+                additions.removeAt(j)
+                if (additions.isEmpty()) {
+                    mAdditionsList.remove(additions)
+                }
+            }
+        }
+        listCount = mChangesList.size
+        for (i in listCount - 1 downTo 0) {
+            val changes = mChangesList[i]
+            count = changes.size
+            for (j in count - 1 downTo 0) {
+                endChangeAnimationIfNecessary(changes[j])
+                if (changes.isEmpty()) {
+                    mChangesList.remove(changes)
+                }
+            }
+        }
+
+        cancelAll(mRemoveAnimations)
+        cancelAll(mMoveAnimations)
+        cancelAll(mAddAnimations)
+        cancelAll(mChangeAnimations)
+
+        dispatchAnimationsFinished()
+    }
+
+    internal fun cancelAll(viewHolders: List<RecyclerView.ViewHolder>) {
+        for (i in viewHolders.indices.reversed()) {
+            viewHolders[i].itemView.animate().cancel()
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     *
+     * If the payload list is not empty, DefaultItemAnimator returns `true`.
+     * When this is the case:
+     *
+     *  * If you override [.animateChange], both
+     * ViewHolder arguments will be the same instance.
+     *
+     *  *
+     * If you are not overriding [.animateChange],
+     * then DefaultItemAnimator will call [.animateMove] and
+     * run a move animation instead.
+     *
+     *
+     */
+    override fun canReuseUpdatedViewHolder(viewHolder: RecyclerView.ViewHolder,
+                                           payloads: List<Any>): Boolean {
+        return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads)
+    }
+}

+ 39 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/OnClickListenerAntiViolence.kt

@@ -0,0 +1,39 @@
+package com.enation.javashop.android.lib.utils
+
+import android.util.Log
+import android.view.View
+
+/**
+ * @author LDD
+ * @Data   2018/1/5 上午10:01
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note
+ */
+class OnClickListenerAntiViolence(val event:((view :View) -> Unit),val interval : Int = 1000) :View.OnClickListener {
+
+    /**
+     * @Name  time
+     * @Type  Long
+     * @Note  点击事件记录
+     */
+    private var time :Long = -12345678910
+
+
+    /**
+     * @author  LDD
+     * @From    OnClickListenerAntiViolence
+     * @Data   2018/1/5 上午10:04
+     * @Note   点击相应
+     * @param  view  所点击的View
+     */
+    override fun onClick(view: View) {
+
+        if (time == -12345678910){
+            time = System.currentTimeMillis()
+            event(view)
+        }else if (System.currentTimeMillis()-time > interval){
+            time = System.currentTimeMillis()
+            event(view)
+        }
+    }
+}

+ 57 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/OnItemClickListenerAntiViolence.kt

@@ -0,0 +1,57 @@
+package com.enation.javashop.android.lib.utils
+
+import android.view.View
+import android.widget.AdapterView
+
+/**
+ * @author  LDD
+ * @Data   2018/1/5 上午10:37
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   防暴力点击 ItemClickListener
+ */
+class OnItemClickListenerAntiViolence(val event :((adapterView: AdapterView<*>?, itemView: View?, position: Int, itemId: Long) -> Unit),val interval: Int = 1000) :AdapterView.OnItemClickListener {
+
+    /**
+     * @Name  time
+     * @Type  Long
+     * @Note  点击事件记录
+     */
+    private var time :Long = -12345678910
+
+    /**
+     * @Name  index
+     * @Type  Int
+     * @Note  点击下标记录
+     */
+    private var index :Int = -1
+
+    /**
+     * @author LDD
+     * @From   OnItemClickListenerAntiViolence
+     * @Data   2018/1/5 上午10:18
+     * @Note   Item点击事件
+     * @param  p0    列表视图
+     * @param  p1    所点击的视图
+     * @param  p2    position
+     * @param  p3    item ID
+     */
+    override fun onItemClick(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
+        if (index == p2){
+            if (time == -12345678910){
+                index = p2
+                event(p0,p1,p2,p3)
+                time = System.currentTimeMillis()
+            }else{
+                if (System.currentTimeMillis()-time >interval){
+                    index = p2
+                    event(p0,p1,p2,p3)
+                    time = System.currentTimeMillis()
+                }
+            }
+        }else{
+            index = p2
+            event(p0,p1,p2,p3)
+            time = System.currentTimeMillis()
+        }
+    }
+}

+ 338 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/RecycleViewScrollHelper.kt

@@ -0,0 +1,338 @@
+package com.enation.javashop.android.lib.utils
+
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.LinearLayoutManager
+
+
+/**
+ * @author LDD
+ * @Date   2018/3/15 下午3:59
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   RecycleView 滑动监听
+ */
+class RecycleViewScrollHelper
+/**
+ * recycleView的滑动监听事件,用于检测是否滑动到顶部或者滑动到底部.
+ *
+ * @param listener [OnScrollPositionChangedListener]滑动位置变动监听事件
+ */
+(listener: OnScrollPositionChangedListener) : RecyclerView.OnScrollListener() {
+    private var mRvScroll: RecyclerView? = null
+    private var mScrollDirectionChangedListener: OnScrollDirectionChangedListener? = null
+    //滑动位置变动的监听事件
+    private var mScrollPositionChangedListener: OnScrollPositionChangedListener? = null
+    //是否同时检测滑动到顶部及底部
+    private var mIsCheckTopBottomTogether = false
+    //检测滑动顶部/底部的优先顺序,默认先检测滑动到底部
+    private var mIsCheckTopFirstBottomAfter = false
+    //检测底部滑动时是否检测满屏状态
+    private var mIsCheckBottomFullRecycle = false
+    //检测顶部滑动时是否检测满屏状态
+    private var mIsCheckTopFullRecycle = false
+    //顶部满屏检测时允许的容差值
+    private var mTopOffsetFaultTolerance = 0
+    //底部满屏检测时允许的容差值
+    private var mBottomOffsetFaultTolerance = 0
+
+
+    private var mScrollDx = 0
+    private var mScrollDy = 0
+
+    init {
+        mScrollPositionChangedListener = listener
+    }
+
+    override fun onScrollStateChanged(recyclerView: RecyclerView?,
+                                      newState: Int) {
+        if (mScrollPositionChangedListener == null || recyclerView!!.adapter == null || recyclerView.childCount <= 0) {
+            return
+        }
+        val layoutManager = recyclerView.layoutManager
+        if (layoutManager is LinearLayoutManager) {
+            val lastItemPosition = layoutManager.findLastVisibleItemPosition()
+            val firstItemPosition = layoutManager.findFirstVisibleItemPosition()
+            val adapter = recyclerView.adapter
+            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+                //判断顶部/底部检测的优先顺序
+                if (!mIsCheckTopFirstBottomAfter) {
+                    //先检测底部
+                    if (this.checkIfScrollToBottom(recyclerView, lastItemPosition, adapter.itemCount)) {
+                        //若检测滑动到底部时,判断是否需要同时检测滑动到顶部
+                        if (mIsCheckTopBottomTogether) {
+                            //检测是否滑动到顶部
+                            this.checkIfScrollToTop(recyclerView, firstItemPosition)
+                            //不管是否滑动到顶部,已经触发了滑动到底部,所以直接返回,否则会调用滑动到未知位置的
+                            return
+                        } else {
+                            //若不需要同时检测,直接返回
+                            return
+                        }
+                    } else if (this.checkIfScrollToTop(recyclerView, firstItemPosition)) {
+                        //当未检测滑动到底部时,再检测是否滑动到顶部
+                        return
+                    }
+                } else {
+                    //先检测是否滑动到顶部
+                    if (this.checkIfScrollToTop(recyclerView, firstItemPosition)) {
+                        if (mIsCheckTopBottomTogether) {
+                            //检测是否滑动到底部
+                            this.checkIfScrollToBottom(recyclerView, lastItemPosition, adapter.itemCount)
+                            return
+                        } else {
+                            //若不需要同时检测,直接返回
+                            return
+                        }
+                    } else if (this.checkIfScrollToBottom(recyclerView, lastItemPosition, adapter.itemCount)) {
+                        //当未检测滑动到底部时,再检测是否滑动到底部
+                        return
+                    }
+                }
+            }
+        }
+        //其它任何情况
+        mScrollPositionChangedListener!!.onScrollToUnknown(false, false)
+    }
+
+    /**
+     * 检测是否滑动到了顶部item并回调事件
+     *
+     * @param recyclerView
+     * @param firstItemPosition 第一个可见itemView的position
+     * @return
+     */
+    private fun checkIfScrollToTop(recyclerView: RecyclerView, firstItemPosition: Int): Boolean {
+        if (firstItemPosition == 0) {
+            if (mIsCheckTopFullRecycle) {
+                val childCount = recyclerView.childCount
+                val firstChild = recyclerView.getChildAt(0)
+                val lastChild = recyclerView.getChildAt(childCount - 1)
+                val top = firstChild.top
+                val bottom = lastChild.bottom
+                //recycleView显示itemView的有效区域的top坐标Y
+                val topEdge = recyclerView.paddingTop - mTopOffsetFaultTolerance
+                //recycleView显示itemView的有效区域的bottom坐标Y
+                val bottomEdge = recyclerView.height - recyclerView.paddingBottom - mBottomOffsetFaultTolerance
+                //第一个view的顶部大于top边界值,说明第一个view已经完全显示在顶部
+                //同时最后一个view的底部应该小于bottom边界值,说明最后一个view的底部已经超出显示范围,部分或者完全移出了界面
+                if (top >= topEdge && bottom > bottomEdge) {
+                    mScrollPositionChangedListener!!.onScrollToTop()
+                    return true
+                } else {
+                    mScrollPositionChangedListener!!.onScrollToUnknown(true, false)
+                }
+            } else {
+                mScrollPositionChangedListener!!.onScrollToTop()
+                return true
+            }
+        }
+        return false
+    }
+
+    /**
+     * 检测是否滑动到底部item并回调事件
+     *
+     * @param recyclerView
+     * @param lastItemPosition 最后一个可见itemView的position
+     * @param itemCount        adapter的itemCount
+     * @return
+     */
+    private fun checkIfScrollToBottom(recyclerView: RecyclerView, lastItemPosition: Int, itemCount: Int): Boolean {
+        if (lastItemPosition + 1 == itemCount) {
+            //是否进行满屏的判断处理
+            //未满屏的情况下将永远不会被回调滑动到低部或者顶部
+            if (mIsCheckBottomFullRecycle) {
+                val childCount = recyclerView.childCount
+                //获取最后一个childView
+                val lastChildView = recyclerView.getChildAt(childCount - 1)
+                //获取第一个childView
+                val firstChildView = recyclerView.getChildAt(0)
+                val top = firstChildView.top
+                val bottom = lastChildView.bottom
+                //recycleView显示itemView的有效区域的bottom坐标Y
+                val bottomEdge = recyclerView.height - recyclerView.paddingBottom + mBottomOffsetFaultTolerance
+                //recycleView显示itemView的有效区域的top坐标Y
+                val topEdge = recyclerView.paddingTop + mTopOffsetFaultTolerance
+                //第一个view的顶部小于top边界值,说明第一个view已经部分或者完全移出了界面
+                //最后一个view的底部小于bottom边界值,说明最后一个view已经完全显示在界面
+                //若不处理这种情况,可能会存在recycleView高度足够高时,itemView数量很少无法填充一屏,但是滑动到最后一项时依然会发生回调
+                //此时其实并不需要任何刷新操作的
+                if (bottom <= bottomEdge && top < topEdge) {
+                    mScrollPositionChangedListener!!.onScrollToBottom()
+                    return true
+                } else {
+                    mScrollPositionChangedListener!!.onScrollToUnknown(false, true)
+                }
+            } else {
+                mScrollPositionChangedListener!!.onScrollToBottom()
+                return true
+            }
+        }
+        return false
+    }
+
+    override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
+        if (mScrollDirectionChangedListener != null) {
+            if (dx == 0 && dy == 0) {
+                mScrollDirectionChangedListener!!.onScrollDirectionChanged(0, 0)
+            } else if (dx == 0) {
+                val isUp = dy > 0
+                val isBeenUp = mScrollDy > 0
+                if (isUp != isBeenUp) {
+                    mScrollDx = dx
+                    mScrollDy = dy
+                    mScrollDirectionChangedListener!!.onScrollDirectionChanged(dx, dy)
+                }
+            } else if (dy == 0) {
+                val isLeft = dx > 0
+                val isBeenLeft = mScrollDx > 0
+                if (isLeft != isBeenLeft) {
+                    mScrollDx = dx
+                    mScrollDy = dy
+                    mScrollDirectionChangedListener!!.onScrollDirectionChanged(dx, dy)
+                }
+            }
+        }
+    }
+
+    //重置数据
+    private fun reset() {
+        mScrollDx = 0
+        mScrollDy = 0
+    }
+
+    /**
+     * 关联recycleView,当关联新的recycleView时,会自动移除上一个关联recycleView
+     *
+     * @param recyclerView
+     */
+    fun attachToRecycleView(recyclerView: RecyclerView?) {
+        if (recyclerView !== mRvScroll) {
+            unAttachToRecycleView()
+            mRvScroll = recyclerView
+            recyclerView?.addOnScrollListener(this)
+        }
+    }
+
+    /**
+     * 移除与recycleView的绑定
+     */
+    fun unAttachToRecycleView() {
+        if (mRvScroll != null) {
+            mRvScroll!!.removeOnScrollListener(this)
+        }
+        this.reset()
+    }
+
+    /**
+     * 设置滑动方向改变时的回调接口
+     *
+     * @param listener
+     */
+    fun setScrollDirectionChangedListener(listener: OnScrollDirectionChangedListener) {
+        mScrollDirectionChangedListener = listener
+    }
+
+    /**
+     * 设置顶部允许偏移的容差值,此值仅在允许检测满屏时有效,当[.setCheckIfItemViewFullRecycleViewForTop]设置为true 或者[.setCheckIfItemViewFullRecycleViewForBottom]设置为true 时有效.<br></br>
+     * 在检测底部滑动时,对顶部的检测会添加此容差值(更容易判断当前第一项childView已超出recycleView的显示范围),用于协助判断是否滑动到底部.
+     * 在检测顶部滑动时,对顶部的检测会添加此容差值(更容易判断为滑动到了顶部)
+     *
+     * @param offset 容差值,此值必须为0或正数
+     */
+    fun setTopOffsetFaultTolerance(offset: Int) {
+        mTopOffsetFaultTolerance = offset
+    }
+
+    /**
+     * 设置顶部允许偏移的容差值,此值仅在允许检测满屏时有效,当[.setCheckIfItemViewFullRecycleViewForTop]设置为true 或者[.setCheckIfItemViewFullRecycleViewForBottom]设置为true 时有效.<br></br>
+     * 在检测底部滑动时,对底部的检测会添加此容差值(更容易判断当前最后一项childView已超出recycleView的显示范围),用于协助判断是否滑动到顶部.
+     * 在检测顶部滑动时,对底部的检测会添加此容差值(更容易判断为滑动到了底部)
+     *
+     * @param offset 容差值,此值必须为0或正数
+     */
+    fun setBottomFaultTolerance(offset: Int) {
+        mBottomOffsetFaultTolerance = offset
+    }
+
+    /**
+     * 设置是否需要检测recycleView是否为满屏的itemView时才回调事件.<br></br>
+     *
+     *
+     * 当RecycleView的childView数量很少时,有可能RecycleView已经显示出所有的itemView,此时不存在向上滑动的可能.<br></br>
+     * 若设置当前值为true时,只有在RecycleView无法完全显示所有的itemView时,才会回调滑动到顶部的事件;否则将不处理;<br></br>
+     * 若设置为false则反之,不管任何时候只要滑动并顶部item显示时都会回调滑动事件
+     *
+     * @param isNeedToCheck true为当检测是否满屏显示;false不检测,直接回调事件
+     */
+    fun setCheckIfItemViewFullRecycleViewForTop(isNeedToCheck: Boolean) {
+        mIsCheckTopFullRecycle = isNeedToCheck
+    }
+
+    /**
+     * 设置是否需要检测recycleView是否为满屏的itemView时才回调事件.<br></br>
+     *
+     *
+     * 当RecycleView的childView数量很少时,有可能RecycleView已经显示o出所有的itemView,此时不存在向下滑动的可能.
+     * 若设置当前值为true时,只有在RecycleView无法完全显示所有的itemView时,才会回调滑动到底部的事件;否则将不处理;
+     * 若设置为false则反之,不管任何时候只要滑动到底部都会回调滑动事件
+     *
+     * @param isNeedToCheck true为当检测是否满屏显示;false不检测,直接回调事件
+     */
+    fun setCheckIfItemViewFullRecycleViewForBottom(isNeedToCheck: Boolean) {
+        mIsCheckBottomFullRecycle = isNeedToCheck
+    }
+
+    /**
+     * 设置是否先检测滑动到哪里.默认为false,先检测滑动到底部
+     *
+     * @param isTopFirst true为先检测滑动到顶部再检测滑动到底部;false为先检测滑动到底部再滑动到顶部
+     */
+    fun setCheckScrollToTopFirstBottomAfter(isTopFirst: Boolean) {
+        mIsCheckTopFirstBottomAfter = isTopFirst
+    }
+
+    /**
+     * 设置是否同时检测滑动到顶部及底部,默认为false,先检测到任何一个状态都会直接返回,不会再继续检测其它状态
+     *
+     * @param isCheckTogether true为两种状态都检测,即使已经检测到其中某种状态了.false为先检测到任何一种状态时将不再检测另一种状态
+     */
+    fun setCheckScrollToTopBottomTogether(isCheckTogether: Boolean) {
+        mIsCheckTopBottomTogether = isCheckTogether
+    }
+
+    /**
+     * 滑动位置改变监听事件,滑动到顶部/底部或者非以上两个位置时
+     */
+    interface OnScrollPositionChangedListener {
+        /**
+         * 滑动到顶部的回调事件
+         */
+        fun onScrollToTop()
+
+        /**
+         * 滑动到底部的回调事件
+         */
+        fun onScrollToBottom()
+
+        /**
+         * 滑动到未知位置的回调事件
+         *
+         * @param isTopViewVisible    当前位置顶部第一个itemView是否可见,这里是指adapter中的最后一个itemView
+         * @param isBottomViewVisible 当前位置底部最后一个itemView是否可见,这里是指adapter中的最后一个itemView
+         */
+        fun onScrollToUnknown(isTopViewVisible: Boolean, isBottomViewVisible: Boolean)
+    }
+
+    /**
+     * 滑动方向改变时监听事件
+     */
+    interface OnScrollDirectionChangedListener {
+        /**
+         * 滑动方向改变时监听事件,当两个参数值都为0时,数据变动重新layout
+         *
+         * @param scrollVertical   竖直方向的滑动方向,向上&lt;0,向下&gt;0,不动(水平滑动时)=0
+         * @param scrollHorizontal 水平方向的滑动方向,向左&lt;0,向右&gt;0,不动(竖直滑动时)=0
+         */
+        fun onScrollDirectionChanged(scrollHorizontal: Int, scrollVertical: Int)
+    }
+}

+ 305 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/ReflexHelper.kt

@@ -0,0 +1,305 @@
+package com.enation.javashop.android.lib.utils
+
+/**
+ * @author LDD
+ * @Date   2018/4/18 上午11:13
+ * @From   com.enation.javashop.android.lib.utils
+ * @Note   反射工具类
+ */
+class ReflexHelper private constructor(clsName :String){
+    
+    /**
+     * @author LDD
+     * @Date   2018/4/18 下午3:47
+     * @From   ReflexHelper
+     * @Note   用来避免在Kotlin中使用反射 Kotlin基础类型无法对应Java基础类型
+     */
+    data class ReflexFieldShell<T>(var value: T)
+
+    /**
+     * @Name  cls
+     * @Type  Class<*>
+     * @Note  查找到的Class对象
+     */
+    private val cls :Class<*> = Class.forName(clsName)
+
+    /**
+     * @Name  instance
+     * @Type  Any
+     * @Note  反射实例化出来的对象
+     */
+    private lateinit var instance :Any
+
+    /**
+     * @author LDD
+     * @Date   2018/4/19 下午2:29
+     * @From   ReflexHelper
+     * @Note   伴生对象用来静态build
+     */
+    companion object {
+
+        /**
+         * @author LDD
+         * @From   ReflexHelper
+         * @Date   2018/4/19 下午2:30
+         * @Note   静态构建
+         * @param  clsName 反射类对应全包名
+         */
+        fun build(clsName: String):ReflexHelper{
+            return ReflexHelper(clsName)
+        }
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:30
+     * @Note   无参实例化
+     */
+    fun newInstance() :ReflexHelper{
+        instance = cls.newInstance()
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:32
+     * @Note   1参反射实例化
+     * @param  arg0 参数
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     */
+    fun newInstance(arg0 :Any,isPrivate :Boolean = false) :ReflexHelper{
+        val constructor = cls.getConstructor(arg0::class.java)
+        constructor.isAccessible = isPrivate
+        instance =  constructor.newInstance(arg0)
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:32
+     * @Note   2参反射实例化
+     * @param  arg0 参数
+     * @param  arg1 参数
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     */
+    fun newInstance(arg0 :Any ,arg1 :Any,isPrivate :Boolean = false) :ReflexHelper{
+        val constructor = cls.getConstructor(arg0::class.java,arg1::class.java)
+        constructor.isAccessible = isPrivate
+        instance = constructor.newInstance(arg0,arg1)
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:32
+     * @Note   3参反射实例化
+     * @param  arg0 参数
+     * @param  arg1 参数
+     * @param  arg2 参数
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     */
+    fun newInstance(arg0 :Any ,arg1 :Any ,arg2 :Any,isPrivate :Boolean = false) :ReflexHelper{
+        val constructor = cls.getConstructor(arg0::class.java,arg1::class.java,arg2::class.java)
+        constructor.isAccessible = isPrivate
+        instance = constructor.newInstance(arg0,arg1,arg2)
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:32
+     * @Note   4参反射实例化
+     * @param  arg0 参数
+     * @param  arg1 参数
+     * @param  arg2 参数
+     * @param  arg3 参数
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     */
+    fun newInstance(arg0 :Any ,arg1 :Any ,arg2 :Any ,arg3 :Any ,isPrivate :Boolean = false) :ReflexHelper{
+        val constructor = cls.getConstructor(arg0::class.java,arg1::class.java,arg2::class.java,arg3::class.java)
+        constructor.isAccessible = isPrivate
+        instance = constructor.newInstance(arg0,arg1,arg2,arg3)
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:32
+     * @Note   4参反射实例化
+     * @param  arg0 参数
+     * @param  arg1 参数
+     * @param  arg2 参数
+     * @param  arg3 参数
+     * @param  arg4 参数
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     */
+    fun newInstance( arg0 :Any ,arg1 :Any ,arg2 :Any ,arg3 :Any ,arg4 :Any ,isPrivate :Boolean = false) :ReflexHelper{
+        val constructor = cls.getConstructor(arg0::class.java,arg1::class.java,arg2::class.java,arg3::class.java,arg4::class.java)
+        constructor.isAccessible = isPrivate
+        instance = constructor.newInstance(arg0,arg1,arg2,arg3,arg4)
+        return this
+    }
+
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:37
+     * @Note   无参数方法反射调用
+     * @param  methodName 方法名
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     * @param  call      如果存在返回参数 实现该回调
+     */
+    fun callMethod(methodName :String ,call :((Any) ->Unit)? = null ,isPrivate :Boolean = false):ReflexHelper{
+        val method = cls.getMethod(methodName)
+        method.isAccessible = isPrivate
+        if (call == null){
+            method.invoke(instance)
+        }else{
+            call.invoke(method.invoke(instance))
+        }
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:37
+     * @Note   无参数方法反射调用
+     * @param  methodName 方法名
+     * @param  arg0  参数
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     * @param  call      如果存在返回参数 实现该回调
+     */
+    fun callMethod(methodName :String ,arg0: Any ,call :((Any) ->Unit)? = null ,isPrivate :Boolean = false):ReflexHelper{
+        val method = cls.getMethod(methodName,arg0::class.java)
+        method.isAccessible = isPrivate
+        if (call == null){
+            method.invoke(instance,arg0)
+        }else{
+            call.invoke(method.invoke(instance,arg0))
+        }
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:37
+     * @Note   无参数方法反射调用
+     * @param  arg0  参数
+     * @param  arg1  参数
+     * @param  methodName 方法名
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     * @param  call      如果存在返回参数 实现该回调
+     */
+    fun callMethod(methodName :String ,arg0: Any ,arg1: Any ,call :((Any) ->Unit)? = null,isPrivate :Boolean = false):ReflexHelper{
+        val method = cls.getMethod(methodName,arg0::class.java,arg1::class.java)
+        method.isAccessible = isPrivate
+        if (call == null){
+            method.invoke(instance,arg0,arg1)
+        }else{
+            call.invoke(method.invoke(instance,arg0,arg1))
+        }
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:37
+     * @Note   无参数方法反射调用
+     * @param  methodName 方法名
+     * @param  arg0  参数
+     * @param  arg1  参数
+     * @param  arg2  参数
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     * @param  call      如果存在返回参数 实现该回调
+     */
+    fun callMethod(methodName :String ,arg0: Any ,arg1: Any ,arg2: Any ,call :((Any) ->Unit)? = null,isPrivate :Boolean = false):ReflexHelper{
+        val method = cls.getMethod(methodName,arg0::class.java,arg1::class.java,arg2::class.java)
+        method.isAccessible = isPrivate
+        if (call == null){
+            method.invoke(instance,arg0,arg1,arg2)
+        }else{
+            call.invoke(method.invoke(instance,arg0,arg1,arg2))
+        }
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:37
+     * @Note   无参数方法反射调用
+     * @param  methodName 方法名
+     * @param  arg0  参数
+     * @param  arg1  参数
+     * @param  arg2  参数
+     * @param  arg3  参数
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     * @param  call      如果存在返回参数 实现该回调
+     */
+    fun callMethod(methodName :String ,arg0: Any ,arg1: Any ,arg2: Any ,arg3: Any ,call :((Any) ->Unit)? = null,isPrivate :Boolean = false):ReflexHelper{
+        val method = cls.getMethod(methodName,arg0::class.java,arg1::class.java,arg2::class.java,arg3::class.java)
+        method.isAccessible = isPrivate
+        if (call == null){
+            method.invoke(instance,arg0,arg1,arg2,arg3)
+        }else{
+            call.invoke(method.invoke(instance,arg0,arg1,arg2,arg3))
+        }
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:37
+     * @Note   无参数方法反射调用
+     * @param  methodName 方法名
+     * @param  arg0  参数
+     * @param  arg1  参数
+     * @param  arg2  参数
+     * @param  arg3  参数
+     * @param  arg4  参数
+     * @param  isPrivate 是否开启私有方法访问 违反封装规范
+     * @param  call      如果存在返回参数 实现该回调
+     */
+    fun callMethod(methodName :String ,arg0: Any ,arg1: Any ,arg2: Any ,arg3: Any ,arg4: Any ,call :((Any) ->Unit)? = null,isPrivate :Boolean = false):ReflexHelper{
+        val method = cls.getMethod(methodName,arg0::class.java,arg1::class.java,arg2::class.java,arg3::class.java,arg4::class.java)
+        method.isAccessible = isPrivate
+        if (call == null){
+            method.invoke(instance,arg0,arg1,arg2,arg3,arg4)
+        }else{
+            call.invoke(method.invoke(instance,arg0,arg1,arg2,arg3,arg4))
+        }
+        return this
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:41
+     * @Note   获取反射成功的Class
+     */
+    fun <ValueType> getObjectClass() :Class<ValueType>{
+        return cls.to()
+    }
+
+    /**
+     * @author LDD
+     * @From   ReflexHelper
+     * @Date   2018/4/19 下午2:42
+     * @Note   获取反射成功的对象
+     */
+    fun <ValueType> getInstance() :ValueType{
+        return instance.to()
+    }
+
+}

+ 26 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/RegularHelper.kt

@@ -0,0 +1,26 @@
+package com.enation.javashop.android.lib.utils
+
+import java.util.regex.Pattern
+
+/**
+ * Created by LDD on 2018/11/16.
+ */
+class RegularHelper {
+
+    fun getMiddleString(content : String , start :String , endString: String , first :Boolean = false) : ArrayList<String>  {
+
+        val result = ArrayList<String>()
+
+        val pattern = Pattern.compile("$start(.*?)$endString")
+
+        val finder = pattern.matcher(content)
+
+        while (finder.find()){
+            result.add(finder.group(1))
+        }
+
+        return result
+
+    }
+
+}

+ 18 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/RxExtra.kt

@@ -0,0 +1,18 @@
+package com.enation.javashop.android.lib.utils
+
+import io.reactivex.Observable
+import okhttp3.ResponseBody
+
+/**
+ * Created by LDD on 2018/11/9.
+ */
+object RxExtra {
+
+    fun createNetErrorObservable (message :String) : Observable<ResponseBody>{
+        return  Observable.create { observableEmitter ->
+            observableEmitter.onError(Throwable(message))
+        }
+    }
+
+
+}

+ 156 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/SmartHideViewHelper.kt

@@ -0,0 +1,156 @@
+package com.enation.javashop.android.lib.utils
+
+import com.scwang.smartrefresh.layout.api.RefreshFooter
+import com.scwang.smartrefresh.layout.api.RefreshHeader
+import com.scwang.smartrefresh.layout.api.RefreshLayout
+import com.scwang.smartrefresh.layout.constant.RefreshState
+import com.scwang.smartrefresh.layout.listener.OnMultiPurposeListener
+
+/**
+ * @author LDD
+ * @From   com.enation.javashop.android.component.home.utils
+ * @Date   2018/1/30 下午3:06
+ * @Note   首页上滑topbar变幻辅助类
+ */
+
+class SmartHideViewHelper constructor(val refreshScrollStart: () -> Unit, val refreshEnd: () -> Unit) : OnMultiPurposeListener{
+
+    /**
+     * @Name  headerReleasing
+     * @Type  Boolean
+     * @Note  是否刷新
+     */
+    private  var headerReleasing =true
+
+
+    override fun onFooterMoving(footer: RefreshFooter?, isDragging: Boolean, percent: Float, offset: Int, footerHeight: Int, maxDragHeight: Int) {
+        refreshEnd.invoke()
+    }
+
+    override fun onHeaderStartAnimator(header: RefreshHeader?, headerHeight: Int, maxDragHeight: Int) {
+
+    }
+
+    override fun onFooterReleased(footer: RefreshFooter?, footerHeight: Int, maxDragHeight: Int) {
+        refreshEnd.invoke()
+    }
+
+    override fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState) {
+        if (!headerReleasing){
+            refreshEnd.invoke()
+        }
+    }
+
+    override fun onHeaderMoving(header: RefreshHeader?, isDragging: Boolean, percent: Float, offset: Int, headerHeight: Int, maxDragHeight: Int) {
+        headerReleasing = true
+    }
+
+    override fun onFooterFinish(footer: RefreshFooter?, success: Boolean) {
+
+    }
+
+    override fun onFooterStartAnimator(footer: RefreshFooter?, footerHeight: Int, maxDragHeight: Int) {
+
+    }
+
+    override fun onHeaderReleased(header: RefreshHeader?, headerHeight: Int, maxDragHeight: Int) {
+        refreshScrollStart.invoke()
+    }
+
+    override fun onLoadMore(refreshLayout: RefreshLayout) {
+
+    }
+
+    override fun onRefresh(refreshLayout: RefreshLayout) {
+
+    }
+
+    override fun onHeaderFinish(header: RefreshHeader?, success: Boolean) {
+
+    }
+}
+
+//class SmartHideViewHelper : OnMultiPurposeListener {
+//
+//    override fun onFooterReleased(p0: RefreshFooter?, p1: Int, p2: Int) {
+//
+//    }
+//
+//    override fun onHeaderReleased(p0: RefreshHeader?, p1: Int, p2: Int) {
+//
+//    }
+//
+//    override fun onLoadMore(p0: RefreshLayout?) {
+//
+//    }
+//
+//    /**
+//     * @Name  headerReleasing
+//     * @Type  Boolean
+//     * @Note  是否刷新
+//     */
+//    private  var headerReleasing =true
+//
+//    /**
+//     * @Name  refreshScrollStart
+//     * @Type  block
+//     * @Note  开始刷新回调
+//     */
+//    private  var refreshScrollStart :()->(Unit)
+//
+//    /**
+//     * @Name  refreshEnd
+//     * @Type  block
+//     * @Note  刷新结束回调
+//     */
+//    private  var refreshEnd :()->(Unit)
+//
+//
+//    constructor(refreshScrollStart: () -> Unit, refreshEnd: () -> Unit) {
+//        this.refreshScrollStart = refreshScrollStart
+//        this.refreshEnd = refreshEnd
+//    }
+//
+//
+//    override fun onFooterPulling(footer: RefreshFooter?, percent: Float, offset: Int, footerHeight: Int, extendHeight: Int) {
+//        refreshEnd.invoke()
+//    }
+//
+//    override fun onHeaderReleasing(header: RefreshHeader?, percent: Float, offset: Int, headerHeight: Int, extendHeight: Int) {
+//        headerReleasing = true
+//    }
+//
+//    override fun onHeaderStartAnimator(header: RefreshHeader?, headerHeight: Int, extendHeight: Int) {
+//    }
+//
+//    override fun onStateChanged(refreshLayout: RefreshLayout?, oldState: RefreshState?, newState: RefreshState?) {
+//        if (!headerReleasing){
+//            refreshEnd.invoke()
+//        }
+//    }
+//
+//    override fun onFooterFinish(footer: RefreshFooter?, success: Boolean) {
+//
+//    }
+//
+//    override fun onFooterStartAnimator(footer: RefreshFooter?, footerHeight: Int, extendHeight: Int) {
+//
+//    }
+//
+//    override fun onFooterReleasing(footer: RefreshFooter?, percent: Float, offset: Int, footerHeight: Int, extendHeight: Int) {
+//        refreshEnd.invoke()
+//    }
+//
+//    override fun onHeaderPulling(header: RefreshHeader?, percent: Float, offset: Int, headerHeight: Int, extendHeight: Int) {
+//        refreshScrollStart.invoke()
+//    }
+//
+//    override fun onRefresh(refreshlayout: RefreshLayout?) {
+//
+//    }
+//
+//    override fun onHeaderFinish(header: RefreshHeader?, success: Boolean) {
+//
+//    }
+//
+//}

+ 0 - 0
common/src/main/code/com/enation/javashop/android/lib/utils/TangramPlugin.kt


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels