diff --git a/MVPModel/.idea/caches/build_file_checksums.ser b/MVPModel/.idea/caches/build_file_checksums.ser index eb435f1..bd23801 100644 Binary files a/MVPModel/.idea/caches/build_file_checksums.ser and b/MVPModel/.idea/caches/build_file_checksums.ser differ diff --git a/MVPModel/.idea/gradle.xml b/MVPModel/.idea/gradle.xml index 7ac24c7..a848dcf 100644 --- a/MVPModel/.idea/gradle.xml +++ b/MVPModel/.idea/gradle.xml @@ -9,6 +9,7 @@ - - - - - - - - - Android - - - Class structureJava - - - Cloning issuesJava - - - Code style issuesJava - - - CorrectnessLintAndroid - - - Data flow issuesJava - - - Declaration redundancyJava - - - GPath inspectionsGroovy - - - Groovy - - - IconsUsabilityLintAndroid - - - JUnit issuesJava - - - Java - - - Java 5Java language level migration aidsJava - - - Java 8Java language level migration aidsJava - - - Java language level migration aidsJava - - - LintAndroid - - - Naming ConventionsGroovy - - - Naming conventionsJava - - - Numeric issuesJava - - - Performance issuesJava - - - PerformanceLintAndroid - - - Probable bugsGroovy - - - Probable bugsJava - - - SecurityLintAndroid - - - TestNGJava - - - UsabilityLintAndroid - - - - - - + diff --git a/MVPModel/.idea/modules.xml b/MVPModel/.idea/modules.xml index e0cb563..cc3167a 100644 --- a/MVPModel/.idea/modules.xml +++ b/MVPModel/.idea/modules.xml @@ -4,6 +4,8 @@ + + \ No newline at end of file diff --git a/MVPModel/app/.gitignore b/MVPModel/app/.gitignore index 796b96d..d33685b 100644 --- a/MVPModel/app/.gitignore +++ b/MVPModel/app/.gitignore @@ -1 +1,13 @@ -/build +.gradle/ +.DS_Store +local.properties + +# build files +build/ +bin/ +gen/ +output/ + +# android studio +*.iml +.idea diff --git a/MVPModel/app/build.gradle b/MVPModel/app/build.gradle index 9c2feaa..fb74df7 100644 --- a/MVPModel/app/build.gradle +++ b/MVPModel/app/build.gradle @@ -1,40 +1,216 @@ apply plugin: 'com.android.application' +ext.getCNName = { + java.util.HashMap map = new HashMap<>(); + map.put("xiaomi", "xiaomi-小米.apk"); + map.put("xueba", "xueba-学霸推广.apk"); + map.put("Baidu", "Baidu-百度.apk"); + map.put("Tencent", "Tencent-腾讯应用宝.apk"); + map.put("XuetangX", "XuetangX-学堂主站.apk"); + map.put("Wandoujia", "Wandoujia-豌豆荚.apk"); + map.put("huawei", "huawei-华为.apk"); + map.put("Qihoo", "Qihoo-360手机助手.apk"); + map.put("meizu", "meizu-魅族.apk"); + map.put("Anzhi", "Anzhi-安智.apk"); + map.put("taobao", "taobao-淘宝.apk"); + map.put("oppo", "oppo-oppo手机.apk"); + map.put("lenovo", "lenovo-联想手机.apk"); + map.put("google", "google-谷歌Play.apk"); + map.put("ppzhushou", "ppzhushou-pp助手.apk"); + map.put("sep_9", "sep_9-某推广渠道.apk"); + map.put("letv", "letv-乐视手机.apk"); + map.put("yingyonghui", "yingyonghui-应用汇.apk"); + map.put("gfan", "gfan-机锋.apk"); + map.put("sougou", "sougou-搜狗.apk"); + map.put("jlyyh", "jlyyh-金立.apk"); + map.put("offline_event", "offline_event-线下活动.apk"); + map.put("vivo", "vivo-vivo手机.apk"); + map.put("qingning", "qingning-青柠.apk"); + map.put("duomeng", "duomeng-多盟.apk"); + map.put("TencentTg", "Tencent-yyytg-应用宝推广.apk"); + map.put("BaiduTg", "Baidu-bdtg-百度推广.apk"); + + return map; +} + android { - compileSdkVersion 26 + signingConfigs { + release { + keyAlias 'mvpmodel' + keyPassword 'android1201' + storeFile file('mvpmodel.jks') + storePassword 'android1201' + } + } + compileSdkVersion rootProject.ext.android.compileSdkVersion + buildToolsVersion rootProject.ext.android.buildToolsVersion defaultConfig { applicationId "com.gaolei.mvpmodel" - minSdkVersion 15 - targetSdkVersion 26 - versionCode 1 - versionName "1.0" + minSdkVersion rootProject.ext.android.minSdkVersion + targetSdkVersion rootProject.ext.android.targetSdkVersion + versionCode rootProject.ext.android.versionCode + versionName rootProject.ext.android.versionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } buildTypes { + debug { + minifyEnabled false //是否启用Proguard + shrinkResources false //是否清理无用资源,依赖于minifyEnabled + zipAlignEnabled false //是否启用zipAlign压缩 + signingConfig signingConfigs.release + } + //执行lint检查,有任何的错误或者警告提示,都会终止构建 +// lintOptions { +// abortOnError false +// } release { - minifyEnabled false + minifyEnabled true //是否启用Proguard + shrinkResources true //是否清理无用资源,依赖于minifyEnabled + zipAlignEnabled true //是否启用zipAlign压缩 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release + //def date = new Date().format('yy-MM-dd-HH'); + applicationVariants.all { variant -> + variant.outputs.all { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.apk')) { + // 输出apk名称为XuetangXRelease-3.1.0(3100)_Baidu-百度.apk + def channel = variant.productFlavors[0].name + def releaseFileName = "build/outputs/MVPModel-${variant.buildType.name}-V${variant.versionName}(${variant.versionCode})_${getCNName().get(channel)}" + outputFileName = releaseFileName + } + } + } } + + } + + flavorDimensions("dimension1") + productFlavors { + xiaomi { + dimension "dimension1" + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi", SPAM_VALUE: "xiaomi"]; + } + xueba { + dimension "dimension1" + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xueba", SPAM_VALUE: "xueba"]; + } + Baidu { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Baidu", SPAM_VALUE: "Baidu"]; + dimension "dimension1" + } + Tencent { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Tencent", SPAM_VALUE: "Tencent"]; + dimension "dimension1" + } + XuetangX { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "XuetangX", SPAM_VALUE: "XuetangX"]; + dimension "dimension1" + } + Wandoujia { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Wandoujia", SPAM_VALUE: "Wandoujia"]; + dimension "dimension1" + } + huawei { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "huawei", SPAM_VALUE: "huawei"]; + dimension "dimension1" + } + Qihoo { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Qihoo", SPAM_VALUE: "Qihoo"]; + dimension "dimension1" + } + meizu { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "meizhu", SPAM_VALUE: "meizhu"]; + dimension "dimension1" + } + Anzhi { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Anzhi", SPAM_VALUE: "Anzhi"]; + dimension "dimension1" + } + taobao { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "taobao", SPAM_VALUE: "taobao"]; + dimension "dimension1" + } + oppo { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "oppo", SPAM_VALUE: "oppo"]; + dimension "dimension1" + } + lenovo { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "lenovo", SPAM_VALUE: "lenovo"]; + dimension "dimension1" + } + google { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "google", SPAM_VALUE: "google"]; + dimension "dimension1" + } + ppzhushou { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "ppzhushou", SPAM_VALUE: "ppzhushou"]; + dimension "dimension1" + } + + sep_9 { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "sep_9", SPAM_VALUE: "sep_9"]; + dimension "dimension1" + } + letv { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "letv", SPAM_VALUE: "letv"]; + dimension "dimension1" + } + yingyonghui { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "yingyonghui", SPAM_VALUE: "yingyonghui"]; + dimension "dimension1" + } + gfan { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "gfan", SPAM_VALUE: "gfan"]; + dimension "dimension1" + } + sougou { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "sougou", SPAM_VALUE: "sougou"]; + dimension "dimension1" + } + jlyyh { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "jlyyh", SPAM_VALUE: "jlyyh"]; + dimension "dimension1" + } + offline_event { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "offline_event", SPAM_VALUE: "offline_event"]; + dimension "dimension1" + } + vivo { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "vivo", SPAM_VALUE: "vivo"]; + dimension "dimension1" + } + qingning { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "qingning", SPAM_VALUE: "qingning"]; + dimension "dimension1" + } + duomeng { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "duomeng", SPAM_VALUE: "duomeng"]; + //duomeng被市场当做推广来用了。 + dimension "dimension1" + } + TencentTg { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Tencent", SPAM_VALUE: "yyytg"]; + dimension "dimension1" + } + BaiduTg { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Baidu", SPAM_VALUE: "bdtg"]; + dimension "dimension1" + } + } } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:26.1.0' - implementation "com.android.support:design:26+" - - implementation 'com.android.support.constraint:constraint-layout:1.1.0' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.1' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' - compile 'com.squareup.okhttp3:okhttp:3.10.0' - compile 'com.squareup.retrofit2:retrofit:2.4.0' - compile 'com.squareup.retrofit2:converter-gson:2.0.2' - implementation 'com.jakewharton:butterknife:8.8.1' - annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' - implementation 'com.github.bumptech.glide:glide:4.6.1' - annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1' - compile 'com.youth.banner:banner:1.4.10' + api fileTree(include: ['*.jar'], dir: 'libs') + + annotationProcessor rootProject.ext.dependencies["butterknife-compiler"] +// annotationProcessor rootProject.ext.dependencies["dagger-compiler"] + annotationProcessor rootProject.ext.dependencies["dagger-android-processor"] + annotationProcessor rootProject.ext.dependencies["dagger-compiler"] + compileOnly 'javax.annotation:javax.annotation-api:1.2' + api project(':basemodule') } diff --git a/MVPModel/app/mvpmodel.jks b/MVPModel/app/mvpmodel.jks new file mode 100644 index 0000000..e15edc9 Binary files /dev/null and b/MVPModel/app/mvpmodel.jks differ diff --git a/MVPModel/app/proguard-rules.pro b/MVPModel/app/proguard-rules.pro index f1b4245..6d04b50 100644 --- a/MVPModel/app/proguard-rules.pro +++ b/MVPModel/app/proguard-rules.pro @@ -19,3 +19,197 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile +# -----------------------------基本 ----------------------------- +# + +# 指定代码的压缩级别 0 - 7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用。) +-optimizationpasses 5 +# 混淆时不会产生形形色色的类名(混淆时不使用大小写混合类名) +-dontusemixedcaseclassnames +# 指定不去忽略非公共的库类(不跳过library中的非public的类) +-dontskipnonpubliclibraryclasses +# 指定不去忽略包可见的库类的成员 +-dontskipnonpubliclibraryclassmembers +#不进行优化,建议使用此选项, +-dontoptimize + # 不进行预校验,Android不需要,可加快混淆速度。 +-dontpreverify + + +# 屏蔽警告 +-ignorewarnings +# 指定混淆是采用的算法,后面的参数是一个过滤器 +# 这个过滤器是谷歌推荐的算法,一般不做更改 +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* +# 保护代码中的Annotation不被混淆 +-keepattributes *Annotation* +# 避免混淆泛型, 这在JSON实体映射时非常重要 +-keepattributes Signature +# 抛出异常时保留代码行号 +-keepattributes SourceFile,LineNumberTable + #优化时允许访问并修改有修饰符的类和类的成员,这可以提高优化步骤的结果。 +# 比如,当内联一个公共的getter方法时,这也可能需要外地公共访问。 +# 虽然java二进制规范不需要这个,要不然有的虚拟机处理这些代码会有问题。当有优化和使用-repackageclasses时才适用。 +#指示语:不能用这个指令处理库中的代码,因为有的类和类成员没有设计成public ,而在api中可能变成public +-allowaccessmodification +#当有优化和使用-repackageclasses时才适用。 +#-repackageclasses com.test + + # 混淆时记录日志(打印混淆的详细信息) + # 这句话能够使我们的项目混淆后产生映射文件 + # 包含有类名->混淆后类名的映射关系 +-verbose + +# 保留枚举类不被混淆 +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +# 保留Annotation不混淆 +-keepattributes *Annotation*,InnerClasses +-dontwarn javax.annotation.** +-dontwarn javax.inject.** + +# 保留R下面的资源 +-keep class **.R$* {*;} + +# 保留本地native方法不被混淆 +-keepclasseswithmembernames class * { + native ; +} +#所有model类不要混淆。 +-keep class com.gaolei.mvpmodel.base.mmodel.**{*;} +# 保留我们自定义控件(继承自View)不被混淆 +-keep public class * extends android.view.View{ + *** get*(); + void set*(***); + public (android.content.Context); + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); +} + +# 保留Parcelable序列化类不被混淆 +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} + +# 保留Serializable序列化的类不被混淆 +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + private static final java.io.ObjectStreamField[] serialPersistentFields; + !static !transient ; + !private ; + !private ; + 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); +} + +# glide +-keep public class * implements com.bumptech.glide.module.GlideModule +-keep public class * extends com.bumptech.glide.module.AppGlideModule +-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { + **[] $VALUES; + public *; +} +# for DexGuard only +#-keepresourcexmlelements manifest/application/meta-data@value=GlideModule + +# OkHttp3 + +-dontwarn okio.** +-dontwarn com.squareup.okhttp3.** +-keep class com.squareup.okhttp3.** { *; } +-keep interface com.squareup.okhttp3.** { *; } +-dontwarn javax.annotation.Nullable +-dontwarn javax.annotation.ParametersAreNonnullByDefault + +# Retrofit +-dontwarn retrofit2.** +-keep class retrofit2.** { *; } +#-keepattributes Signature-keepattributes Exceptions + +# 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 +# Gson +-keep class com.google.gson.stream.** { *; } +-keepattributes EnclosingMethod +-keep class org.xz_sale.entity.**{*;} + +# ButterKnife +-keep class butterknife.** { *;} +-dontwarn butterknife.internal.** +-keep class **$$ViewBinder { *;} +-keepclasseswithmembernames class * { + @butterknife.* ; +} +-keepclasseswithmembernames class * { + @butterknife.* ; +} + +# EventBus +-keepattributes *Annotation* +-keepclassmembers class * { + @org.greenrobot.eventbus.Subscribe ; +} +-keep enum org.greenrobot.eventbus.ThreadMode { *; } + +# Only required if you use AsyncExecutor +-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { + (java.lang.Throwable); +} + +#greendao3.2.0,此是针对3.2.0,如果是之前的,可能需要更换下包名 +# # ------------------------------------------- +-keep class freemarker.** { *; } +-dontwarn freemarker.** + +-keep class org.greenrobot.greendao.**{*;} +-dontwarn org.greenrobot.greendao.** + +-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao { +public static java.lang.String TABLENAME; +} +#友盟 +-keep class com.umeng.** {*;} +-keepclassmembers class * { + public (org.json.JSONObject); +} +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} +-keep public class com.gaolei.mvpmodel.R$*{ +public static final int *; +} \ No newline at end of file diff --git a/MVPModel/app/src/main/AndroidManifest.xml b/MVPModel/app/src/main/AndroidManifest.xml index 415edca..09ca59c 100644 --- a/MVPModel/app/src/main/AndroidManifest.xml +++ b/MVPModel/app/src/main/AndroidManifest.xml @@ -9,24 +9,30 @@ + - + + - + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/JsonUtil.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/JsonUtil.java deleted file mode 100644 index 504dc72..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/JsonUtil.java +++ /dev/null @@ -1,245 +0,0 @@ -package com.gaolei.mvpmodel; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; -import com.google.gson.reflect.TypeToken; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * JSON字符换和对象间转换的工具类 - */ -public class JsonUtil { - - private static final Gson GSON = new Gson(); - - /** - * 将json字符串转换成相应的对象 - * - * @param jsonString json字符串 - * @param classOfT 对象类型的class - * @param 对象的类型 - * @return 转换后的对象 - * @throws JsonParseException if json is not a valid representation for an object of type classOfT - */ - public static T decode(String jsonString, Class classOfT) throws RuntimeException { - return GSON.fromJson(jsonString, classOfT); - } - - /** - * 将json字符串转换成相应的对象 - * - * @param jsonString json字符串 - * @param typeOfT 对象类型的type - * @param 对象的类型 - * @return 转换后的对象 - * @throws JsonParseException if json is not a valid representation for an object of type typeOfT - */ - public static T decode(String jsonString, Type typeOfT) throws RuntimeException { - return GSON.fromJson(jsonString, typeOfT); - } - - /** - * 将已经从json转换后的对象(通常是一个Map)转换成对应Bean的对象实例 - * - * @param object 一个转json换中的过程对象,通常是一个Map,若传值为null,则返回null - * @param typeOfT 要转换的对象类型的type - * @param 要转换的对象类型 - * @return 转换后的对象 - * @throws JsonParseException if object is not a valid representation for an object of type typeOfT - */ - public static T decode(Object object, Type typeOfT) throws RuntimeException { - String jsonString = GSON.toJson(object); - return GSON.fromJson(jsonString, typeOfT); - } - - /** - * 将一个JavaBean转换成json字符串 - * - * @param object 待转换的对象 - * @return json字符串 - * @throws JsonParseException if there was a problem while parsing object. - */ - public static String encode(Object object) throws RuntimeException { - return GSON.toJson(object); - } - - - /** - * 获取JsonObject - * - * @param json - * @return - */ - public static JsonObject parseJson(String json) { - JsonParser parser = new JsonParser(); - JsonObject jsonObj = parser.parse(json).getAsJsonObject(); - return jsonObj; - } - - /** - * 根据javaBean转json字符串再将字符串转Map对象 - * - * @param object - * @return - */ - public static Map javaBeanToMap(Object object) { - String strJson = encode(object); - return toMap(parseJson(strJson)); - } - - /** - * 将JSONObjec对象转换成Map-List集合 - * - * @param json - * @return - */ - public static Map toMap(JsonObject json) { - Map map = new HashMap(); - Set> entrySet = json.entrySet(); - for (Iterator> iter = entrySet.iterator(); iter.hasNext(); ) { - Map.Entry entry = iter.next(); - String key = entry.getKey(); - Object value = entry.getValue(); - if (value instanceof JsonArray) - map.put((String) key, toList((JsonArray) value)); - else if (value instanceof JsonObject) - map.put((String) key, toMap((JsonObject) value)); - else - map.put((String) key, value); - } - return map; - } - - /** - * 将JSONArray对象转换成List集合 - * - * @param json - * @return - */ - public static List toList(JsonArray json) { - List list = new ArrayList(); - for (int i = 0; i < json.size(); i++) { - Object value = json.get(i); - if (value instanceof JsonArray) { - list.add(toList((JsonArray) value)); - } else if (value instanceof JsonObject) { - list.add(toMap((JsonObject) value)); - } else { - list.add(value); - } - } - return list; - } - - /** - * Json解析公用方法 数组 - * - * @param json 解析参数 - * @param token 解析的类型 new TypeToken(){} - * ArrayList temp = ParserJson.fromJson(data, new TypeToken>(){}); - * @return - */ - public static T fromJson(JsonElement json, TypeToken token) { - try { - Gson gson = new Gson(); - return gson.fromJson(json, token.getType()); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - /** - * Json解析公用方法 数组 - * - * @param json 解析参数 - * @param type 解析的类型 new TypeToken(){}.getType() - * ArrayList temp = ParserJson.fromJson(data, new TypeToken>(){}); - * @return - */ - public static T fromJson(JsonElement json, Type type) { - try { - Gson gson = new Gson(); - return gson.fromJson(json, type); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - /** - * Json解析公用方法 单个类 - * - * @param json 解析参数 - * @param t 解析的类。 class - * @return - */ - public static T fromJson(JsonElement json, Class t) { - try { - Gson gson = new Gson(); - return gson.fromJson(json, t); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - /** - * Json解析公用方法 数组 - * - * @param json 解析参数 - * @param token 解析的类型 new TypeToken(){} - * ArrayList temp = ParserJson.fromJson(data, new TypeToken>(){}); - * @return - */ - public static T fromJson(String json, TypeToken token) { - try { - Gson gson = new Gson(); - return gson.fromJson(json, token.getType()); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - /** - * Json解析公用方法 单个类 - * - * @param json 解析参数 - * @param t 解析的类。 class - * @return - */ - public static T fromJson(String json, Class t) { - try { - Gson gson = new Gson(); - return gson.fromJson(json, t); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - /** - * 把数据转换成Json结构 - * - * @param mType Object的数据,支持所有类型 - * @return - */ - public static String toJson(Object mType) { - Gson mGson = new Gson(); - String mResult = mGson.toJson(mType); - return mResult; - } -} - diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/MainActivity.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/MainActivity.java index 693eb9f..e1ecbe4 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/MainActivity.java +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/MainActivity.java @@ -1,200 +1,148 @@ package com.gaolei.mvpmodel; import android.Manifest; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.design.widget.BottomNavigationView; -import android.support.v4.app.ActivityCompat; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; import android.os.Bundle; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.RecyclerView; -import android.view.MenuItem; +import android.support.annotation.Nullable; +import android.support.design.widget.TabLayout; +import android.support.v4.app.Fragment; +import android.view.View; import android.widget.TextView; -import android.widget.Toast; -import com.gaolei.mvpmodel.activity.BaseActivity; -import com.gaolei.mvpmodel.fragment.BaseMvpFragment; -import com.gaolei.mvpmodel.fragment.KnowledgeFragment; +import com.gaolei.mvpmodel.adapter.MainTabAdapter; +import com.gaolei.mvpmodel.base.activity.BaseActivity; +import com.gaolei.mvpmodel.base.utils.LogUtil; +import com.gaolei.mvpmodel.base.utils.PermissionUtil; +import com.gaolei.mvpmodel.base.utils.Utils; import com.gaolei.mvpmodel.fragment.HomeFragment; +import com.gaolei.mvpmodel.fragment.KnowledgeFragment; import com.gaolei.mvpmodel.fragment.NavigationFragment; import com.gaolei.mvpmodel.fragment.ProjectFragment; +import com.gaolei.mvpmodel.fragment.UserFragment; +import com.gaolei.mvpmodel.view.CustomViewPager; import java.util.ArrayList; import butterknife.BindView; +import butterknife.OnClick; public class MainActivity extends BaseActivity { - private ArrayList mFragments; - private int mLastFgIndex = 0; + private ArrayList mFragments; + private ArrayList titles; + + @BindView(R.id.viewPager) + CustomViewPager viewPager; + @BindView(R.id.tabLayout) + TabLayout tabLayout; + @BindView(R.id.title) TextView title; - private static final int MY_PERMISSION_REQUEST_CODE = 10000; - // BottomNavigationView bottomNavigationView; - @BindView(R.id.bottom_navigation_view) - BottomNavigationView bottomNavigationView; - String[] permissionArray = new String[]{ - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE, - }; + HomeFragment homeFragment; + ProjectFragment projectFragment; @Override - protected int setContentLayout() { + protected int getLayoutId() { return R.layout.activity_main; } @Override protected void initData(Bundle bundle) { - // 取消BottomNavigation大于3个时,动画 - BottomNavigationViewHelper.disableShiftMode(bottomNavigationView); - mFragments = new ArrayList(); - title = findViewById(R.id.title); - mFragments.add(new HomeFragment()); + initView(); + requestPermission(); + + } + protected void initView(){ + mFragments = new ArrayList(); + homeFragment = new HomeFragment(); + projectFragment = new ProjectFragment(); + mFragments.add(homeFragment); + mFragments.add(projectFragment); mFragments.add(new KnowledgeFragment()); mFragments.add(new NavigationFragment()); - mFragments.add(new ProjectFragment()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - //如果versionCode>=23 则需要动态授权 - checkPermission(); - } else { - switchFragment(0); - } - - bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { - @Override - public boolean onNavigationItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case R.id.tab_main_pager: - title.setText(getString(R.string.home_pager)); - switchFragment(0); - - break; - case R.id.tab_knowledge_hierarchy: - title.setText(getString(R.string.knowledge_hierarchy)); - switchFragment(1); - - break; - case R.id.tab_navigation: - title.setText(getString(R.string.navigation)); - switchFragment(2); - - break; - case R.id.tab_project: - title.setText(getString(R.string.project)); - switchFragment(3); - break; - } - return true; - } - }); + mFragments.add(new UserFragment()); + + titles = new ArrayList(); + titles.add(getString(R.string.home)); + titles.add(getString(R.string.project)); + titles.add(getString(R.string.knowledge)); + titles.add(getString(R.string.navigation)); + titles.add(getString(R.string.mine)); + + MainTabAdapter adapter = new MainTabAdapter(getSupportFragmentManager(), mFragments); + viewPager.setOffscreenPageLimit(mFragments.size()); + viewPager.setAdapter(adapter); + viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); + tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager)); + //将TabLayout和ViewPager关联起来 + tabLayout.setupWithViewPager(viewPager); + initTab(); } + /** - * 切换fragment - * - * @param position 要显示的fragment的下标 + * 设置添加Tab */ - private void switchFragment(int position) { - - FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - Fragment targetFg = mFragments.get(position); - Fragment lastFg = mFragments.get(mLastFgIndex); - mLastFgIndex = position; - ft.hide(lastFg); - if (!targetFg.isAdded()) { - getSupportFragmentManager().beginTransaction().remove(targetFg).commit(); - ft.add(R.id.fragment_group, targetFg); - } - ft.show(targetFg); - ft.commitAllowingStateLoss(); - } + private void initTab() { - public void checkPermission() { - /** - * 第 1 步: 检查是否有相应的权限 - */ - boolean isAllGranted = checkPermissionAllGranted( - permissionArray - ); - // 如果这权限全都拥有, 则显示HomeFragment - if (isAllGranted) { - switchFragment(0); - return; - } - - /** - * 第 2 步: 请求权限 - */ - // 一次请求多个权限, 如果其他有权限是已经授予的将会自动忽略掉 - ActivityCompat.requestPermissions( - this, - permissionArray, - MY_PERMISSION_REQUEST_CODE - ); - } + tabLayout.getTabAt(0).setCustomView(R.layout.tab_home); + tabLayout.getTabAt(1).setCustomView(R.layout.tab_project); + tabLayout.getTabAt(2).setCustomView(R.layout.tab_knowledge); + tabLayout.getTabAt(3).setCustomView(R.layout.tab_navigation); + tabLayout.getTabAt(4).setCustomView(R.layout.tab_mine); + + + tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + //标签选中之后执行的方法 + @Override + public void onTabSelected(TabLayout.Tab tab) { + title.setText(titles.get(tab.getPosition())); +// if(tab.getPosition()==1) +// throw new RuntimeException("I'm a cool exception and I crashed the main thread!"); - /** - * 检查是否拥有指定的所有权限 - */ - private boolean checkPermissionAllGranted(String[] permissions) { - for (String permission : permissions) { - if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { - // 只要有一个权限没有被授予, 则直接返回 false - return false; } - } - return true; - } - /** - * 第 3 步: 申请权限结果返回处理 - */ - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - - if (requestCode == MY_PERMISSION_REQUEST_CODE) { - boolean isAllGranted = true; - // 判断是否所有的权限都已经授予了 - for (int grant : grantResults) { - if (grant != PackageManager.PERMISSION_GRANTED) { - isAllGranted = false; - break; - } + //标签没选中 + @Override + public void onTabUnselected(TabLayout.Tab tab) { + } - if (isAllGranted) { - // 如果所有的权限都授予了, 则显示HomeFragment - switchFragment(0); - } else { - // 弹出对话框告诉用户需要权限的原因, 并引导用户去应用权限管理中手动打开权限按钮 - getAppDetailSettingIntent(this); - toast("App正常使用需要授权" ); + @Override + public void onTabReselected(TabLayout.Tab tab) { } - } + }); + //默认选中的Tab + tabLayout.getTabAt(0).getCustomView().setSelected(true); + } + + @OnClick({R.id.title}) + public void onClick() { + int index = viewPager.getCurrentItem(); + if (index == 0) + homeFragment.scrollToTop(); + if (index == 1) + projectFragment.scrollToTop(); + + } - public void toast(String content) { - Toast.makeText(getApplicationContext(), content, Toast.LENGTH_SHORT).show(); + public void requestPermission() { + requestPermission(this, new PermissionUtil.RequestPermissionCallBack() { + + @Override + public void granted() { + + } + + @Override + public void denied() { + } + }, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE}); } - private void getAppDetailSettingIntent(Context context) { - Intent intent = new Intent(); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - if (Build.VERSION.SDK_INT >= 9) { - intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); - intent.setData(Uri.fromParts("package", getPackageName(), null)); - } else if (Build.VERSION.SDK_INT <= 8) { - intent.setAction(Intent.ACTION_VIEW); - intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails"); - intent.putExtra("com.android.settings.ApplicationPkgName", getPackageName()); - } - startActivity(intent); + public void onRestart() { + super.onRestart(); + //跳转到设置界面后返回,重新检查权限 + requestPermission(); } } diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/SplashActivity.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/SplashActivity.java new file mode 100644 index 0000000..314a11a --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/SplashActivity.java @@ -0,0 +1,42 @@ +package com.gaolei.mvpmodel; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.view.View; + +/** + * description: test + * author: zlm + * date: 2017/3/17 16:01 + */ +public class SplashActivity extends Activity { + + + Handler handler = new Handler() { + public void handleMessage(Message msg) { + Intent intent = new Intent(SplashActivity.this, MainActivity.class); + startActivity(intent); + finish(); + } + }; + + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_splash); + + handler.sendEmptyMessageDelayed(0, 3000); + } + + public void jumpToMainActivity(View view){ + Intent intent = new Intent(SplashActivity.this, MainActivity.class); + startActivity(intent); + handler.removeCallbacksAndMessages(null); + finish(); + } + +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/ArticleDetailActivity.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/ArticleDetailActivity.java index 2e0f81d..d3b5cdd 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/ArticleDetailActivity.java +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/ArticleDetailActivity.java @@ -1,24 +1,14 @@ package com.gaolei.mvpmodel.activity; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.design.widget.BottomNavigationView; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; -import android.view.MenuItem; +import android.support.annotation.Nullable; import android.view.View; +import android.widget.ImageView; import android.widget.TextView; -import com.gaolei.mvpmodel.BottomNavigationViewHelper; import com.gaolei.mvpmodel.R; -import com.gaolei.mvpmodel.fragment.BaseMvpFragment; -import com.gaolei.mvpmodel.fragment.HomeFragment; -import com.gaolei.mvpmodel.fragment.KnowledgeFragment; -import com.gaolei.mvpmodel.fragment.NavigationFragment; -import com.gaolei.mvpmodel.fragment.ProjectFragment; -import com.gaolei.mvpmodel.view.Html5Webview; - -import java.util.ArrayList; +import com.gaolei.mvpmodel.base.activity.BaseActivity; +import com.gaolei.mvpmodel.base.view.Html5Webview; import butterknife.BindView; @@ -26,9 +16,13 @@ public class ArticleDetailActivity extends BaseActivity { @BindView(R.id.webview_article) Html5Webview webview_article; + @BindView(R.id.iv_back) + ImageView iv_back; + @BindView(R.id.title) + TextView title; @Override - protected int setContentLayout() { + protected int getLayoutId() { return R.layout.activity_article_detail; } diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/BaseActivity.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/BaseActivity.java deleted file mode 100644 index 803b16a..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/BaseActivity.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.gaolei.mvpmodel.activity; - -import android.graphics.Color; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; -import android.support.v7.app.AppCompatActivity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.gaolei.mvpmodel.R; -import com.gaolei.mvpmodel.utils.NetworkUtil; -import com.gaolei.mvpmodel.utils.StatusBarUtil; - -import butterknife.ButterKnife; -import butterknife.Unbinder; - - -/** - * Created by gaolei on 2018/4/26. - */ - -public abstract class BaseActivity extends FragmentActivity implements View.OnClickListener { - private Unbinder mBinder; - ImageView iv_back; - TextView title; - - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LayoutInflater inflater = LayoutInflater.from(this); - setContentView(addContentView(inflater)); - setStatusBarColor(R.color.yellow); - mBinder = ButterKnife.bind(this); - Bundle bundle = getIntent().getExtras(); - if (bundle == null) { - bundle = savedInstanceState; - } - initData(bundle); - - - } - - protected abstract int setContentLayout(); - - protected abstract void initData(Bundle bundle); - - private void initBaseView(View view) { - iv_back = view.findViewById(R.id.iv_back); - title = view.findViewById(R.id.title); - iv_back.setOnClickListener(this); - } - - - public View addContentView(LayoutInflater inflater) { - LinearLayout mParentView = (LinearLayout) inflater.inflate(R.layout.activity_base, null); - View subActivityView = inflater.inflate(setContentLayout(), null); - mParentView.addView(subActivityView); - initBaseView(mParentView); - return mParentView; - } - - /** - * 设置状态栏颜色 - */ - public void setStatusBarColor(int resColor) { - StatusBarUtil.setWindowStatusBarColor(this, resColor, true); - } - - protected void onDestroy() { - super.onDestroy(); - if (mBinder != null) { - mBinder.unbind(); - } - } - - @Override - public void onClick(View v) { - switch (v.getId()) { - case R.id.iv_back: - finish(); - break; - } - } -} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/BaseMvpActivity.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/BaseMvpActivity.java deleted file mode 100644 index f89fd4b..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/activity/BaseMvpActivity.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gaolei.mvpmodel.activity; - -import android.os.Bundle; -import android.support.annotation.Nullable; - -import com.gaolei.mvpmodel.mpresenter.BasePresenter; - - -/** - * Created by liuhaiyang on 2017/8/2. - */ - -public abstract class BaseMvpActivity> extends BaseActivity { - - public P mPresenter; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mPresenter = initPresenter(); - mPresenter.attach((V) this); - } - - @Override - protected void onDestroy() { - mPresenter.dettach(); - super.onDestroy(); - } - - //实例presenter - public abstract P initPresenter(); -} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/ArticleListAdapter.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/ArticleListAdapter.java new file mode 100644 index 0000000..e11724a --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/ArticleListAdapter.java @@ -0,0 +1,79 @@ +package com.gaolei.mvpmodel.adapter; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.gaolei.mvpmodel.R; +import com.gaolei.mvpmodel.base.mmodel.ArticleListData.FeedArticleData; +import com.gaolei.mvpmodel.base.thirdframe.glide.ImageLoader; + +import java.util.List; + + +public class ArticleListAdapter extends RecyclerView.Adapter { + + public Context context; + int selectPosition = 0; + OnItemClickListener listener; + List list; + + public ArticleListAdapter(Context context, List list) { + this.context = context; + this.list = list; + } + + public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(context).inflate(R.layout.item_article_list, null); + MyViewHolder holder = new MyViewHolder(view); + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + int position = (int) view.getTag(); + if (listener != null) { + listener.onItemClick(view, position); + } + } + }); + return holder; + } + + public void onBindViewHolder(MyViewHolder holder, int position) { + holder.itemView.setTag(position); + FeedArticleData projectInfo = list.get(position); + + holder.tv_item_title.setText(projectInfo.getTitle()); + holder.tv_item_time.setText(projectInfo.getNiceDate()); + holder.tv_item_author.setText(context.getString(R.string.author) + projectInfo.getAuthor()); + + } + + @Override + public int getItemCount() { + return list.size(); + } + + class MyViewHolder extends RecyclerView.ViewHolder { + TextView tv_item_title, tv_item_author, tv_item_time; + + public MyViewHolder(View view) { + super(view); + tv_item_title = view.findViewById(R.id.tv_item_title); + tv_item_author = view.findViewById(R.id.tv_item_author); + tv_item_time = view.findViewById(R.id.tv_item_time); + } + } + + public interface OnItemClickListener { + public void onItemClick(View v, int position); + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.listener = listener; + } +} \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/MainTabAdapter.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/MainTabAdapter.java new file mode 100644 index 0000000..d6fd3f0 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/MainTabAdapter.java @@ -0,0 +1,41 @@ +package com.gaolei.mvpmodel.adapter; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + + +import com.gaolei.mvpmodel.fragment.HomeFragment; + +import java.util.List; + + +public class MainTabAdapter extends FragmentPagerAdapter { + + List fragments; + + public MainTabAdapter(FragmentManager fm, List fragments) { + super(fm); + this.fragments = fragments; + + + } + + @Override + public Fragment getItem(int position) { + Fragment fragment = fragments.get(position); +// Bundle bundle=new Bundle(); +// bundle.putString("title",titles[position]); +// fragment.setArguments(bundle); + return fragment; + } + + @Override + public int getCount() { + return fragments.size(); + } +} + diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/ProjectAdapter.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/ProjectAdapter.java deleted file mode 100644 index dfe4984..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/ProjectAdapter.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.gaolei.mvpmodel.adapter; - -import android.content.Context; -import android.media.Image; -import android.support.v7.widget.RecyclerView; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import com.bumptech.glide.Glide; -import com.gaolei.mvpmodel.R; -import com.gaolei.mvpmodel.mmodel.ProjectListData.FeedArticleData; - -import java.util.List; - -import static com.gaolei.mvpmodel.application.CustomApplication.options; - -public class ProjectAdapter extends RecyclerView.Adapter { - - public Context context; - int selectPosition = 0; - OnItemClickListener listener; - List list; - - public ProjectAdapter(Context context, List list) { - this.context = context; - this.list = list; - } - - public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = LayoutInflater.from(context).inflate(R.layout.item_project_list, null); - MyViewHolder holder = new MyViewHolder(view); - view.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - - int position = (int) view.getTag(); - if (listener != null) { - listener.onItemClick(view, position); - } - } - }); - return holder; - } - - public void onBindViewHolder(MyViewHolder holder, int position) { - holder.itemView.setTag(position); - FeedArticleData projectInfo=list.get(position); - Log.d("gaolei","onBindViewHolder-----------"+position); - Log.d("gaolei","projectInfo.getTitle()-----------"+projectInfo.getTitle()); - holder.item_project_list_title_tv.setText(projectInfo.getTitle()); - holder.item_project_list_content_tv.setText(projectInfo.getDesc()); - holder.item_project_list_time_tv.setText(projectInfo.getNiceDate()); - holder.item_project_list_author_tv.setText(projectInfo.getAuthor()); - Glide.with(context) - .load(projectInfo.getEnvelopePic()) // 图片地址 - .apply(options) // 参数 - .into(holder.item_project_list_iv); // 需要显示的ImageView控件 - } - - @Override - public int getItemCount() { - return list.size(); - } - - class MyViewHolder extends RecyclerView.ViewHolder { - TextView item_project_list_title_tv,item_project_list_content_tv,item_project_list_time_tv,item_project_list_author_tv; - ImageView item_project_list_iv; - - public MyViewHolder(View view) { - super(view); - item_project_list_title_tv = view.findViewById(R.id.item_project_list_title_tv); - item_project_list_content_tv = view.findViewById(R.id.item_project_list_content_tv); - item_project_list_time_tv = view.findViewById(R.id.item_project_list_time_tv); - item_project_list_author_tv = view.findViewById(R.id.item_project_list_author_tv); - item_project_list_iv = view.findViewById(R.id.item_project_list_iv); - } - } - - public interface OnItemClickListener { - public void onItemClick(View v, int position); - } - - public void setOnItemClickListener(OnItemClickListener listener) { - this.listener = listener; - } -} \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/ProjectListAdapter.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/ProjectListAdapter.java new file mode 100644 index 0000000..4fb8a38 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/adapter/ProjectListAdapter.java @@ -0,0 +1,87 @@ +package com.gaolei.mvpmodel.adapter; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.gaolei.mvpmodel.R; +import com.gaolei.mvpmodel.base.mmodel.ProjectListData; +import com.gaolei.mvpmodel.base.mmodel.ProjectListData.ProjectData; +import com.gaolei.mvpmodel.base.thirdframe.glide.ImageLoader; + +import java.util.List; + + +public class ProjectListAdapter extends RecyclerView.Adapter { + + public Context context; + int selectPosition = 0; + OnItemClickListener listener; + List list; + + public ProjectListAdapter(Context context, List list) { + this.context = context; + this.list = list; + } + + public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(context).inflate(R.layout.item_project_list, null); + MyViewHolder holder = new MyViewHolder(view); + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + int position = (int) view.getTag(); + if (listener != null) { + listener.onItemClick(view, position); + } + } + }); + return holder; + } + + public void onBindViewHolder(MyViewHolder holder, int position) { + holder.itemView.setTag(position); + ProjectData projectInfo=list.get(position); + Log.d("gaolei","onBindViewHolder-----------"+position); + Log.d("gaolei","projectInfo.getTitle()-----------"+projectInfo.getTitle()); + holder.item_project_list_title_tv.setText(projectInfo.getTitle()); + holder.item_project_list_content_tv.setText(projectInfo.getDesc()); + holder.item_project_list_time_tv.setText(projectInfo.getNiceDate()); + holder.item_project_list_author_tv.setText(context.getString(R.string.author)+projectInfo.getAuthor()); + ImageLoader.getInstance().load(context,projectInfo.getEnvelopePic(),holder.item_project_list_iv); + + } + + @Override + public int getItemCount() { + return list.size(); + } + + class MyViewHolder extends RecyclerView.ViewHolder { + TextView item_project_list_title_tv,item_project_list_content_tv,item_project_list_time_tv,item_project_list_author_tv; + ImageView item_project_list_iv; + + public MyViewHolder(View view) { + super(view); + item_project_list_title_tv = view.findViewById(R.id.item_project_list_title_tv); + item_project_list_content_tv = view.findViewById(R.id.item_project_list_content_tv); + item_project_list_time_tv = view.findViewById(R.id.item_project_list_time_tv); + item_project_list_author_tv = view.findViewById(R.id.item_project_list_author_tv); + item_project_list_iv = view.findViewById(R.id.item_project_list_iv); + } + } + + public interface OnItemClickListener { + public void onItemClick(View v, int position); + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.listener = listener; + } +} \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/application/App.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/application/App.java new file mode 100644 index 0000000..9fd21c5 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/application/App.java @@ -0,0 +1,58 @@ +package com.gaolei.mvpmodel.application; + +import android.app.Activity; +import android.app.Application; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.ConnectivityManager; +import android.support.v4.app.Fragment; +import android.util.Log; + +import com.gaolei.mvpmodel.base.application.CustomApplication; +import com.gaolei.mvpmodel.base.utils.LogUtil; + +import com.gaolei.mvpmodel.dagger.component.DaggerAppComponent; +import com.umeng.analytics.MobclickAgent; +import com.umeng.commonsdk.UMConfigure; + +import javax.inject.Inject; + +import cat.ereza.customactivityoncrash.CustomActivityOnCrash; +import dagger.android.AndroidInjector; +import dagger.android.DispatchingAndroidInjector; +import dagger.android.HasActivityInjector; +import dagger.android.support.HasSupportFragmentInjector; + + +public class App extends CustomApplication implements HasSupportFragmentInjector, HasActivityInjector { + + public static ConnectivityManager connectivityManager; + public static Context context; + @Inject + DispatchingAndroidInjector mDispatchingAndroidInjector; + @Inject + DispatchingAndroidInjector mFragmentDispatchingAndroidInjector; + @Override + public void onCreate() { + super.onCreate(); + + DaggerAppComponent.create().inject(this); + + + + } + + @Override + public AndroidInjector activityInjector() { + return mDispatchingAndroidInjector; + } + + @Override + public AndroidInjector supportFragmentInjector() { + return mFragmentDispatchingAndroidInjector; + } + + + +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/application/CustomApplication.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/application/CustomApplication.java deleted file mode 100644 index e781e76..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/application/CustomApplication.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gaolei.mvpmodel.application; - -import android.app.Application; -import android.content.Context; - -import com.bumptech.glide.load.engine.DiskCacheStrategy; -import com.bumptech.glide.request.RequestOptions; -import com.gaolei.mvpmodel.R; - - -public class CustomApplication extends Application { - - public static RequestOptions options; - @Override - public void onCreate() { - super.onCreate(); - options = new RequestOptions() -// .placeholder(R.drawable.ic_launcher)// 正在加载中的图片 -// .error(R.drawable.video_error) // 加载失败的图片 - .diskCacheStrategy(DiskCacheStrategy.ALL); // 磁盘缓存策略 - } - } diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/component/AppComponent.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/component/AppComponent.java new file mode 100644 index 0000000..f7aa875 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/component/AppComponent.java @@ -0,0 +1,22 @@ +package com.gaolei.mvpmodel.dagger.component; + + +import com.gaolei.mvpmodel.application.App; +import com.gaolei.mvpmodel.dagger.module.AllActivitysMoudle; +import com.gaolei.mvpmodel.dagger.module.AllFragmentsModule; + + +import dagger.Component; +import dagger.android.AndroidInjectionModule; +import dagger.android.support.AndroidSupportInjectionModule; + + +@Component(modules = { + AndroidInjectionModule.class, + AndroidSupportInjectionModule.class, + AllActivitysMoudle.class, + AllFragmentsModule.class +}) +public interface AppComponent { + void inject(App app); +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/AllActivitysMoudle.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/AllActivitysMoudle.java new file mode 100644 index 0000000..cb6fa9d --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/AllActivitysMoudle.java @@ -0,0 +1,23 @@ +package com.gaolei.mvpmodel.dagger.module; + +import com.gaolei.mvpmodel.MainActivity; +import com.gaolei.mvpmodel.dagger.scope.PerActivity; + +import dagger.Module; +import dagger.android.ContributesAndroidInjector; + +/** + *
+ *     author : lex
+ *     e-mail : ldlywt@163.com
+ *     time   : 2018/09/03
+ *     desc   :
+ *     version: 1.0
+ * 
+ */ +@Module +public abstract class AllActivitysMoudle { +// @PerActivity +// @ContributesAndroidInjector +// abstract MainActivity contributeTopicDetailActivityInjector(); +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/AllFragmentsModule.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/AllFragmentsModule.java new file mode 100644 index 0000000..3c4e805 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/AllFragmentsModule.java @@ -0,0 +1,50 @@ +package com.gaolei.mvpmodel.dagger.module; + + +import com.gaolei.mvpmodel.dagger.scope.PerFragment; +import com.gaolei.mvpmodel.fragment.HomeFragment; +import com.gaolei.mvpmodel.fragment.KnowledgeFragment; +import com.gaolei.mvpmodel.fragment.NavigationFragment; +import com.gaolei.mvpmodel.fragment.ProjectFragment; +import com.gaolei.mvpmodel.fragment.UserFragment; + +import dagger.Module; +import dagger.android.ContributesAndroidInjector; + +/** + *
+ *     author : lex
+ *     e-mail : ldlywt@163.com
+ *     time   : 2018/09/03
+ *     desc   :
+ *     version: 1.0
+ * 
+ */ +@Module +public abstract class AllFragmentsModule { +// @PerFragment +// @ContributesAndroidInjector(modules = TopicFragmentModule.class) +// abstract TopicFragment contributeTopicFragmentInjector(); + + @PerFragment + @ContributesAndroidInjector(modules = HomeFragmentModule.class) + abstract HomeFragment contributeHomeFragmentInjector(); + + @PerFragment + @ContributesAndroidInjector(modules = ProjectFragmentModule.class) + abstract ProjectFragment contributeProjectFragmentInjector(); + + @PerFragment + @ContributesAndroidInjector(modules = HomeFragmentModule.class) + abstract UserFragment contributeMineFragmentInjector(); + + @PerFragment + @ContributesAndroidInjector(modules = HomeFragmentModule.class) + abstract KnowledgeFragment contributeTreeFragmentInjector(); + + @PerFragment + @ContributesAndroidInjector(modules = HomeFragmentModule.class) + abstract NavigationFragment contributeNavigationFragmentInjector(); + + +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/HomeFragmentModule.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/HomeFragmentModule.java new file mode 100644 index 0000000..9c3cc43 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/HomeFragmentModule.java @@ -0,0 +1,30 @@ +package com.gaolei.mvpmodel.dagger.module; + + +import com.gaolei.mvpmodel.fragment.HomeFragment; +import com.gaolei.mvpmodel.fragment.KnowledgeFragment; +import com.gaolei.mvpmodel.fragment.NavigationFragment; +import com.gaolei.mvpmodel.fragment.ProjectFragment; +import com.gaolei.mvpmodel.fragment.UserFragment; +import com.gaolei.mvpmodel.mpresenter.HomePresenter; + +import dagger.Module; +import dagger.Provides; +import dagger.android.ContributesAndroidInjector; + +/** + *
+ *     author : lex
+ *     e-mail : ldlywt@163.com
+ *     time   : 2018/09/03
+ *     desc   :
+ *     version: 1.0
+ * 
+ */ +@Module +public abstract class HomeFragmentModule { + @Provides + static HomePresenter provideHomePresenter() { + return new HomePresenter(); + } +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/ProjectFragmentModule.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/ProjectFragmentModule.java new file mode 100644 index 0000000..0e22c0e --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/module/ProjectFragmentModule.java @@ -0,0 +1,25 @@ +package com.gaolei.mvpmodel.dagger.module; + + +import com.gaolei.mvpmodel.mpresenter.HomePresenter; +import com.gaolei.mvpmodel.mpresenter.ProjectPresenter; + +import dagger.Module; +import dagger.Provides; + +/** + *
+ *     author : lex
+ *     e-mail : ldlywt@163.com
+ *     time   : 2018/09/03
+ *     desc   :
+ *     version: 1.0
+ * 
+ */ +@Module +public abstract class ProjectFragmentModule { + @Provides + static ProjectPresenter provideProjectPresenter() { + return new ProjectPresenter(); + } +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerActivity.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerActivity.java new file mode 100644 index 0000000..422c9ae --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerActivity.java @@ -0,0 +1,16 @@ +package com.gaolei.mvpmodel.dagger.scope; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +/** + * Created by lw on 2017/1/19. + */ +@Scope +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface PerActivity { +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerApp.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerApp.java new file mode 100644 index 0000000..f94c105 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerApp.java @@ -0,0 +1,16 @@ +package com.gaolei.mvpmodel.dagger.scope; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +/** + * @author woong + */ +@Scope +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface PerApp { +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerFragment.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerFragment.java new file mode 100644 index 0000000..38d078c --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerFragment.java @@ -0,0 +1,16 @@ +package com.gaolei.mvpmodel.dagger.scope; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +/** + * @author woong + */ +@Scope +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface PerFragment { +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerService.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerService.java new file mode 100644 index 0000000..fc3ac73 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/dagger/scope/PerService.java @@ -0,0 +1,16 @@ +package com.gaolei.mvpmodel.dagger.scope; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +/** + * @author woong + */ +@Scope +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface PerService { +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/BaseMvpFragment.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/BaseMvpFragment.java deleted file mode 100644 index c5a0d31..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/BaseMvpFragment.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gaolei.mvpmodel.fragment; - -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; - -import com.gaolei.mvpmodel.mpresenter.BasePresenter; - -/** - * Created by gaolei on 2018/4/26. - */ - - -public abstract class BaseMvpFragment> extends BaseFragment { - - public P mPresenter; - - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mPresenter = initPresenter(); - if (mPresenter != null) - mPresenter.attach((V) this); - } - - @Override - public void onDestroy() { - if (mPresenter != null) - mPresenter.dettach(); - super.onDestroy(); - } - - //实例presenter - public abstract P initPresenter(); -} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/HomeFragment.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/HomeFragment.java index 46c23c6..d425b33 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/HomeFragment.java +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/HomeFragment.java @@ -3,23 +3,27 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.os.Debug; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.util.Log; import android.view.View; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.gaolei.mvpmodel.R; import com.gaolei.mvpmodel.activity.ArticleDetailActivity; +import com.gaolei.mvpmodel.adapter.ArticleListAdapter; import com.gaolei.mvpmodel.adapter.DividerItemDecoration; -import com.gaolei.mvpmodel.adapter.ProjectAdapter; -import com.gaolei.mvpmodel.mmodel.BannerListData; -import com.gaolei.mvpmodel.mmodel.ProjectListData; +import com.gaolei.mvpmodel.base.fragment.BaseMvpFragment; +import com.gaolei.mvpmodel.base.mmodel.ArticleListData; +import com.gaolei.mvpmodel.base.mmodel.ArticleListData.FeedArticleData; +import com.gaolei.mvpmodel.base.mmodel.BannerListData; +import com.gaolei.mvpmodel.mcontract.HomeContract; import com.gaolei.mvpmodel.mpresenter.HomePresenter; -import com.gaolei.mvpmodel.mview.ProjectListView; -import com.gaolei.mvpmodel.net.RestService; -import com.gaolei.mvpmodel.net.UrlConfig; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener; import com.youth.banner.Banner; import com.youth.banner.BannerConfig; import com.youth.banner.Transformer; @@ -29,30 +33,35 @@ import java.util.List; import butterknife.BindView; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; -import retrofit2.converter.gson.GsonConverterFactory; -/** - * @author quchao - * @date 2018/2/11 - */ -public class HomeFragment extends BaseMvpFragment implements ProjectListView { +public class HomeFragment extends BaseMvpFragment implements HomeContract.View { - @BindView(R.id.project_recyclerview) - RecyclerView project_recyclerview; + @BindView(R.id.article_recyclerview) + RecyclerView article_recyclerview; @BindView(R.id.banner) Banner banner; - ProjectAdapter projectAdapter; + @BindView(R.id.smartRefreshLayout_home) + SmartRefreshLayout smartRefreshLayout; + private List articleDataList; + private ArticleListAdapter feedArticleAdapter; +// @Inject +// HomePresenter homePresenter; @Override public void initData(Bundle bundle) { - mPresenter.getProjectInfo(1, 294); - mPresenter.getBannerInfo(); + + Debug.startMethodTracing("traceview"); + + Debug.stopMethodTracing(); + + } + + @Override + public void initView() { + initSmartRefreshLayout(); + initRecyclerView(); } @Override @@ -62,36 +71,36 @@ public int setContentLayout() { @Override public void reload() { - mPresenter.getProjectInfo(1, 294); + mPresenter.getFeedArticleList(0); mPresenter.getBannerInfo(); } - @Override - public HomePresenter initPresenter() { - return new HomePresenter(); - } +// @Override +// public BasePresenter initPresenter() { +// return new HomePresenter(); +// } @Override - public void showLoading() { - setLoading(true); - } + protected void loadData() { + mPresenter.getFeedArticleList(0); + mPresenter.getBannerInfo(); - @Override - public void hideLoading() { - setLoading(false); } @Override - public void requstProjectList(ProjectListData listData) { - final List articleDataList = listData.data.getDatas(); - projectAdapter = new ProjectAdapter(getActivity(), articleDataList); + public void showArticleList(ArticleListData listData, boolean isRefresh) { + final List newDataList = listData.data.getDatas(); + if (isRefresh) { + smartRefreshLayout.finishRefresh(true); + } else { + articleDataList.addAll(newDataList); + feedArticleAdapter.notifyItemRangeInserted(articleDataList.size() - newDataList.size(), newDataList.size()); + feedArticleAdapter.notifyDataSetChanged(); + smartRefreshLayout.finishLoadMore(); + } - project_recyclerview.addItemDecoration(new DividerItemDecoration(getActivity(), - DividerItemDecoration.VERTICAL_LIST)); - project_recyclerview.setLayoutManager(new LinearLayoutManager(getActivity())); - project_recyclerview.setAdapter(projectAdapter); - projectAdapter.setOnItemClickListener(new ProjectAdapter.OnItemClickListener() { + feedArticleAdapter.setOnItemClickListener(new ArticleListAdapter.OnItemClickListener() { @Override public void onItemClick(View v, int position) { Intent intent = new Intent(getActivity(), ArticleDetailActivity.class); @@ -104,14 +113,13 @@ public void onItemClick(View v, int position) { } @Override - public void requstBannerList(BannerListData itemBeans) { + public void showBannerList(BannerListData itemBeans) { final List linkList = new ArrayList(); List imageList = new ArrayList(); List titleList = new ArrayList(); int size = itemBeans.data.size(); - Log.d("gaolei", "url--------------" + itemBeans.data.get(0).getUrl()); - Log.d("gaolei", "title--------------" + itemBeans.data.get(0).getTitle()); + for (int i = 0; i < size; i++) { imageList.add(itemBeans.data.get(i).getImagePath()); titleList.add(itemBeans.data.get(i).getTitle()); @@ -158,4 +166,49 @@ public void OnBannerClick(int position) { }); } + private void initRecyclerView() { + articleDataList = new ArrayList<>(); + feedArticleAdapter = new ArticleListAdapter(getActivity(), articleDataList); + article_recyclerview.addItemDecoration(new DividerItemDecoration(getActivity(), + DividerItemDecoration.VERTICAL_LIST)); + article_recyclerview.setLayoutManager(new LinearLayoutManager(getActivity())); + article_recyclerview.setAdapter(feedArticleAdapter); + article_recyclerview.setLayoutManager(new LinearLayoutManager(getActivity()) { + public boolean canScrollVertically() { + //解决ScrollView里存在多个RecyclerView时滑动卡顿的问题 + //如果你的RecyclerView是水平滑动的话可以重写canScrollHorizontally方法 + return false; + } + }); + } + + //初始化下拉刷新控件 + private void initSmartRefreshLayout() { + smartRefreshLayout.setEnableRefresh(false); + smartRefreshLayout.setEnableLoadMore(true); + smartRefreshLayout.setEnableScrollContentWhenLoaded(true);//是否在加载完成时滚动列表显示新的内容 + smartRefreshLayout.setEnableFooterFollowWhenLoadFinished(true); + smartRefreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { + @Override + public void onLoadMore(RefreshLayout refreshLayout) { + mPresenter.onLoadMore(); + } + + + }); + } + + public void scrollToTop() { + article_recyclerview.scrollToPosition(0); + } + + public void onResume() { + super.onResume(); + + } + + public void onDestroy() { + super.onDestroy(); + } + } diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/KnowledgeFragment.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/KnowledgeFragment.java index 280dbf7..e329f16 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/KnowledgeFragment.java +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/KnowledgeFragment.java @@ -1,26 +1,28 @@ package com.gaolei.mvpmodel.fragment; import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; import com.gaolei.mvpmodel.R; -import com.gaolei.mvpmodel.mpresenter.BasePresenter; +import com.gaolei.mvpmodel.base.fragment.BaseMvpFragment; +import com.gaolei.mvpmodel.base.mmodel.ArticleListData; +import com.gaolei.mvpmodel.base.mmodel.BannerListData; +import com.gaolei.mvpmodel.base.mpresenter.BasePresenter; +import com.gaolei.mvpmodel.mcontract.HomeContract; +import com.gaolei.mvpmodel.mpresenter.HomePresenter; -/** - * @author quchao - * @date 2018/2/11 - */ - -public class KnowledgeFragment extends BaseMvpFragment { +public class KnowledgeFragment extends BaseMvpFragment implements HomeContract.View { @Override public void initData( Bundle bundle) { } + @Override + public void initView() { + + } + @Override public int setContentLayout() { return R.layout.fragment_knowledge; @@ -30,8 +32,23 @@ public int setContentLayout() { public void reload() { } +// @Override +// public BasePresenter initPresenter() { +// return null; +// } + @Override - public BasePresenter initPresenter() { - return null; + protected void loadData() { + + } + + @Override + public void showArticleList(ArticleListData itemBeans, boolean isRefresh) { + + } + + @Override + public void showBannerList(BannerListData itemBeans) { + } } diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/NavigationFragment.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/NavigationFragment.java index 6e8eee0..66eaecc 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/NavigationFragment.java +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/NavigationFragment.java @@ -1,26 +1,33 @@ package com.gaolei.mvpmodel.fragment; import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; import com.gaolei.mvpmodel.R; -import com.gaolei.mvpmodel.mpresenter.BasePresenter; +import com.gaolei.mvpmodel.base.fragment.BaseMvpFragment; +import com.gaolei.mvpmodel.base.mmodel.ArticleListData; +import com.gaolei.mvpmodel.base.mmodel.BannerListData; +import com.gaolei.mvpmodel.base.mpresenter.BasePresenter; +import com.gaolei.mvpmodel.mcontract.HomeContract; +import com.gaolei.mvpmodel.mpresenter.HomePresenter; -/** - * @author quchao - * @date 2018/2/11 - */ +public class NavigationFragment extends BaseMvpFragment implements HomeContract.View { -public class NavigationFragment extends BaseMvpFragment { + @Override + protected void loadData() { + + } @Override public void initData( Bundle bundle) { } + @Override + public void initView() { + + } + @Override public int setContentLayout() { return R.layout.fragment_navigation; @@ -31,7 +38,17 @@ public void reload() { } @Override - public BasePresenter initPresenter() { - return null; + public void showArticleList(ArticleListData itemBeans, boolean isRefresh) { + + } + + @Override + public void showBannerList(BannerListData itemBeans) { + } + +// @Override +// public BasePresenter initPresenter() { +// return null; +// } } diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/ProjectFragment.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/ProjectFragment.java index 7da69dd..86cdda2 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/ProjectFragment.java +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/ProjectFragment.java @@ -1,27 +1,53 @@ package com.gaolei.mvpmodel.fragment; +import android.content.Intent; import android.os.Bundle; -import android.view.LayoutInflater; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.view.View; -import android.view.ViewGroup; import com.gaolei.mvpmodel.R; -import com.gaolei.mvpmodel.mpresenter.BasePresenter; +import com.gaolei.mvpmodel.activity.ArticleDetailActivity; +import com.gaolei.mvpmodel.adapter.DividerItemDecoration; +import com.gaolei.mvpmodel.adapter.ProjectListAdapter; +import com.gaolei.mvpmodel.base.fragment.BaseMvpFragment; +import com.gaolei.mvpmodel.base.mmodel.ProjectListData; +import com.gaolei.mvpmodel.mcontract.ProjectContract; +import com.gaolei.mvpmodel.mpresenter.ProjectPresenter; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener; +import java.util.ArrayList; +import java.util.List; -/** - * @author quchao - * @date 2018/2/11 - */ +import butterknife.BindView; -public class ProjectFragment extends BaseMvpFragment { +public class ProjectFragment extends BaseMvpFragment implements ProjectContract.View { + + @BindView(R.id.project_recyclerview) + RecyclerView project_recyclerview; + @BindView(R.id.smartRefreshLayout_home) + SmartRefreshLayout smartRefreshLayout; + ProjectListAdapter projectAdapter; + private List projectDataList; + @Override - public void initData( Bundle bundle) { + public void initData(Bundle bundle) { + + + mPresenter.getProjectInfo(1, 294); } + @Override + public void initView() { + initSmartRefreshLayout(); + initRecyclerView(); + } + @Override public int setContentLayout() { return R.layout.fragment_project; @@ -29,10 +55,74 @@ public int setContentLayout() { @Override public void reload() { + mPresenter.getProjectInfo(1, 294); + } + +// @Override +// public BasePresenter initPresenter() { +// return new ProjectPresenter(); +// } + + @Override + protected void loadData() { + + mPresenter.getProjectInfo(1, 294); } + @Override - public BasePresenter initPresenter() { - return null; + public void showProjectList(ProjectListData listData, boolean isRefresh) { + final List newDataList = listData.data.getDatas(); + + if (isRefresh) { +// mAdapter.replaceData(feedArticleListData.getDatas()); + smartRefreshLayout.finishRefresh(true); + } else { + projectDataList.addAll(newDataList); + projectAdapter.notifyItemRangeInserted(projectDataList.size() - newDataList.size(), newDataList.size()); + projectAdapter.notifyDataSetChanged(); + smartRefreshLayout.finishLoadMore(); + } + + projectAdapter.setOnItemClickListener(new ProjectListAdapter.OnItemClickListener() { + @Override + public void onItemClick(View v, int position) { + Intent intent = new Intent(getActivity(), ArticleDetailActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("url", projectDataList.get(position).getLink()); + intent.putExtras(bundle); + startActivity(intent); + } + }); + } + + private void initRecyclerView() { + projectDataList = new ArrayList<>(); + projectAdapter = new ProjectListAdapter(getActivity(), projectDataList); + project_recyclerview.addItemDecoration(new DividerItemDecoration(getActivity(), + DividerItemDecoration.VERTICAL_LIST)); + project_recyclerview.setLayoutManager(new LinearLayoutManager(getActivity())); + project_recyclerview.setAdapter(projectAdapter); + } + + //初始化下拉刷新控件 + private void initSmartRefreshLayout() { + + smartRefreshLayout.setEnableScrollContentWhenLoaded(true);//是否在加载完成时滚动列表显示新的内容 + smartRefreshLayout.setEnableFooterFollowWhenLoadFinished(true); + smartRefreshLayout.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() { + @Override + public void onLoadMore(RefreshLayout refreshLayout) { + mPresenter.onLoadMore(294); + } + + @Override + public void onRefresh(RefreshLayout refreshLayout) { + mPresenter.onRefreshMore(294); + } + }); + } + public void scrollToTop(){ + project_recyclerview.scrollToPosition(0); } } diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/UserFragment.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/UserFragment.java new file mode 100644 index 0000000..7a95295 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/UserFragment.java @@ -0,0 +1,56 @@ +package com.gaolei.mvpmodel.fragment; + +import android.os.Bundle; + +import com.gaolei.mvpmodel.R; +import com.gaolei.mvpmodel.base.fragment.BaseMvpFragment; +import com.gaolei.mvpmodel.base.mmodel.ArticleListData; +import com.gaolei.mvpmodel.base.mmodel.BannerListData; +import com.gaolei.mvpmodel.base.mpresenter.BasePresenter; +import com.gaolei.mvpmodel.mcontract.HomeContract; +import com.gaolei.mvpmodel.mpresenter.HomePresenter; + + +public class UserFragment extends BaseMvpFragment implements HomeContract.View { + + + @Override + public void initData( Bundle bundle) { + + } + + @Override + public void initView() { + + } + + @Override + public int setContentLayout() { + return R.layout.fragment_user; + } + + @Override + public void reload() { + } + +// @Override +// public BasePresenter initPresenter() { +// return null; +// } + + + @Override + protected void loadData() { + + } + + @Override + public void showArticleList(ArticleListData itemBeans, boolean isRefresh) { + + } + + @Override + public void showBannerList(BannerListData itemBeans) { + + } +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mcontract/HomeContract.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mcontract/HomeContract.java new file mode 100644 index 0000000..c178675 --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mcontract/HomeContract.java @@ -0,0 +1,30 @@ +package com.gaolei.mvpmodel.mcontract; + +import com.gaolei.mvpmodel.base.mmodel.BannerListData; +import com.gaolei.mvpmodel.base.mmodel.ArticleListData; + +/** + * Created by gaolei on 2018/6/18. + */ + +public class HomeContract { + + public interface Presenter { + + /** + * Get feed article list + */ + void getFeedArticleList(int num); + + void getBannerInfo(); + + void onLoadMore(); + } + + public interface View { + + void showArticleList(ArticleListData itemBeans, boolean isRefresh); + + void showBannerList(BannerListData itemBeans); + } +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mcontract/ProjectContract.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mcontract/ProjectContract.java new file mode 100644 index 0000000..dea722d --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mcontract/ProjectContract.java @@ -0,0 +1,24 @@ +package com.gaolei.mvpmodel.mcontract; + +import com.gaolei.mvpmodel.base.mmodel.ProjectListData; + +/** + * Created by gaolei on 2018/6/18. + */ + +public class ProjectContract { + + public interface Presenter { + + void getProjectInfo(int page, int cid); + + void onRefreshMore(int cid); + + void onLoadMore(int cid); + } + + public interface View { + + void showProjectList(ProjectListData itemBeans, boolean isRefresh); + } +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/BasePresenter.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/BasePresenter.java deleted file mode 100644 index 16c7ba7..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/BasePresenter.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gaolei.mvpmodel.mpresenter; - -import com.gaolei.mvpmodel.net.RestApiProvider; -import com.gaolei.mvpmodel.net.RestService; - -import retrofit2.Call; - -public abstract class BasePresenter { - - public V mView; - public Call mCall; - public RestService mRestService = RestApiProvider.getInstance().withNoInterceptor().builder().getApiService(); - - - /** - * 绑定View - * - * @param view - */ - public void attach(V view) { - this.mView = view; - } - - /** - * 释放View - */ - public void dettach() { - this.mView = null; - if (mCall != null) { - mCall.cancel(); - } - } -} \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/HomePresenter.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/HomePresenter.java index 62443a3..9d969f4 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/HomePresenter.java +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/HomePresenter.java @@ -1,64 +1,62 @@ package com.gaolei.mvpmodel.mpresenter; -import com.gaolei.mvpmodel.mmodel.BannerListData; -import com.gaolei.mvpmodel.mmodel.ProjectListData; -import com.gaolei.mvpmodel.mview.ProjectListView; -import com.gaolei.mvpmodel.net.RestService; -import com.gaolei.mvpmodel.net.UrlConfig; +import com.gaolei.mvpmodel.base.mmodel.ArticleListData; +import com.gaolei.mvpmodel.base.mmodel.BannerListData; +import com.gaolei.mvpmodel.base.mpresenter.BasePresenter; +import com.gaolei.mvpmodel.mcontract.HomeContract; +import com.gaolei.mvpmodel.thirdframe.rxjava.BaseObserver; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; -import retrofit2.converter.gson.GsonConverterFactory; +import javax.inject.Inject; -/** - * Created by caiwancheng on 2017/8/30. - */ +import io.reactivex.Observable; -public class HomePresenter extends BasePresenter { - public void getProjectInfo(int page, int cid) { - mCall = mRestService.getProjectListData(page, cid); - mView.showLoading(); - mCall.enqueue(new Callback() { - public void onResponse(Call call, Response response) { - mView.hideLoading(); +public class HomePresenter extends BasePresenter implements HomeContract.Presenter { + private boolean isRefresh = true; + private int mCurrentPage = 0; + @Inject + public HomePresenter() { + } - mView.requstProjectList(response.body()); + @Override + public void onLoadMore() { + ++mCurrentPage; + Observable observable = mRestService.getFeedArticleList(mCurrentPage); + addSubscribe(observable, new BaseObserver(false) { + @Override + public void onNext(ArticleListData feedArticleListData) { + mView.showArticleList(feedArticleListData, false); } + }); + } - public void onFailure(Call call, Throwable t) { - mView.hideLoading(); - + @Override + public void getFeedArticleList(int num) { + Observable observable = mRestService.getFeedArticleList(num); + addSubscribe(observable, new BaseObserver(true) { + @Override + public void onNext(ArticleListData feedArticleListData) { + mView.showArticleList(feedArticleListData, false); } }); } + + @Override public void getBannerInfo() { -// Retrofit mRetrofit = new Retrofit.Builder() -// .baseUrl(UrlConfig.BASE_URL) -// .addConverterFactory(GsonConverterFactory.create()) -// //.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) -// .build(); -// RestService mRestService = mRetrofit.create(RestService.class); - mCall = mRestService.getBannerListData(); - mView.showLoading(); - mCall.enqueue(new Callback() { - public void onResponse(Call call, Response response) { - mView.hideLoading(); - - mView.requstBannerList(response.body()); + Observable observable = mRestService.getBannerListData(); + addSubscribe(observable, new BaseObserver(true) { + @Override + public void onNext(BannerListData bannerListData) { + mView.showBannerList(bannerListData); } - public void onFailure(Call call, Throwable t) { - mView.hideLoading(); - - } }); + + } } diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/ProjectPresenter.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/ProjectPresenter.java new file mode 100644 index 0000000..ef7f73b --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mpresenter/ProjectPresenter.java @@ -0,0 +1,52 @@ +package com.gaolei.mvpmodel.mpresenter; + + +import com.gaolei.mvpmodel.base.mmodel.ProjectListData; +import com.gaolei.mvpmodel.base.mpresenter.BasePresenter; +import com.gaolei.mvpmodel.mcontract.ProjectContract; +import com.gaolei.mvpmodel.thirdframe.rxjava.BaseObserver; + +import io.reactivex.Observable; + + +public class ProjectPresenter extends BasePresenter implements ProjectContract.Presenter { + + private int mCurrentPage = 1; + + @Override + public void getProjectInfo(int page, int cid) { + Observable observable = mRestService.getProjectListData(page, cid); + addSubscribe(observable, new BaseObserver(true) { + @Override + public void onNext(ProjectListData projectListData) { + mView.showProjectList(projectListData, false); + } + }); + } + + @Override + public void onRefreshMore(int cid) { + Observable observable = mRestService.getProjectListData(-1, cid); + addSubscribe(observable, new BaseObserver(false) { + @Override + public void onNext(ProjectListData projectListData) { + mView.showProjectList(projectListData, true); + } + }); + } + + @Override + public void onLoadMore(int cid) { + ++mCurrentPage; + Observable observable = mRestService.getProjectListData(mCurrentPage, cid); + addSubscribe(observable, new BaseObserver(false) { + @Override + public void onNext(ProjectListData projectListData) { + mView.showProjectList(projectListData, false); + } + }); + } + + +} + diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mview/BaseView.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mview/BaseView.java deleted file mode 100644 index 155db4c..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mview/BaseView.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.gaolei.mvpmodel.mview; - -public interface BaseView { - - void showLoading(); - void hideLoading(); -} \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mview/ProjectListView.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mview/ProjectListView.java deleted file mode 100644 index 1255d52..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mview/ProjectListView.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gaolei.mvpmodel.mview; - - -import com.gaolei.mvpmodel.mmodel.BannerListData; -import com.gaolei.mvpmodel.mmodel.ProjectListData; - -import java.util.List; - -/** - * 倒计时mview - * Created by caiwancheng on 2017/8/29. - */ - -public interface ProjectListView extends BaseView { - - - void requstProjectList(ProjectListData itemBeans); - void requstBannerList(BannerListData itemBeans); -} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/HttpLoggingInterceptor.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/HttpLoggingInterceptor.java deleted file mode 100644 index 8cb857e..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/HttpLoggingInterceptor.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.gaolei.mvpmodel.net; - -import android.support.v4.BuildConfig; -import android.util.Log; - - -import java.io.IOException; - -import okhttp3.Interceptor; -import okhttp3.Request; -import okhttp3.Response; - -/** - * Created by liuhaiyang on 2016/9/6. - */ -public class HttpLoggingInterceptor implements Interceptor { - @Override - public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - - long t1 = System.nanoTime(); - - if (BuildConfig.DEBUG) { - Log.i("HTTP", String.format("----> %s %s on %s %n%s", - request.method(), request.url(), chain.connection(), request.headers())); - } - - - Response response = chain.proceed(request); - - long t2 = System.nanoTime(); - - if (BuildConfig.DEBUG) { - Log.i("HTTP", String.format("----> %s %s (%.1fms) %n%s", response.code(), - response.request().url(), (t2 - t1) / 1e6d, response.headers())); - } - - - return response; - } -} \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/OkHttpUtil.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/OkHttpUtil.java deleted file mode 100644 index 8cdb4d2..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/OkHttpUtil.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.gaolei.mvpmodel.net; - - -import java.io.IOException; -import java.util.Map; -import java.util.Set; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.FormBody; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - -/** - * Created by gaolei on 2018/4/27. - */ - -public class OkHttpUtil { - //静态本类对象 - private static OkHttpUtil okHttpUtil; - private OkHttpClient okHttpClient; - - //私有化构造方法 - private OkHttpUtil() { - okHttpClient = new OkHttpClient.Builder().build(); - } - - //公共的供外部访问的方法 - public static OkHttpUtil getInstance() { - if (okHttpUtil == null) { - synchronized (OkHttpUtil.class) { - if (okHttpUtil == null) { - okHttpUtil = new OkHttpUtil(); - } - } - } - return okHttpUtil; - } - - public void get(String url, Map map, final NetworkCallback networkCallback) { - - if (map != null && map.size() > 0) { - - StringBuffer sb = new StringBuffer(url); - sb.append("?"); - Set set = map.keySet(); - for (String str : set) { - - sb.append(str).append("=").append(map.get(str)).append("&"); - } - url = sb.substring(0, sb.length() - 1); - } - - Request request = new Request.Builder().url(url).build(); - okHttpClient.newCall(request).enqueue(new Callback() { - @Override - public void onFailure(Call call, IOException e) { - networkCallback.error(e.getMessage()); - } - - @Override - public void onResponse(Call call, Response response) throws IOException { - String string = response.body().string(); - networkCallback.successful(string); - } - }); - } - - public void post(String url, Map map, final NetworkCallback networkCallback) { - if (map != null && map.size() > 0) { - - StringBuffer sb = new StringBuffer(url); - sb.append("?"); - Set set = map.keySet(); - for (String str : set) { - - sb.append(str).append("=").append(map.get(str)).append("&"); - } - url = sb.substring(0, sb.length() - 1); - } - - RequestBody body = new FormBody.Builder().build(); - Request request = new Request.Builder().url(url).method("POST", body).build(); - okHttpClient.newCall(request).enqueue(new Callback() { - @Override - public void onFailure(Call call, IOException e) { - networkCallback.error(e.getMessage()); - } - - @Override - public void onResponse(Call call, Response response) throws IOException { - String string = response.body().string(); - networkCallback.successful(string); - } - }); - } - - public interface NetworkCallback{ - void error(String error); - void successful(String response); - } -} \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/RestApiProvider.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/RestApiProvider.java deleted file mode 100644 index 90568dc..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/RestApiProvider.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.gaolei.mvpmodel.net; - - -import okhttp3.CertificatePinner; -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import retrofit2.Retrofit; -import retrofit2.converter.gson.GsonConverterFactory; - - -public final class RestApiProvider { - - private Retrofit mRetrofit; - private OkHttpClient mOkHttpClient; - private static volatile RestApiProvider sInstance; - private RestService restService; - - private RestApiProvider() { - } - - - public RestApiProvider withInterceptor(Interceptor intertor, CertificatePinner pinner) { - if (mOkHttpClient == null) { - mOkHttpClient = new OkHttpClient.Builder() - .addNetworkInterceptor(new HttpLoggingInterceptor()) - .addInterceptor(intertor) - .certificatePinner(pinner) - .build(); - } - return sInstance; - } - - public RestApiProvider withNoInterceptor() { - - - if (mOkHttpClient == null) { - mOkHttpClient = new OkHttpClient.Builder() - .addNetworkInterceptor(new HttpLoggingInterceptor()) - .build(); - } - return sInstance; - } - - public RestApiProvider builder() { - if (mOkHttpClient == null) { - mOkHttpClient = new OkHttpClient.Builder() - .addNetworkInterceptor(new HttpLoggingInterceptor()) - .build(); - } - if (mRetrofit == null) { - mRetrofit = new Retrofit.Builder() - .client(mOkHttpClient) - .baseUrl(UrlConfig.BASE_URL) - .addConverterFactory(GsonConverterFactory.create()) - //.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) - .build(); - } - return sInstance; - } - - public static RestApiProvider getInstance() { - if (sInstance == null) { - synchronized (RestApiProvider.class) { - if (sInstance == null) { - sInstance = new RestApiProvider(); - } - } - } - return sInstance; - } - - public RestService getApiService() { - if (restService == null) - restService = mRetrofit.create(RestService.class); - return restService; - } -} \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/RestService.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/RestService.java deleted file mode 100644 index f9a3682..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/RestService.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gaolei.mvpmodel.net; - - -import com.gaolei.mvpmodel.mmodel.BannerListData; -import com.gaolei.mvpmodel.mmodel.ProjectListData; - -import java.util.List; - -import retrofit2.Call; -import retrofit2.http.GET; -import retrofit2.http.Path; -import retrofit2.http.Query; - -/** - * Created by liuhaiyang on 2016/9/6. - */ -public interface RestService { -// @GET -// Call loadHomeList(@Url String url, @Query("strRecord") int strRecord, @Query("pageSize") int pageSize); -// -// @GET -// Call loadData(@Url String url, @QueryMap Map map); -// -// @GET -// Call loadData(@Url String url); -// -// -// @POST -// Call postData(@Url String url, @Body Object body); -// -// -// @FormUrlEncoded -// @POST -// Call login(@Url String url, @Field("username") String username, -// @Field("password") String pwd -// ); -/* - http://www.wanandroid.com/project/list/1/json?cid=294 - 方法:GET - 参数:cid 分类的id,页码:拼接在链接中,从1开始。 - */ - @GET("project/list/{page}/json") - Call getProjectListData(@Path("page") int page, @Query("cid") int cid); -/* - http://www.wanandroid.com/banner/json - 广告栏数据 -*/ - - @GET("banner/json") - Call getBannerListData(); -} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/SignInterceptor.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/SignInterceptor.java deleted file mode 100644 index 18b70e0..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/SignInterceptor.java +++ /dev/null @@ -1,161 +0,0 @@ -//package com.gaolei.mvpmodel.net; -// -//import android.content.Context; -//import android.support.v4.util.ArrayMap; -//import android.util.Log; -//import android.util.Pair; -// -//import org.json.JSONException; -//import org.json.JSONObject; -// -//import java.io.IOException; -//import java.nio.charset.Charset; -//import java.util.ArrayList; -//import java.util.Collections; -//import java.util.Comparator; -//import java.util.Iterator; -//import java.util.List; -// -//import okhttp3.FormBody; -//import okhttp3.Interceptor; -//import okhttp3.MediaType; -//import okhttp3.Request; -//import okhttp3.RequestBody; -//import okhttp3.Response; -//import okio.Buffer; -// -///** -// * Created by liuhaiyang on 2017/8/9. -// * 加密sign -// */ -// -//public final class SignInterceptor implements Interceptor { -// -// private static final String MD5KEY = "base64:FgBvWS7+m3BPRnKemuoOwXEf7kvldmM+VOmJS5Iccxs="; -// private Context mContext; -// -// public SignInterceptor(Context context) { -// this.mContext = context; -// } -// -// @Override -// public Response intercept(Chain chain) throws IOException { -// -// Request request = chain.request(); -// -// //header add version -// Request.Builder requestBuilder = request.newBuilder(); -// requestBuilder.addHeader("version", BuildConfig.VERSION_NAME); -// requestBuilder.addHeader("platform", "ANDROID"); -// requestBuilder.addHeader("deviceid", ExtendUtil.getDeviceID(mContext)); -// -// if (!request.method().equals("POST")) { -// return chain.proceed(request); -// } -// -// JSONObject bodyJson = null; -// List> params = new ArrayList<>(); -// ArrayMap arrayMap = new ArrayMap<>(); -// -// FormBody body = null; -// try { -// body = (FormBody) request.body(); -// } catch (ClassCastException c) { -// } -// -// if (body != null) { -// -// int size = body.size(); -// if (size > 0) { -// for (int i = 0; i < size; i++) { -// params.add(new Pair<>(body.name(i), body.value(i))); -// } -// } -// } else { -// RequestBody requestBody = request.body(); -// -// if (requestBody != null) { -// Buffer buffer = new Buffer(); -// requestBody.writeTo(buffer); -// Charset charset = Charset.forName("UTF-8"); -// MediaType contentType = requestBody.contentType(); -// if (contentType != null) { -// charset = contentType.charset(charset); -// } -// String paramsStr = buffer.readString(charset); -// if (BuildConfig.DEBUG) { -// Log.i("HTTP", "request = " + paramsStr); -// } -// -// try { -// bodyJson = new JSONObject(paramsStr); -// } catch (JSONException e) { -// LogUtils.e("JSON", "JsonObject err"); -// } -// -// if (bodyJson != null) { -// Iterator it = bodyJson.keys(); -// while (it.hasNext()) { -// String key = it.next(); -// Object value = null; -// try { -// value = bodyJson.get(key); -// } catch (JSONException e) { -// LogUtils.e("JSON", "JsonObject get err"); -// } -// if (key.equals("token")) { -// arrayMap.put("token", String.valueOf(value)); -// arrayMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000)); -// -// for (String strKey : arrayMap.keySet()) { -// params.add(new Pair<>(strKey, arrayMap.get(strKey))); -// } -// } else { -// params.add(new Pair<>(key, String.valueOf(value))); -// } -// -// } -// } -// -// } -// } -// -// params.add(new Pair<>("MD5Key", MD5KEY)); -// Collections.sort(params, new Comparator>() { -// @Override -// public int compare(Pair lhs, Pair rhs) { -// return lhs.second.compareTo(rhs.second); -// } -// }); -// -// StringBuilder sb = new StringBuilder(); -// for (int i = 0; i < params.size(); i++) { -// sb.append(params.get(i).second); -// if (i < params.size() - 1) { -// sb.append(""); -// } -// } -// -// String sign = StringUtil.md5Encode(sb.toString()); -// params.add(new Pair<>("sign", sign)); -// -// for (Pair pair : params) { -// if ((arrayMap.containsKey(pair.first) || pair.first.equals("sign")) && bodyJson != null) { -// try { -// bodyJson.put(pair.first, pair.second); -// } catch (JSONException e) { -// LogUtils.e("JSON", "JsonObject put err"); -// } -// } -// } -// -// String postBodyString = bodyJson.toString(); -// request = requestBuilder -// .post(RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), -// postBodyString)) -// .build(); -// -// return chain.proceed(request); -// } -// -//} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/UrlConfig.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/UrlConfig.java deleted file mode 100644 index 1d66eb5..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/net/UrlConfig.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gaolei.mvpmodel.net; - - -import retrofit2.http.GET; - -/** - * Created by liuhaiyang on 2017/8/9. - */ - -public final class UrlConfig { - -// -public static final String BASE_URL = "http://www.wanandroid.com/"; - -} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/utils/NetworkUtil.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/utils/NetworkUtil.java deleted file mode 100644 index 339bdca..0000000 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/utils/NetworkUtil.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gaolei.mvpmodel.utils; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; - -public class NetworkUtil { - - /** - * 检查网络是否可用 - * - * @param context - * @return - */ - public static boolean isNetworkAvailable(Context context) { - - ConnectivityManager manager = (ConnectivityManager) context - .getApplicationContext().getSystemService( - Context.CONNECTIVITY_SERVICE); - - if (manager == null) { - return false; - } - - NetworkInfo networkinfo = manager.getActiveNetworkInfo(); - - if (networkinfo == null || !networkinfo.isAvailable()) { - return false; - } - - return true; - } - -} \ No newline at end of file diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/view/CustomViewPager.java b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/view/CustomViewPager.java new file mode 100644 index 0000000..90c759c --- /dev/null +++ b/MVPModel/app/src/main/java/com/gaolei/mvpmodel/view/CustomViewPager.java @@ -0,0 +1,42 @@ +package com.gaolei.mvpmodel.view; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; + + + +public class CustomViewPager extends ViewPager { + + + public boolean canScroll=true; + + public CustomViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CustomViewPager(Context context) { + super(context); + } + + + public void setCanScroll(boolean canScroll) { + this.canScroll = canScroll; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return canScroll && super.onTouchEvent(ev); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return canScroll && super.onInterceptTouchEvent(ev); + } + + @Override + public void setCurrentItem(int item) { + setCurrentItem(item, false); + } +} diff --git a/MVPModel/app/src/main/res/anim/anim_dialog_load.xml b/MVPModel/app/src/main/res/anim/anim_dialog_load.xml new file mode 100644 index 0000000..51a4d13 --- /dev/null +++ b/MVPModel/app/src/main/res/anim/anim_dialog_load.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/MVPModel/app/src/main/res/anim/request_progress_loading.xml b/MVPModel/app/src/main/res/anim/anim_progress_load.xml similarity index 100% rename from MVPModel/app/src/main/res/anim/request_progress_loading.xml rename to MVPModel/app/src/main/res/anim/anim_progress_load.xml diff --git a/MVPModel/app/src/main/res/color/selector_tab_text.xml b/MVPModel/app/src/main/res/color/selector_tab_text.xml new file mode 100644 index 0000000..740b889 --- /dev/null +++ b/MVPModel/app/src/main/res/color/selector_tab_text.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/common_textcolor_states.xml b/MVPModel/app/src/main/res/drawable-xhdpi/common_textcolor_states.xml deleted file mode 100644 index 6c95c89..0000000 --- a/MVPModel/app/src/main/res/drawable-xhdpi/common_textcolor_states.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/default_project_img.jpg b/MVPModel/app/src/main/res/drawable-xhdpi/default_project_img.jpg new file mode 100755 index 0000000..5d3a1f7 Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xhdpi/default_project_img.jpg differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_home_pager_not_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_home_pager_not_selected.png deleted file mode 100644 index 83d161f..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_home_pager_not_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_home_pager_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_home_pager_selected.png deleted file mode 100644 index dc2b26e..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_home_pager_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_knowledge_hierarchy_not_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_knowledge_hierarchy_not_selected.png deleted file mode 100644 index 3870703..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_knowledge_hierarchy_not_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_knowledge_hierarchy_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_knowledge_hierarchy_selected.png deleted file mode 100644 index bcfdbce..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_knowledge_hierarchy_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_like_article_select.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_like_article_select.png new file mode 100644 index 0000000..9d1d750 Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xhdpi/icon_like_article_select.png differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_like_article_unselect.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_like_article_unselect.png new file mode 100644 index 0000000..8cb98aa Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xhdpi/icon_like_article_unselect.png differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_me_not_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_me_not_selected.png deleted file mode 100644 index e876d0b..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_me_not_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_me_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_me_selected.png deleted file mode 100644 index 9430e23..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_me_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_navigation_not_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_navigation_not_selected.png deleted file mode 100644 index 491a016..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_navigation_not_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_navigation_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_navigation_selected.png deleted file mode 100644 index 2a1e47c..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_navigation_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_project_not_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_project_not_selected.png deleted file mode 100644 index 5b675ff..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_project_not_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_project_selected.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_project_selected.png deleted file mode 100644 index 5c63971..0000000 Binary files a/MVPModel/app/src/main/res/drawable-xhdpi/icon_project_selected.png and /dev/null differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/icon_time.png b/MVPModel/app/src/main/res/drawable-xhdpi/icon_time.png new file mode 100644 index 0000000..7ef5ff1 Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xhdpi/icon_time.png differ diff --git a/MVPModel/app/src/main/res/drawable-xhdpi/nav_item_color_state.xml b/MVPModel/app/src/main/res/drawable-xhdpi/nav_item_color_state.xml deleted file mode 100644 index aa16206..0000000 --- a/MVPModel/app/src/main/res/drawable-xhdpi/nav_item_color_state.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_home_tab_select.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_home_tab_select.png new file mode 100644 index 0000000..6c182b2 Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_home_tab_select.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_home_tab_unselect.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_home_tab_unselect.png new file mode 100644 index 0000000..b344af4 Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_home_tab_unselect.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_knowledge_tab_select.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_knowledge_tab_select.png new file mode 100644 index 0000000..c4ad471 Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_knowledge_tab_select.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_knowledge_tab_unselect.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_knowledge_tab_unselect.png new file mode 100644 index 0000000..896ddb8 Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_knowledge_tab_unselect.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_mine_tab_select.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_mine_tab_select.png new file mode 100644 index 0000000..244686c Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_mine_tab_select.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_mine_tab_unselect.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_mine_tab_unselect.png new file mode 100644 index 0000000..d0a3bfb Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_mine_tab_unselect.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_navigation_tab_select.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_navigation_tab_select.png new file mode 100644 index 0000000..04e30e9 Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_navigation_tab_select.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_navigation_tab_unselect.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_navigation_tab_unselect.png new file mode 100644 index 0000000..4ad307c Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_navigation_tab_unselect.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_project_tab_select.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_project_tab_select.png new file mode 100644 index 0000000..19e9ae1 Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_project_tab_select.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/icon_project_tab_unselect.png b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_project_tab_unselect.png new file mode 100644 index 0000000..e140dfe Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/icon_project_tab_unselect.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxhdpi/progress_dialog_icon.png b/MVPModel/app/src/main/res/drawable-xxhdpi/progress_dialog_icon.png new file mode 100644 index 0000000..ccc722b Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxhdpi/progress_dialog_icon.png differ diff --git a/MVPModel/app/src/main/res/drawable-xxxhdpi/progress_dialog_icon.png b/MVPModel/app/src/main/res/drawable-xxxhdpi/progress_dialog_icon.png new file mode 100644 index 0000000..ccc722b Binary files /dev/null and b/MVPModel/app/src/main/res/drawable-xxxhdpi/progress_dialog_icon.png differ diff --git a/MVPModel/app/src/main/res/drawable/selected_radius.xml b/MVPModel/app/src/main/res/drawable/banner_selected_radius.xml similarity index 100% rename from MVPModel/app/src/main/res/drawable/selected_radius.xml rename to MVPModel/app/src/main/res/drawable/banner_selected_radius.xml diff --git a/MVPModel/app/src/main/res/drawable/tab_selector_home.xml b/MVPModel/app/src/main/res/drawable/tab_selector_home.xml new file mode 100644 index 0000000..dde85d6 --- /dev/null +++ b/MVPModel/app/src/main/res/drawable/tab_selector_home.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/drawable/tab_selector_knowledge.xml b/MVPModel/app/src/main/res/drawable/tab_selector_knowledge.xml new file mode 100644 index 0000000..feeeaa1 --- /dev/null +++ b/MVPModel/app/src/main/res/drawable/tab_selector_knowledge.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/drawable/tab_selector_mine.xml b/MVPModel/app/src/main/res/drawable/tab_selector_mine.xml new file mode 100644 index 0000000..f21ede0 --- /dev/null +++ b/MVPModel/app/src/main/res/drawable/tab_selector_mine.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/drawable/tab_selector_novagation.xml b/MVPModel/app/src/main/res/drawable/tab_selector_novagation.xml new file mode 100644 index 0000000..dc4267c --- /dev/null +++ b/MVPModel/app/src/main/res/drawable/tab_selector_novagation.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/drawable/tab_selector_project.xml b/MVPModel/app/src/main/res/drawable/tab_selector_project.xml new file mode 100644 index 0000000..c5ed4ce --- /dev/null +++ b/MVPModel/app/src/main/res/drawable/tab_selector_project.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/layout/activity_article_detail.xml b/MVPModel/app/src/main/res/layout/activity_article_detail.xml index fc481a2..94f60bb 100644 --- a/MVPModel/app/src/main/res/layout/activity_article_detail.xml +++ b/MVPModel/app/src/main/res/layout/activity_article_detail.xml @@ -5,30 +5,11 @@ android:layout_height="match_parent" android:orientation="vertical"> - - - - - - - - - - - - - - - - - - - - - - + - diff --git a/MVPModel/app/src/main/res/layout/activity_base.xml b/MVPModel/app/src/main/res/layout/activity_base.xml index ddeeb92..8592a3b 100644 --- a/MVPModel/app/src/main/res/layout/activity_base.xml +++ b/MVPModel/app/src/main/res/layout/activity_base.xml @@ -8,7 +8,7 @@ + android:background="@color/app_color"> - - - - - - - - - - - + android:layout_height="45dp" /> + + + - - + app:tabIndicatorColor="@color/app_color" + app:tabIndicatorHeight="0dp"> + + + diff --git a/MVPModel/app/src/main/res/layout/activity_splash.xml b/MVPModel/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..097d63e --- /dev/null +++ b/MVPModel/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/MVPModel/app/src/main/res/layout/dialog_loading.xml b/MVPModel/app/src/main/res/layout/dialog_loading.xml new file mode 100644 index 0000000..15bdcfd --- /dev/null +++ b/MVPModel/app/src/main/res/layout/dialog_loading.xml @@ -0,0 +1,30 @@ + + + + + + + + + diff --git a/MVPModel/app/src/main/res/layout/fragment_base.xml b/MVPModel/app/src/main/res/layout/fragment_base.xml index 01a81a4..33e70f2 100644 --- a/MVPModel/app/src/main/res/layout/fragment_base.xml +++ b/MVPModel/app/src/main/res/layout/fragment_base.xml @@ -11,7 +11,7 @@ - + @@ -46,7 +46,7 @@ android:layout_width="68dp" android:layout_height="68dp" android:layout_centerInParent="true" - android:indeterminateDrawable="@anim/request_progress_loading" /> + android:indeterminateDrawable="@anim/anim_progress_load" /> diff --git a/MVPModel/app/src/main/res/layout/fragment_home.xml b/MVPModel/app/src/main/res/layout/fragment_home.xml index 11359a4..c317e4c 100644 --- a/MVPModel/app/src/main/res/layout/fragment_home.xml +++ b/MVPModel/app/src/main/res/layout/fragment_home.xml @@ -4,21 +4,67 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> - + - + android:layout_height="match_parent"> + + + + + + + + + + + + + + + + + + + + diff --git a/MVPModel/app/src/main/res/layout/fragment_knowledge.xml b/MVPModel/app/src/main/res/layout/fragment_knowledge.xml index aa48255..b9afc8e 100644 --- a/MVPModel/app/src/main/res/layout/fragment_knowledge.xml +++ b/MVPModel/app/src/main/res/layout/fragment_knowledge.xml @@ -9,7 +9,7 @@ android:layout_height="wrap_content" android:textSize="18sp" android:layout_centerInParent="true" - android:text="@string/knowledge_hierarchy" /> + android:text="@string/knowledge" /> diff --git a/MVPModel/app/src/main/res/layout/fragment_project.xml b/MVPModel/app/src/main/res/layout/fragment_project.xml index ee3cd68..9db4590 100644 --- a/MVPModel/app/src/main/res/layout/fragment_project.xml +++ b/MVPModel/app/src/main/res/layout/fragment_project.xml @@ -1,16 +1,27 @@ - - + android:layout_height="match_parent" + android:orientation="vertical"> + + - + + - - + + + diff --git a/MVPModel/app/src/main/res/layout/fragment_user.xml b/MVPModel/app/src/main/res/layout/fragment_user.xml new file mode 100644 index 0000000..79ac68a --- /dev/null +++ b/MVPModel/app/src/main/res/layout/fragment_user.xml @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/MVPModel/app/src/main/res/layout/item_article_list.xml b/MVPModel/app/src/main/res/layout/item_article_list.xml new file mode 100644 index 0000000..d256aaa --- /dev/null +++ b/MVPModel/app/src/main/res/layout/item_article_list.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + diff --git a/MVPModel/app/src/main/res/layout/item_project_list.xml b/MVPModel/app/src/main/res/layout/item_project_list.xml index 8556ce3..a423582 100644 --- a/MVPModel/app/src/main/res/layout/item_project_list.xml +++ b/MVPModel/app/src/main/res/layout/item_project_list.xml @@ -4,10 +4,10 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="8dp" - android:layout_marginEnd="12dp" android:layout_marginStart="12dp" android:layout_marginTop="8dp" + android:layout_marginEnd="12dp" + android:layout_marginBottom="8dp" android:clickable="true" android:focusable="true"> @@ -15,34 +15,31 @@ android:layout_width="match_parent" android:layout_height="180dp" android:orientation="horizontal" - android:padding="12dp"> + android:padding="10dp"> + android:contentDescription="@null" /> + android:layout_marginLeft="12dp"> + android:textColor="@color/color_5b5d5c" + android:textSize="16sp" /> + android:maxLines="3" + android:textColor="@color/color_5b5d5c" /> - + android:layout_alignParentBottom="true" + android:layout_marginBottom="8dp"> - + + + + + + diff --git a/MVPModel/app/src/main/res/layout/layout_error_page.xml b/MVPModel/app/src/main/res/layout/layout_error_page.xml index e9c3c90..6e313b7 100644 --- a/MVPModel/app/src/main/res/layout/layout_error_page.xml +++ b/MVPModel/app/src/main/res/layout/layout_error_page.xml @@ -32,6 +32,5 @@ android:layout_margin="36dp" android:gravity="center" android:text="@string/refresh" - android:textColor="@color/color_co" - android:drawable="@drawable/common_textcolor_states" /> + android:textColor="@color/color_co"/> diff --git a/MVPModel/app/src/main/res/layout/tab_home.xml b/MVPModel/app/src/main/res/layout/tab_home.xml new file mode 100644 index 0000000..b5ba1c6 --- /dev/null +++ b/MVPModel/app/src/main/res/layout/tab_home.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/layout/tab_knowledge.xml b/MVPModel/app/src/main/res/layout/tab_knowledge.xml new file mode 100644 index 0000000..065f363 --- /dev/null +++ b/MVPModel/app/src/main/res/layout/tab_knowledge.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/layout/tab_mine.xml b/MVPModel/app/src/main/res/layout/tab_mine.xml new file mode 100644 index 0000000..abc4335 --- /dev/null +++ b/MVPModel/app/src/main/res/layout/tab_mine.xml @@ -0,0 +1,22 @@ + + + + + + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/layout/tab_navigation.xml b/MVPModel/app/src/main/res/layout/tab_navigation.xml new file mode 100644 index 0000000..d8f2f7f --- /dev/null +++ b/MVPModel/app/src/main/res/layout/tab_navigation.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/layout/tab_project.xml b/MVPModel/app/src/main/res/layout/tab_project.xml new file mode 100644 index 0000000..027de9c --- /dev/null +++ b/MVPModel/app/src/main/res/layout/tab_project.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/menu/bottom_navigation_main.xml b/MVPModel/app/src/main/res/menu/bottom_navigation_main.xml deleted file mode 100644 index c8e6630..0000000 --- a/MVPModel/app/src/main/res/menu/bottom_navigation_main.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - diff --git a/MVPModel/app/src/main/res/mipmap-xhdpi/icon_mvp.jpg b/MVPModel/app/src/main/res/mipmap-xhdpi/app_icon.jpg similarity index 100% rename from MVPModel/app/src/main/res/mipmap-xhdpi/icon_mvp.jpg rename to MVPModel/app/src/main/res/mipmap-xhdpi/app_icon.jpg diff --git a/MVPModel/app/src/main/res/mipmap-xhdpi/app_icon2.jpeg b/MVPModel/app/src/main/res/mipmap-xhdpi/app_icon2.jpeg new file mode 100644 index 0000000..b2c25e6 Binary files /dev/null and b/MVPModel/app/src/main/res/mipmap-xhdpi/app_icon2.jpeg differ diff --git a/MVPModel/app/src/main/res/mipmap-xhdpi/splash.jpg b/MVPModel/app/src/main/res/mipmap-xhdpi/splash.jpg new file mode 100644 index 0000000..f6ecfdd Binary files /dev/null and b/MVPModel/app/src/main/res/mipmap-xhdpi/splash.jpg differ diff --git a/MVPModel/app/src/main/res/mipmap-xhdpi/splash3.jpg b/MVPModel/app/src/main/res/mipmap-xhdpi/splash3.jpg new file mode 100644 index 0000000..e806406 Binary files /dev/null and b/MVPModel/app/src/main/res/mipmap-xhdpi/splash3.jpg differ diff --git a/MVPModel/app/src/main/res/mipmap-xhdpi/splash4.jpg b/MVPModel/app/src/main/res/mipmap-xhdpi/splash4.jpg new file mode 100644 index 0000000..7e45aae Binary files /dev/null and b/MVPModel/app/src/main/res/mipmap-xhdpi/splash4.jpg differ diff --git a/MVPModel/app/src/main/res/values-zh/values-zh.xml b/MVPModel/app/src/main/res/values-zh/values-zh.xml new file mode 100644 index 0000000..ea4d97d --- /dev/null +++ b/MVPModel/app/src/main/res/values-zh/values-zh.xml @@ -0,0 +1,5 @@ + + + MVP模式 + + \ No newline at end of file diff --git a/MVPModel/app/src/main/res/values/colors.xml b/MVPModel/app/src/main/res/values/colors.xml index 260738a..6c0b8a3 100644 --- a/MVPModel/app/src/main/res/values/colors.xml +++ b/MVPModel/app/src/main/res/values/colors.xml @@ -1,15 +1,5 @@ - #3F51B5 - #303F9F - #FF4081 - #f39c12 - #cccccc - #FFFFFF - #5b5d5c - #8A8E99 - #FF7429 - #C2C5CC diff --git a/MVPModel/app/src/main/res/values/strings.xml b/MVPModel/app/src/main/res/values/strings.xml index d8ef228..8434766 100644 --- a/MVPModel/app/src/main/res/values/strings.xml +++ b/MVPModel/app/src/main/res/values/strings.xml @@ -1,15 +1,15 @@ - MVPModel - Awesome WanAndroid + MVP模式 - 我的 - 知识体系 - 首页 + 我的 + 知识点 + 首页 导航 项目 网络不给力,刷新一下试试? 加载中... 刷新 文章详情 + 作者: diff --git a/MVPModel/app/src/main/res/values/styles.xml b/MVPModel/app/src/main/res/values/styles.xml index 0eb88fe..88d821a 100644 --- a/MVPModel/app/src/main/res/values/styles.xml +++ b/MVPModel/app/src/main/res/values/styles.xml @@ -8,4 +8,26 @@ @color/colorAccent + + + + + + + + diff --git a/MVPModel/basemodule/.gitignore b/MVPModel/basemodule/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/MVPModel/basemodule/.gitignore @@ -0,0 +1 @@ +/build diff --git a/MVPModel/basemodule/build.gradle b/MVPModel/basemodule/build.gradle new file mode 100644 index 0000000..9a3e0af --- /dev/null +++ b/MVPModel/basemodule/build.gradle @@ -0,0 +1,92 @@ +apply plugin: 'com.android.library' +//使用greendao +apply plugin: 'org.greenrobot.greendao' +apply plugin: 'com.jakewharton.butterknife' + +android { + compileSdkVersion rootProject.ext.android.compileSdkVersion + buildToolsVersion rootProject.ext.android.buildToolsVersion + defaultConfig { + minSdkVersion rootProject.ext.android.minSdkVersion + targetSdkVersion rootProject.ext.android.targetSdkVersion + + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + javaCompileOptions { + annotationProcessorOptions { + arguments = [eventBusIndex: 'com.gaolei.mvpmodel.MyEventBusIndex'] + } + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + //执行lint检查,有任何的错误或者警告提示,都会终止构建 + lintOptions { + abortOnError false + } +// sourceSets { +// main { +// //jni库的调用会到资源文件夹下libs里面找so文件,对于so文件,android studio理论上是要求放置在一个jniLibs文件夹下的,这样程序才能够找到要所依赖的so文件 +// jniLibs.srcDirs = ['libs'] +// } +// } + + dependencies { + api fileTree(include: ['*.jar'], dir: 'libs') + api rootProject.ext.dependencies.appcompatV7 + api rootProject.ext.dependencies.design + api rootProject.ext.dependencies["constraint-layout"] + testImplementation 'junit:junit:4.12' + + api fileTree(include: ['*.jar'], dir: 'libs') + //okhttp retrofit + api rootProject.ext.dependencies["okhttp3"] + api rootProject.ext.dependencies["retrofit"] + api rootProject.ext.dependencies["retrofit-converter-gson"] + //butterknife + api rootProject.ext.dependencies["butterknife"] + annotationProcessor rootProject.ext.dependencies["butterknife-compiler"] + // glide + api rootProject.ext.dependencies["glide"] + annotationProcessor rootProject.ext.dependencies["glide-compiler"] + // banner + api rootProject.ext.dependencies["banner"] + // rxjava + api rootProject.ext.dependencies["rxjava"] + api rootProject.ext.dependencies["rxandroid"] + api rootProject.ext.dependencies["retrofit2:adapter-rxjava2"] + // dagger2 +// api rootProject.ext.dependencies["dagger"] + api rootProject.ext.dependencies["dagger-android"] + api rootProject.ext.dependencies["dagger-android-support"] + annotationProcessor rootProject.ext.dependencies["dagger-android-processor"] + annotationProcessor rootProject.ext.dependencies["dagger-compiler"] + // eventbus + api rootProject.ext.dependencies["event-bus"] + annotationProcessor rootProject.ext.dependencies["eventbus-annotation-processor"] + // BlockCanary进行卡顿监控和提示 + debugImplementation rootProject.ext.dependencies["blockcanary-android"] + releaseImplementation rootProject.ext.dependencies["blockcanary-no-op"] + //LeakCanary + debugImplementation rootProject.ext.dependencies["leakcanary-android"] + releaseImplementation rootProject.ext.dependencies["leakcanary-android-no-op"] + // Optional, if you use support library fragments: + debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.1' + //okhttp保存cookie + api rootProject.ext.dependencies["PersistentCookieJar"] + //下拉刷新框架 + api rootProject.ext.dependencies["SmartRefreshLayout"] + api rootProject.ext.dependencies["SmartRefreshHeader"] + + //友盟统计 + api rootProject.ext.dependencies["umeng-common"] + api rootProject.ext.dependencies["umeng-analytics"] + api 'cat.ereza:customactivityoncrash:2.2.0' + compileOnly 'javax.annotation:javax.annotation-api:1.2' + + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/proguard-rules.pro b/MVPModel/basemodule/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/MVPModel/basemodule/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 diff --git a/MVPModel/basemodule/src/androidTest/java/com/gaolei/basemodule/ExampleInstrumentedTest.java b/MVPModel/basemodule/src/androidTest/java/com/gaolei/basemodule/ExampleInstrumentedTest.java new file mode 100644 index 0000000..e417e8d --- /dev/null +++ b/MVPModel/basemodule/src/androidTest/java/com/gaolei/basemodule/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.gaolei.basemodule; + +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 Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.gaolei.basemodule.test", appContext.getPackageName()); + } +} diff --git a/MVPModel/basemodule/src/main/AndroidManifest.xml b/MVPModel/basemodule/src/main/AndroidManifest.xml new file mode 100644 index 0000000..0802909 --- /dev/null +++ b/MVPModel/basemodule/src/main/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/activity/BaseActivity.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/activity/BaseActivity.java new file mode 100644 index 0000000..51c2aa6 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/activity/BaseActivity.java @@ -0,0 +1,155 @@ +package com.gaolei.mvpmodel.base.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.FragmentActivity; +import android.support.v4.content.ContextCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.gaolei.basemodule.R; +import com.gaolei.basemodule.R2; +import com.gaolei.mvpmodel.base.utils.ExitAppUtils; +import com.gaolei.mvpmodel.base.utils.PermissionUtil; +import com.gaolei.mvpmodel.base.utils.StatusBarUtil; +import com.umeng.analytics.MobclickAgent; + +import butterknife.BindView; +import butterknife.ButterKnife; +import dagger.android.AndroidInjection; + +import static com.gaolei.mvpmodel.base.utils.PermissionUtil.PERMISSION_CODE; + + +/** + * Created by gaolei on 2018/4/26. + */ + +public abstract class BaseActivity extends BasePermisssionActivity implements View.OnClickListener { + private PermissionUtil.RequestPermissionCallBack mRequestPermissionCallBack; + + + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(getLayoutId()); + ButterKnife.bind(this); +// AndroidInjection.inject(this); + ExitAppUtils.getInstance().addActivity(this); + + setStatusBarColor(R.color.app_color); + + Bundle bundle = getIntent().getExtras(); + if (bundle == null) { + bundle = savedInstanceState; + } + initData(bundle); + + } + + + protected abstract int getLayoutId(); + + protected abstract void initData(Bundle bundle); + + @Override + public void onClick(View v) { + if (v.getId() == R.id.iv_back) { + finish(); + } + } + + /** + * 设置状态栏颜色 + */ + public void setStatusBarColor(int resColor) { + StatusBarUtil.setWindowStatusBarColor(this, resColor, true); + } + +// /** +// * 发起权限请求 +// * +// * @param context +// * @param permissions +// * @param callback +// */ +// +// public void requestPermission(final Context context, +// PermissionUtil.RequestPermissionCallBack callback, final String... permissions) { +// this.mRequestPermissionCallBack = callback; +// +// //如果所有权限都已授权,则直接返回授权成功,只要有一项未授权,则发起权限请求 +// boolean isAllGranted = true; +// for (String permission : permissions) { +// if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED) { +// isAllGranted = false; +// ActivityCompat.requestPermissions(((Activity) context), permissions, PERMISSION_CODE); +// } +// } +// if (isAllGranted) { +// mRequestPermissionCallBack.granted(); +// } +// } +// +// /** +// * 权限请求结果回调 +// * +// * @param requestCode +// * @param permissions +// * @param grantResults +// */ +// @Override +// public void onRequestPermissionsResult(int requestCode, @NonNull final String[] permissions, @NonNull int[] grantResults) { +// super.onRequestPermissionsResult(requestCode, permissions, grantResults); +// boolean hasAllGranted = true; +// +// switch (requestCode) { +// case PERMISSION_CODE: { +// for (int i = 0; i < grantResults.length; ++i) { +// if (grantResults[i] == PackageManager.PERMISSION_DENIED) { +// hasAllGranted = false; +// //在用户已经拒绝授权的情况下,如果shouldShowRequestPermissionRationale返回false则 +// // 可以推断出用户选择了“不在提示”选项,在这种情况下需要引导用户至设置页手动授权 +// if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) { +// PermissionUtil.requestForeverDenyDialog(BaseActivity.this, permissions); +// +// } else { +// PermissionUtil.requestDenyDialog(BaseActivity.this, permissions); +// +// //用户拒绝权限请求,但未选中“不再提示”选项 +// } +// mRequestPermissionCallBack.denied(); +// } +// } +// if (grantResults.length > 0 && hasAllGranted) { +// mRequestPermissionCallBack.granted(); +// } +// } +// } +// } + protected void onResume() { + super.onResume(); + MobclickAgent.onResume(this); + } + + protected void onPause() { + super.onPause(); + MobclickAgent.onPause(this); + } + protected void onDestroy() { + super.onDestroy(); + ExitAppUtils.getInstance().delActivity(this); + + } + + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/activity/BaseMvpActivity.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/activity/BaseMvpActivity.java new file mode 100644 index 0000000..38bce64 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/activity/BaseMvpActivity.java @@ -0,0 +1,30 @@ +package com.gaolei.mvpmodel.base.activity; + +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.gaolei.mvpmodel.base.mpresenter.BasePresenter; + + + + +public abstract class BaseMvpActivity< P extends BasePresenter> extends BaseActivity { + + public P mPresenter; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mPresenter = initPresenter(); + mPresenter.attach( this); + } + + @Override + protected void onDestroy() { + mPresenter.dettach(); + super.onDestroy(); + } + + //实例presenter + public abstract P initPresenter(); +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/activity/BasePermisssionActivity.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/activity/BasePermisssionActivity.java new file mode 100644 index 0000000..288a7b5 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/activity/BasePermisssionActivity.java @@ -0,0 +1,101 @@ +package com.gaolei.mvpmodel.base.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.FragmentActivity; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AppCompatActivity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.gaolei.basemodule.R; +import com.gaolei.mvpmodel.base.utils.PermissionUtil; +import com.gaolei.mvpmodel.base.utils.StatusBarUtil; +import com.umeng.analytics.MobclickAgent; + +import butterknife.ButterKnife; + +import static com.gaolei.mvpmodel.base.utils.PermissionUtil.PERMISSION_CODE; + + +/** + * Created by gaolei on 2018/4/26. + */ + +public class BasePermisssionActivity extends FragmentActivity { + private PermissionUtil.RequestPermissionCallBack mRequestPermissionCallBack; + + + /** + * 发起权限请求 + * + * @param context + * @param permissions + * @param callback + */ + + public void requestPermission(final Context context, + PermissionUtil.RequestPermissionCallBack callback, final String... permissions) { + this.mRequestPermissionCallBack = callback; + + //如果所有权限都已授权,则直接返回授权成功,只要有一项未授权,则发起权限请求 + boolean isAllGranted = true; + for (String permission : permissions) { + if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED) { + isAllGranted = false; + ActivityCompat.requestPermissions(((Activity) context), permissions, PERMISSION_CODE); + } + } + if (isAllGranted) { + mRequestPermissionCallBack.granted(); + } + } + + /** + * 权限请求结果回调 + * + * @param requestCode + * @param permissions + * @param grantResults + */ + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull final String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + boolean hasAllGranted = true; + + switch (requestCode) { + case PERMISSION_CODE: { + for (int i = 0; i < grantResults.length; ++i) { + if (grantResults[i] == PackageManager.PERMISSION_DENIED) { + hasAllGranted = false; + //在用户已经拒绝授权的情况下,如果shouldShowRequestPermissionRationale返回false则 + // 可以推断出用户选择了“不在提示”选项,在这种情况下需要引导用户至设置页手动授权 + if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) { + PermissionUtil.requestForeverDenyDialog(BasePermisssionActivity.this, permissions); + + } else { + PermissionUtil.requestDenyDialog(BasePermisssionActivity.this, permissions); + + //用户拒绝权限请求,但未选中“不再提示”选项 + } + mRequestPermissionCallBack.denied(); + } + } + if (grantResults.length > 0 && hasAllGranted) { + mRequestPermissionCallBack.granted(); + } + } + } + } + + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/api/ApiService.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/api/ApiService.java new file mode 100644 index 0000000..8c439b0 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/api/ApiService.java @@ -0,0 +1,69 @@ +package com.gaolei.mvpmodel.base.api; + + +import com.gaolei.mvpmodel.base.mmodel.BannerListData; +import com.gaolei.mvpmodel.base.mmodel.ArticleListData; +import com.gaolei.mvpmodel.base.mmodel.LoginData; +import com.gaolei.mvpmodel.base.mmodel.ProjectListData; + +import io.reactivex.Observable; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Path; +import retrofit2.http.Query; + + +public interface ApiService { + + /* + http://www.wanandroid.com/project/list/1/json?cid=294 + 方法:GET + 参数:cid 分类的id,页码:拼接在链接中,从1开始。 + */ + @GET("project/list/{page}/json") + Observable getProjectListData(@Path("page") int page, @Query("cid") int cid); + + /* + http://www.wanandroid.com/banner/json + 广告栏数据 + */ + @GET("banner/json") + Observable getBannerListData(); + + /** + * 获取feed文章列表 + * + * @param num 页数 + * @return feed文章列表数据 + */ + @GET("article/list/{num}/json") + Observable getFeedArticleList(@Path("num") int num); + + /** + * 登陆 + * http://www.wanandroid.com/user/login + * + * @param username user name + * @param password password + * @return 登陆数据 + */ + @POST("user/login") + @FormUrlEncoded + Observable getLoginData(@Field("username") String username, @Field("password") String password); + + /** + * 注册 + * http://www.wanandroid.com/user/register + * + * @param username user name + * @param password password + * @param repassword re password + * @return 注册数据 + */ + @POST("user/register") + @FormUrlEncoded + Observable getRegisterData(@Field("username") String username, @Field("password") String password, @Field("repassword") String repassword); + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/application/CustomApplication.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/application/CustomApplication.java new file mode 100644 index 0000000..ec7b6b8 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/application/CustomApplication.java @@ -0,0 +1,109 @@ +package com.gaolei.mvpmodel.base.application; + +import android.app.Activity; +import android.app.Application; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.ConnectivityManager; +import android.support.v4.BuildConfig; +import android.support.v4.app.Fragment; +import android.util.Log; + +import com.gaolei.mvpmodel.base.utils.LogUtil; +import com.github.moduth.blockcanary.BlockCanary; +import com.github.moduth.blockcanary.BlockCanaryContext; +import com.squareup.leakcanary.LeakCanary; +import com.umeng.analytics.MobclickAgent; +import com.umeng.commonsdk.UMConfigure; + +import javax.inject.Inject; + +import cat.ereza.customactivityoncrash.CustomActivityOnCrash; +import dagger.android.AndroidInjector; +import dagger.android.DispatchingAndroidInjector; +import dagger.android.HasActivityInjector; +import dagger.android.support.HasSupportFragmentInjector; + + +public class CustomApplication extends Application { + public static ConnectivityManager connectivityManager; + public static Context context; + @Inject + DispatchingAndroidInjector mDispatchingAndroidInjector; + @Inject + DispatchingAndroidInjector mFragmentDispatchingAndroidInjector; + @Override + public void onCreate() { + super.onCreate(); + connectivityManager = (ConnectivityManager) getApplicationContext() + .getSystemService(Context.CONNECTIVITY_SERVICE); + context = this; + + LeakCanary.install(this); + BlockCanary.install(this, new AppContext()).start(); + + UMConfigure.init(this, UMConfigure.DEVICE_TYPE_PHONE, ""); + MobclickAgent.onEvent(this, "enter", "CustomApplication");//前统计的事件ID + +// CustomActivityOnCrash.install(this); +// CrashHandler crashHandler = CrashHandler.getInstance(); +// crashHandler.init(getApplicationContext()); + + } + public class AppContext extends BlockCanaryContext { + private static final String TAG = "AppContext"; + + @Override + public String provideQualifier() { + String qualifier = ""; + try { + PackageInfo info = getApplicationContext().getPackageManager() + .getPackageInfo(getApplicationContext().getPackageName(), 0); + qualifier += info.versionCode + "_" + info.versionName + "_YYB"; + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "provideQualifier exception", e); + } + return qualifier; + } + + @Override + public int provideBlockThreshold() { + return 1000; + } + + @Override + public boolean displayNotification() { + return BuildConfig.DEBUG; + } + + @Override + public boolean stopWhenDebugging() { + return false; + } + } + + /** + * 监听程序崩溃/重启 + */ + private static class CustomEventListener implements CustomActivityOnCrash.EventListener { + //程序崩溃回调 + @Override + public void onLaunchErrorActivity() { + LogUtil.e("onLaunchErrorActivity()"); + } + + //重启程序时回调 + @Override + public void onRestartAppFromErrorActivity() { + LogUtil.e("onRestartAppFromErrorActivity()"); + } + + //在崩溃提示页面关闭程序时回调 + @Override + public void onCloseAppFromErrorActivity() { + LogUtil.e("onCloseAppFromErrorActivity()"); + } + + } +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/BaseFragment.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/fragment/BaseFragment.java similarity index 76% rename from MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/BaseFragment.java rename to MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/fragment/BaseFragment.java index 3b39cf1..8166f01 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/fragment/BaseFragment.java +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/fragment/BaseFragment.java @@ -1,5 +1,6 @@ -package com.gaolei.mvpmodel.fragment; +package com.gaolei.mvpmodel.base.fragment; +import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; @@ -10,18 +11,15 @@ import android.widget.LinearLayout; import android.widget.RelativeLayout; -import com.gaolei.mvpmodel.R; -import com.gaolei.mvpmodel.utils.NetworkUtil; -import com.gaolei.mvpmodel.utils.StatusBarUtil; +import com.gaolei.basemodule.R; +import com.gaolei.mvpmodel.base.utils.NetUtils; +import com.gaolei.mvpmodel.base.utils.StatusBarUtil; import butterknife.ButterKnife; import butterknife.Unbinder; +import dagger.android.support.AndroidSupportInjection; -/** - * Created by liuhaiyang on 2017/1/2. - */ - public abstract class BaseFragment extends Fragment implements View.OnClickListener { private FrameLayout mLlContent; View subFragmentView; @@ -35,28 +33,33 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa View mParentView = inflater.inflate(R.layout.fragment_base, container, false); initBaseView(mParentView); addContentView(inflater); + Bundle bundle = getActivity().getIntent().getExtras(); if (bundle == null) { bundle = savedInstanceState; } initData(bundle); + initView(); return mParentView; } + @Override + public void onAttach(Context context) { + // 这一句很重要 + AndroidSupportInjection.inject(this); + super.onAttach(context); + } + - /** - * 用于布局加载完毕,子Fragment可以开始初始化数据 - * - * @param bundle - */ public abstract void initData(Bundle bundle); + public abstract void initView(); private void initBaseView(View view) { mLlContent = view.findViewById(R.id.base_fragment_content); mErrorPageView = view.findViewById(R.id.ll_base_error_content); bt_error_refresh = view.findViewById(R.id.bt_error_refresh); mLlLoading = view.findViewById(R.id.ll_loading); - if (!NetworkUtil.isNetworkAvailable(getActivity())) - mErrorPageView.setVisibility(View.VISIBLE); +// if (!NetworkUtil.isNetworkAvailable(getActivity())) +// showErrorPage(true); bt_error_refresh.setOnClickListener(this); } @@ -93,17 +96,15 @@ public void setLoading(boolean isShow) { * @param isShow */ public void showErrorPage(boolean isShow) { -// mErrorPageView.setVisibility(isShow ? View.VISIBLE : View.GONE); + mErrorPageView.setVisibility(isShow ? View.VISIBLE : View.GONE); } @Override public void onClick(View v) { - switch (v.getId()) { - case R.id.bt_error_refresh: - if (NetworkUtil.isNetworkAvailable(getActivity())) - mErrorPageView.setVisibility(View.GONE); - reload(); - break; + if (v.getId() == R.id.bt_error_refresh) { + if (NetUtils.isConnected()) + mErrorPageView.setVisibility(View.GONE); + reload(); } } @@ -113,6 +114,7 @@ public void onClick(View v) { public void setStatusBarColor(int resColor) { StatusBarUtil.setWindowStatusBarColor(getActivity(), resColor, true); } + public void onDestroyView() { super.onDestroyView(); if (mBinder != null) { diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/fragment/BaseLazyFragment.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/fragment/BaseLazyFragment.java new file mode 100644 index 0000000..44ec0da --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/fragment/BaseLazyFragment.java @@ -0,0 +1,66 @@ +package com.gaolei.mvpmodel.base.fragment; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + + + +public abstract class BaseLazyFragment extends BaseFragment { + + //Fragment的View加载完毕的标记 + private boolean isViewCreated; + //Fragment对用户可见的标记 + private boolean isUIVisible; + + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + isViewCreated = true; + lazyLoad(); + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + + super.setUserVisibleHint(isVisibleToUser); + //isVisibleToUser这个boolean值表示:该Fragment的UI 用户是否可见 + if (isVisibleToUser) { + isUIVisible = true; + lazyLoad(); + } else { + isUIVisible = false; + } + } + + private void lazyLoad() { + + //这里进行双重标记判断,是因为setUserVisibleHint会多次回调,并且会在onCreateView执行前回调,必须确保onCreateView加载完毕且页面可见,才加载数据 + if (isViewCreated && isUIVisible) { + + loadData(); + //数据加载完毕,恢复标记,防止重复加载 + isViewCreated = false; + isUIVisible = false; + + } + } + + + protected abstract void loadData(); + + + @Override + public void onDestroyView() { + super.onDestroyView(); + //页面销毁,恢复标记 + isViewCreated = false; + isUIVisible = false; + + } + + + /**Fragment中TextView显示的内容*/ + // protected abstract String getFragmentTextviewContent(); +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/fragment/BaseMvpFragment.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/fragment/BaseMvpFragment.java new file mode 100644 index 0000000..a31dc41 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/fragment/BaseMvpFragment.java @@ -0,0 +1,89 @@ +package com.gaolei.mvpmodel.base.fragment; + +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.gaolei.mvpmodel.base.mpresenter.BasePresenter; + +import javax.inject.Inject; + + +/** + * Created by gaolei on 2018/4/26. + */ + + +public abstract class BaseMvpFragment

extends BaseFragment { + + //Fragment的View加载完毕的标记 + private boolean isViewCreated; + //Fragment对用户可见的标记 + private boolean isUIVisible; + @Inject + @Nullable + public P mPresenter; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + isViewCreated = true; + +// mPresenter = initPresenter(); + //新添代码 + + if (mPresenter != null) + mPresenter.attach(this); + lazyLoad(); + } + + + @Override + public void onDestroy() { + if (mPresenter != null) + mPresenter.dettach(); + super.onDestroy(); + } + + // //实例presenter +// public abstract P initPresenter(); + + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + + super.setUserVisibleHint(isVisibleToUser); + // isVisibleToUser这个boolean值表示:该Fragment的UI 用户是否可见 + if (isVisibleToUser) { + isUIVisible = true; + lazyLoad(); + } else { + isUIVisible = false; + } + } + + private void lazyLoad() { + + //这里进行双重标记判断,是因为setUserVisibleHint会多次回调,并且会在onCreateView执行前回调,必须确保onCreateView加载完毕且页面可见,才加载数据 + if (isViewCreated && isUIVisible) { + + loadData(); + //数据加载完毕,恢复标记,防止重复加载 + isViewCreated = false; + isUIVisible = false; + + } + } + + + protected abstract void loadData(); + + + @Override + public void onDestroyView() { + super.onDestroyView(); + //页面销毁,恢复标记 + isViewCreated = false; + isUIVisible = false; + + } +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/ArticleListData.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/ArticleListData.java new file mode 100644 index 0000000..b3057c4 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/ArticleListData.java @@ -0,0 +1,256 @@ +package com.gaolei.mvpmodel.base.mmodel; + +import java.io.Serializable; +import java.util.List; + +/** + * @author quchao + * @date 2018/2/12 + */ + +public class ArticleListData { + public ListData data; + + public class ListData { + private int curPage; + public List datas; + private int offset; + private boolean over; + private int pageCount; + private int size; + private int total; + + public int getCurPage() { + return curPage; + } + + public void setCurPage(int curPage) { + this.curPage = curPage; + } + + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + public boolean isOver() { + return over; + } + + public void setOver(boolean over) { + this.over = over; + } + + public int getPageCount() { + return pageCount; + } + + public void setPageCount(int pageCount) { + this.pageCount = pageCount; + } + + public int getSize() { + return size; + } + + public void setSize(int size) { + this.size = size; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public List getDatas() { + return datas; + } + + public void setDatas(List datas) { + this.datas = datas; + } + + } + public class FeedArticleData implements Serializable { + + private String apkLink; + private String author; + private int chapterId; + private String chapterName; + private boolean collect; + private int courseId; + private String desc; + private String envelopePic; + private int id; + private String link; + private String niceDate; + private String origin; + private String projectLink; + private int superChapterId; + private String superChapterName; + private long publishTime; + private String title; + private int visible; + private int zan; + + public String getApkLink() { + return apkLink; + } + + public void setApkLink(String apkLink) { + this.apkLink = apkLink; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public int getChapterId() { + return chapterId; + } + + public void setChapterId(int chapterId) { + this.chapterId = chapterId; + } + + public String getChapterName() { + return chapterName; + } + + public void setChapterName(String chapterName) { + this.chapterName = chapterName; + } + + public boolean isCollect() { + return collect; + } + + public void setCollect(boolean collect) { + this.collect = collect; + } + + public int getCourseId() { + return courseId; + } + + public void setCourseId(int courseId) { + this.courseId = courseId; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getEnvelopePic() { + return envelopePic; + } + + public void setEnvelopePic(String envelopePic) { + this.envelopePic = envelopePic; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getLink() { + return link; + } + + public void setLink(String link) { + this.link = link; + } + + public String getNiceDate() { + return niceDate; + } + + public void setNiceDate(String niceDate) { + this.niceDate = niceDate; + } + + public String getOrigin() { + return origin; + } + + public void setOrigin(String origin) { + this.origin = origin; + } + + public String getProjectLink() { + return projectLink; + } + + public void setProjectLink(String projectLink) { + this.projectLink = projectLink; + } + + public int getSuperChapterId() { + return superChapterId; + } + + public void setSuperChapterId(int superChapterId) { + this.superChapterId = superChapterId; + } + + public String getSuperChapterName() { + return superChapterName; + } + + public void setSuperChapterName(String superChapterName) { + this.superChapterName = superChapterName; + } + + public long getPublishTime() { + return publishTime; + } + + public void setPublishTime(long publishTime) { + this.publishTime = publishTime; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getVisible() { + return visible; + } + + public void setVisible(int visible) { + this.visible = visible; + } + + public int getZan() { + return zan; + } + + public void setZan(int zan) { + this.zan = zan; + } + } + +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mmodel/BannerListData.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/BannerListData.java similarity index 93% rename from MVPModel/app/src/main/java/com/gaolei/mvpmodel/mmodel/BannerListData.java rename to MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/BannerListData.java index dce47eb..7c3e7d9 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mmodel/BannerListData.java +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/BannerListData.java @@ -1,11 +1,7 @@ -package com.gaolei.mvpmodel.mmodel; +package com.gaolei.mvpmodel.base.mmodel; -import java.io.Serializable; import java.util.List; -/** - * Created by caiwancheng on 2017/8/29. - */ public class BannerListData { @@ -15,8 +11,8 @@ public class BannerListData { // 1, "order":0, "title":"最新项目上线啦~", "type":0, "url":"http://www.wanandroid.com/pindex" // } - int errorCode; - String errorMsg; + public int errorCode; + public String errorMsg; public List data; public List getData() { return data; diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/LoginData.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/LoginData.java new file mode 100644 index 0000000..6b39a9d --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/LoginData.java @@ -0,0 +1,57 @@ +package com.gaolei.mvpmodel.base.mmodel; + +import java.util.List; + +/** + * @author quchao + * @date 2018/2/26 + */ + +public class LoginData { + + private String username; + private String password; + private String icon; + private int type; + private List collectIds; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public List getCollectIds() { + return collectIds; + } + + public void setCollectIds(List collectIds) { + this.collectIds = collectIds; + } +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mmodel/ProjectListData.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/ProjectListData.java similarity index 96% rename from MVPModel/app/src/main/java/com/gaolei/mvpmodel/mmodel/ProjectListData.java rename to MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/ProjectListData.java index 40cb1b2..0262d05 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/mmodel/ProjectListData.java +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mmodel/ProjectListData.java @@ -1,4 +1,4 @@ -package com.gaolei.mvpmodel.mmodel; +package com.gaolei.mvpmodel.base.mmodel; import java.io.Serializable; import java.util.List; @@ -24,29 +24,26 @@ public class ProjectListData { public class ListData { private int curPage; - private List datas; + private List datas; private int offset; private boolean over; private int pageCount; private int size; private int total; - public List getDatas() { + public List getDatas() { return datas; } - public void setDatas(List datas) { + public void setDatas(List datas) { this.datas = datas; } // public int getCurPage() { -// // return curPage; // } // // public void setCurPage(int curPage) { // this.curPage = curPage; // } -// - // // public int getOffset() { // return offset; @@ -89,10 +86,10 @@ public void setDatas(List datas) { // } } - public class FeedArticleData implements Serializable + public class ProjectData implements Serializable { - // { +// { // "apkLink": "", // "author": "LiangLuDev", // "chapterId": 294, diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mpresenter/BasePresenter.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mpresenter/BasePresenter.java new file mode 100644 index 0000000..ea65609 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mpresenter/BasePresenter.java @@ -0,0 +1,49 @@ +package com.gaolei.mvpmodel.base.mpresenter; + +import com.gaolei.mvpmodel.base.api.ApiService; +import com.gaolei.mvpmodel.thirdframe.retrofit.RetrofitProvider; +import com.gaolei.mvpmodel.thirdframe.rxjava.BaseObserver; + + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; + +public abstract class BasePresenter { + + public V mView; +// public Observable observable; + public ApiService mRestService = RetrofitProvider.getInstance().builder().getApiService(); + CompositeDisposable mCompositeDisposable ; + + /** + * 绑定View + * + * @param view + */ + public void attach(V view) { + this.mView = view; + if (mCompositeDisposable == null) { + mCompositeDisposable = new CompositeDisposable(); + } + } + + /** + * 释放View + */ + public void dettach() { + this.mView = null; + if (mCompositeDisposable != null) { + mCompositeDisposable.clear(); + } + } + + public void addSubscribe( Observable observable,BaseObserver observer){ + mCompositeDisposable.add(observer); + observable.subscribeOn(Schedulers.io()) + .unsubscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(observer); + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mview/BaseView.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mview/BaseView.java new file mode 100644 index 0000000..fc56b36 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/mview/BaseView.java @@ -0,0 +1,8 @@ +package com.gaolei.mvpmodel.base.mview; + +public interface BaseView { + + void showLoading(); + void hideLoading(); + void showErrorMsg(String errorMsg); +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/glide/ImageLoader.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/glide/ImageLoader.java new file mode 100644 index 0000000..02ecbda --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/glide/ImageLoader.java @@ -0,0 +1,43 @@ +package com.gaolei.mvpmodel.base.thirdframe.glide; + +import android.content.Context; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; +import com.bumptech.glide.request.RequestOptions; + + +public class ImageLoader { + public static ImageLoader instance; + public static RequestOptions options; + + private ImageLoader() { + } + + public static ImageLoader getInstance() { + if (instance == null) { + instance = new ImageLoader(); + options = new RequestOptions() +// .placeholder(R.drawable.ic_launcher)// 正在加载中的图片 +// .error(R.drawable.video_error) // 加载失败的图片 + .diskCacheStrategy(DiskCacheStrategy.ALL); // 磁盘缓存策略 + + } + return instance; + } + + /** + * 使用Glide加载圆形ImageView(如头像)时,不要使用占位图 + * + * @param context context + * @param url image url + * @param iv imageView + */ + public void load(Context context, String url, ImageView iv) { + + Glide.with(context).load(url).apply(options).transition(new DrawableTransitionOptions().crossFade(500)) + .into(iv); + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/glide/MyAppGlideModule.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/glide/MyAppGlideModule.java new file mode 100644 index 0000000..b1046bc --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/glide/MyAppGlideModule.java @@ -0,0 +1,50 @@ +package com.gaolei.mvpmodel.thirdframe.glide; + +import android.content.Context; +import android.os.Environment; +import android.support.annotation.NonNull; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.GlideBuilder; +import com.bumptech.glide.Registry; +import com.bumptech.glide.annotation.GlideModule; +import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool; +import com.bumptech.glide.load.engine.cache.DiskLruCacheFactory; +import com.bumptech.glide.load.engine.cache.LruResourceCache; +import com.bumptech.glide.module.AppGlideModule; +import com.gaolei.mvpmodel.base.application.CustomApplication; + +@GlideModule +public final class MyAppGlideModule extends AppGlideModule { + + public static String glideCachePath; + @Override + public boolean isManifestParsingEnabled() { +// return super.isManifestParsingEnabled(); + return false; + } + + @Override + public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) { + int diskCacheSizeBytes = 1024 * 1024 * 100; // 50 MB + glideCachePath= CustomApplication.context.getExternalFilesDir("glide_cache").getAbsolutePath(); + builder.setDiskCache( + new DiskLruCacheFactory( glideCachePath, diskCacheSizeBytes ) + ); + int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取系统分配给应用的总内存大小 + int memoryCacheSize = maxMemory / 8;//设置图片内存缓存占用八分之一 + //设置内存缓存大小 + builder.setMemoryCache(new LruResourceCache(memoryCacheSize)); + //设置BitmapPool缓存内存大小 + builder.setBitmapPool(new LruBitmapPool(memoryCacheSize)); + + } + private String getStorageDirectory(Context context){ + return Environment.getExternalStorageDirectory().getPath()+"/"+context.getPackageName(); + } + @Override + public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { + super.registerComponents(context, glide, registry); + } +} + diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/RetrofitProvider.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/RetrofitProvider.java new file mode 100644 index 0000000..ff7fdce --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/RetrofitProvider.java @@ -0,0 +1,87 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit; + + +import com.franmontiel.persistentcookiejar.PersistentCookieJar; +import com.franmontiel.persistentcookiejar.cache.SetCookieCache; +import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; +import com.gaolei.mvpmodel.base.api.ApiService; +import com.gaolei.mvpmodel.base.application.CustomApplication; +import com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.GzipRequestInterceptor; +import com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.HttpLoggingInterceptor; +import com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.OfflineCacheInterceptor; +import com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.OnlineCacheInterceptor; +import com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.RetryIntercepter; + +import java.io.File; +import java.util.concurrent.TimeUnit; + +import okhttp3.Cache; +import okhttp3.OkHttpClient; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +import retrofit2.converter.gson.GsonConverterFactory; + + +public final class RetrofitProvider { + + private Retrofit mRetrofit; + private OkHttpClient mOkHttpClient; + private static volatile RetrofitProvider sInstance; + private ApiService restService; + public static String netCachePath; + + private RetrofitProvider() { + } + + + public RetrofitProvider builder() { + netCachePath= CustomApplication.context.getExternalFilesDir("net_cache").getAbsolutePath(); + if (mOkHttpClient == null) { + mOkHttpClient = new OkHttpClient.Builder() + .addNetworkInterceptor(new HttpLoggingInterceptor()) + .addNetworkInterceptor(new OnlineCacheInterceptor())//有网缓存拦截器 + .addInterceptor(new OfflineCacheInterceptor())//无网缓存拦截器 + .cache(new Cache(new File(netCachePath), 50 * 10240 * 1024))//缓存路径和空间设置 + .addInterceptor(new RetryIntercepter(4))//重试 + .addInterceptor(new GzipRequestInterceptor())//开启Gzip压缩 + +// .addInterceptor(new DefaultHeaderInterceptor())//请求连接中添加头信息 +// .addInterceptor(new ProgressInterceptor())//请求url的进度 +// .addInterceptor(new TokenInterceptor())//token过期,自动刷新Token +// .addInterceptor(new SignInterceptor())//所有的接口,默认需要带上sign,timestamp2个参数 +// .addNetworkInterceptor(new ParamsEncryptInterceptor())//参数加密,一般针对表单中的字段和值进行加密,防止中途第三方进行窥探和篡改 +.cookieJar(new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(CustomApplication.context))) + .connectTimeout(5, TimeUnit.SECONDS) + .readTimeout(5, TimeUnit.SECONDS) + .writeTimeout(5, TimeUnit.SECONDS) + .build(); + + } + if (mRetrofit == null) { + mRetrofit = new Retrofit.Builder() + .client(mOkHttpClient) + .baseUrl(com.gaolei.mvpmodel.thirdframe.retrofit.UrlConfig.BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .build(); + } + return sInstance; + } + + public static RetrofitProvider getInstance() { + if (sInstance == null) { + synchronized (RetrofitProvider.class) { + if (sInstance == null) { + sInstance = new RetrofitProvider(); + } + } + } + return sInstance; + } + + public ApiService getApiService() { + if (restService == null) + restService = mRetrofit.create(ApiService.class); + return restService; + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/UrlConfig.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/UrlConfig.java new file mode 100644 index 0000000..a4d148f --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/UrlConfig.java @@ -0,0 +1,11 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit; + + + + +public final class UrlConfig { + +// +public static final String BASE_URL = "http://www.wanandroid.com/"; + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/DefaultHeaderInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/DefaultHeaderInterceptor.java new file mode 100644 index 0000000..a211454 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/DefaultHeaderInterceptor.java @@ -0,0 +1,23 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import java.io.IOException; + +import okhttp3.Headers; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class DefaultHeaderInterceptor implements Interceptor { + + @Override + public Response intercept(Chain chain) throws IOException { + Request originalrequest = chain.request();//原始request + Headers headers = new Headers.Builder() + .add("name", "jason") + .add("age", "27") + .add("token", "dfedsdfsdfffdd12dsef123sdfef1s2dfe") + .build();//构造一个Headers + Request request = originalrequest.newBuilder().headers(headers).build();//注意这行代码别写错了 + return chain.proceed(request); + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/GzipRequestInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/GzipRequestInterceptor.java new file mode 100644 index 0000000..45331ce --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/GzipRequestInterceptor.java @@ -0,0 +1,48 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; /** This interceptor compresses the HTTP request body. Many webservers can't handle this! */ + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okio.BufferedSink; +import okio.GzipSink; +import okio.Okio; + +/** + * 我们在向服务器提交大量数据的时候,希望对post的数据进行gzip压缩 + * 这个拦截器压缩了请求实体. 很多网络服务器无法处理它 */ +public class GzipRequestInterceptor implements Interceptor { + @Override public Response intercept(Interceptor.Chain chain) throws IOException { + Request originalRequest = chain.request(); + if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { + return chain.proceed(originalRequest); + } + + Request compressedRequest = originalRequest.newBuilder() + .header("Content-Encoding", "gzip") + .method(originalRequest.method(), gzip(originalRequest.body())) + .build(); + return chain.proceed(compressedRequest); + } + + private RequestBody gzip(final RequestBody body) { + return new RequestBody() { + @Override public MediaType contentType() { + return body.contentType(); + } + + @Override public long contentLength() { + return -1; // We don't know the compressed length in advance! + } + + @Override public void writeTo(BufferedSink sink) throws IOException { + BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); + body.writeTo(gzipSink); + gzipSink.close(); + } + }; + } +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/HttpLoggingInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/HttpLoggingInterceptor.java new file mode 100644 index 0000000..d11a4fe --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/HttpLoggingInterceptor.java @@ -0,0 +1,42 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import android.util.Log; + + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + + +public class HttpLoggingInterceptor implements Interceptor { + public Response intercept(Interceptor.Chain chain) throws IOException { + //这个chain里面包含了request和response,所以你要什么都可以从这里拿 + Request request = chain.request(); + + long t1 = System.nanoTime();//请求发起的时间 + Log.d("gaolei",String.format("发送请求 %s on %s%n%s", + request.url(), chain.connection(), request.headers())); + + Response response = chain.proceed(request); + + long t2 = System.nanoTime();//收到响应的时间 + + //这里不能直接使用response.body().string()的方式输出日志 + //因为response.body().string()之后,response中的流会被关闭,程序会报错,我们需要创建出一 + //个新的response给应用层处理 + ResponseBody responseBody = response.peekBody(1024 * 1024); + + Log.d("gaolei",String.format("接收响应: [%s] %n返回json:【%s】 %.1fms%n%s", + response.request().url(), + responseBody.string(), + (t2 - t1) / 1e6d, + response.headers())); + + return response; + } +} + + diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/OfflineCacheInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/OfflineCacheInterceptor.java new file mode 100644 index 0000000..9e0bbf1 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/OfflineCacheInterceptor.java @@ -0,0 +1,37 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import android.util.Log; + +import com.gaolei.mvpmodel.base.utils.NetUtils; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class OfflineCacheInterceptor implements Interceptor { + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + if (!NetUtils.isConnected()) { + int offlineCacheTime = Integer.MAX_VALUE;//离线的时候的缓存的过期时间 + request = request.newBuilder() +// .cacheControl(new CacheControl +// .Builder() +// .maxStale(60, TimeUnit.SECONDS) +// .onlyIfCached() +// .build() +// ) +// 两种方式结果是一样的,写法不同 + .header("Cache-Control", "public, only-if-cached, max-stale=" + offlineCacheTime) + .build(); + } + Response response = chain.proceed(request); + Log.d("gaolei","OfflineCacheInterceptor------------response.code():"+response.code()); + if (response.code() == 504) { + // 缓存已经不可使用 + } + return response; + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/OnlineCacheInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/OnlineCacheInterceptor.java new file mode 100644 index 0000000..798cc92 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/OnlineCacheInterceptor.java @@ -0,0 +1,25 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import android.util.Log; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class OnlineCacheInterceptor implements Interceptor { + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Response response = chain.proceed(request); + int onlineCacheTime = 10;//在线的时候的缓存过期时间,如果想要不缓存,直接时间设置为0 + Response newResponse = response.newBuilder() + .header("Cache-Control", "public, max-age=" + onlineCacheTime) + .removeHeader("Pragma") + .build(); + Log.d("gaolei","OnlineCacheInterceptor------------newResponse.code():"+newResponse.code()); + + return newResponse; + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/ParamsEncryptInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/ParamsEncryptInterceptor.java new file mode 100644 index 0000000..d01f6a8 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/ParamsEncryptInterceptor.java @@ -0,0 +1,100 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import android.util.Base64; +import android.util.Log; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import okhttp3.Interceptor; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okio.Buffer; + +public class ParamsEncryptInterceptor implements Interceptor { + + private static final String TAG = ParamsEncryptInterceptor.class.getSimpleName(); + + private static final boolean DEBUG = true; + + @Override + public Response intercept(Chain chain) throws IOException { + + + Request request = chain.request(); + try { + RequestBody oldBody = request.body(); + Buffer buffer = new Buffer(); + oldBody.writeTo(buffer); + String strOldBody = buffer.readUtf8(); + MediaType mediaType = MediaType.parse("text/plain; charset=utf-8"); + //在发动报文前,用Base64和AES对参数进行加密转码 + String strNewBody = encryptDataWithSymmetricKey(generateSymmetric(), strOldBody); + RequestBody body = RequestBody.create(mediaType, strNewBody); + request = request.newBuilder().header("Content-Type", body.contentType().toString()) + .header("Content-Length", String.valueOf(body.contentLength())).method(request.method(), body).build(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + } + return chain.proceed(request); +} + + //加密算法自己和服务端约定即可 + private static String encrypt(String str){ + //your code + return ""; + } + + //生成了对称密钥 + public static SecretKeySpec generateSymmetric() { + // Set up secret key spec for 128-bit AES encryption and decryption + SecretKeySpec sks = null; + try { + SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); + sr.setSeed("any data used as random seed".getBytes()); + KeyGenerator kg = KeyGenerator.getInstance("AES"); + kg.init(128, sr); + SecretKey secretKey=kg.generateKey(); + //在这里可以用从服务端获取到的RSA公钥对刚才随机产生的加密密钥secretKey进行加密 + sks = new SecretKeySpec(secretKey.getEncoded(), "AES"); + + System.out.println("AES KEY: " + sks); + } catch (Exception e) { + Log.e(TAG, "AES secret key spec error"); + } + return sks; + } + +//用SecretKeySpec加密数据 + private static String encryptDataWithSymmetricKey (SecretKeySpec symmKey, String data) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + + // encryption + byte[] toBeCiphred = data.getBytes("UTF-8"); + String encryptedData = null; + + try { + Cipher c = Cipher.getInstance("AES"); + c.init(Cipher.ENCRYPT_MODE, symmKey); + byte[] encodedBytes = c.doFinal(toBeCiphred); + System.out.println("BYTE STRING (ASYMM): " + encodedBytes); + //将SecretKeySpec转换为Base64字符串格式 + encryptedData = Base64.encodeToString(encodedBytes, Base64.DEFAULT); + + } catch (Exception e) { + Log.e(TAG, "AES encryption error"); + throw new RuntimeException(e); + } + return encryptedData; + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/ProgressInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/ProgressInterceptor.java new file mode 100644 index 0000000..aac09a6 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/ProgressInterceptor.java @@ -0,0 +1,41 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.util.ProgressListener; +import com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.util.ProgressResponseBody; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +/** + * @author guolin + * @since 2017/11/5 + */ +public class ProgressInterceptor implements Interceptor { + + public static final Map LISTENER_MAP = new HashMap<>(); + + public static void addListener(String url, ProgressListener listener) { + LISTENER_MAP.put(url, listener); + } + + public static void removeListener(String url) { + LISTENER_MAP.remove(url); + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Response response = chain.proceed(request); + String url = request.url().toString(); + ResponseBody body = response.body(); + Response newResponse = response.newBuilder().body(new ProgressResponseBody(url, body)).build(); + return newResponse; + } + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/RetryIntercepter.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/RetryIntercepter.java new file mode 100644 index 0000000..b4b6b2d --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/RetryIntercepter.java @@ -0,0 +1,30 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class RetryIntercepter implements Interceptor { + + public int maxRetry;//最大重试次数 + private int retryNum = 0;//假如设置为3次重试的话,则最大可能请求4次(默认1次+3次重试) + + public RetryIntercepter(int maxRetry) { + this.maxRetry = maxRetry; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + System.out.println("retryNum=" + retryNum); + Response response = chain.proceed(request); + while (!response.isSuccessful() && retryNum < maxRetry) { + retryNum++; + System.out.println("retryNum=" + retryNum); + response = chain.proceed(request); + } + return response; + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/SignInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/SignInterceptor.java new file mode 100644 index 0000000..79dc684 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/SignInterceptor.java @@ -0,0 +1,160 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import android.content.Context; +import android.support.v4.util.ArrayMap; +import android.util.Log; +import android.util.Pair; + +import com.gaolei.mvpmodel.base.utils.LogUtil; +import com.gaolei.mvpmodel.base.utils.Utils; +import com.github.moduth.blockcanary.BuildConfig; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import okhttp3.FormBody; +import okhttp3.Interceptor; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okio.Buffer; + + + +public final class SignInterceptor implements Interceptor { + + private static final String MD5KEY = "base64:FgBvWS7+m3BPRnKemuoOwXEf7kvldmM+VOmJS5Iccxs="; + private Context mContext; + + public SignInterceptor() { + } + + @Override + public Response intercept(Chain chain) throws IOException { + + Request request = chain.request(); + + //header add version + Request.Builder requestBuilder = request.newBuilder(); + requestBuilder.addHeader("version", BuildConfig.VERSION_NAME); + requestBuilder.addHeader("platform", "ANDROID"); + + if (!request.method().equals("POST")) { + return chain.proceed(request); + } + + JSONObject bodyJson = null; + List> params = new ArrayList<>(); + ArrayMap arrayMap = new ArrayMap<>(); + + FormBody body = null; + try { + body = (FormBody) request.body(); + } catch (ClassCastException c) { + } + + if (body != null) { + + int size = body.size(); + if (size > 0) { + for (int i = 0; i < size; i++) { + params.add(new Pair<>(body.name(i), body.value(i))); + } + } + } else { + RequestBody requestBody = request.body(); + + if (requestBody != null) { + Buffer buffer = new Buffer(); + requestBody.writeTo(buffer); + Charset charset = Charset.forName("UTF-8"); + MediaType contentType = requestBody.contentType(); + if (contentType != null) { + charset = contentType.charset(charset); + } + String paramsStr = buffer.readString(charset); + if (BuildConfig.DEBUG) { + Log.i("HTTP", "request = " + paramsStr); + } + + try { + bodyJson = new JSONObject(paramsStr); + } catch (JSONException e) { + LogUtil.e( "JsonObject err"); + } + + if (bodyJson != null) { + Iterator it = bodyJson.keys(); + while (it.hasNext()) { + String key = it.next(); + Object value = null; + try { + value = bodyJson.get(key); + } catch (JSONException e) { + LogUtil.e("JsonObject get err"); + } + if (key.equals("token")) { + arrayMap.put("token", String.valueOf(value)); + arrayMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000)); + + for (String strKey : arrayMap.keySet()) { + params.add(new Pair<>(strKey, arrayMap.get(strKey))); + } + } else { + params.add(new Pair<>(key, String.valueOf(value))); + } + + } + } + + } + } + + params.add(new Pair<>("MD5Key", MD5KEY)); + Collections.sort(params, new Comparator>() { + @Override + public int compare(Pair lhs, Pair rhs) { + return lhs.second.compareTo(rhs.second); + } + }); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < params.size(); i++) { + sb.append(params.get(i).second); + if (i < params.size() - 1) { + sb.append(""); + } + } + + String sign = Utils.md5Encode(sb.toString()); + params.add(new Pair<>("sign", sign)); + + for (Pair pair : params) { + if ((arrayMap.containsKey(pair.first) || pair.first.equals("sign")) && bodyJson != null) { + try { + bodyJson.put(pair.first, pair.second); + } catch (JSONException e) { + LogUtil.e("JsonObject put err"); + } + } + } + + String postBodyString = bodyJson.toString(); + request = requestBuilder + .post(RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), + postBodyString)) + .build(); + + return chain.proceed(request); + } + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/TokenInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/TokenInterceptor.java new file mode 100644 index 0000000..ece876b --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/TokenInterceptor.java @@ -0,0 +1,70 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import com.gaolei.mvpmodel.base.utils.LogUtil; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class TokenInterceptor implements Interceptor { + + String TAG=getClass()+""; + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Response response = chain.proceed(request); + LogUtil.d(response.code()+""); + + if (isTokenExpired(response)) {//根据和服务端的约定判断token过期 + LogUtil.d("静默自动刷新Token,然后重新请求数据"); + //同步请求方式,获取最新的Token + String newSession = getNewToken(); + //使用新的Token,创建新的请求 + Request newRequest = chain.request() + .newBuilder() + .header("Cookie", "JSESSIONID=" + newSession) + .build(); + //重新请求 + return chain.proceed(newRequest); + } + return response; + } + + /** + * 根据Response,判断Token是否失效 + * + * @param response + * @return + */ + private boolean isTokenExpired(Response response) { + if (response.code() == 404) { + return true; + } + return false; + } + + /** + * 同步请求方式,获取最新的Token + * + * @return + */ + private String getNewToken() throws IOException { + // 通过一个特定的接口获取新的token,此处要用到同步的retrofit请求 +// Response_Login loginInfo = CacheManager.restoreLoginInfo(BaseApplication.getContext()); +// String username = loginInfo.getUserName(); +// String password = loginInfo.getPassword(); +// +// LogUtil.print("loginInfo=" + loginInfo.toString()); +// Call call = WebHelper.getSyncInterface().synclogin(new Request_Login(username, password)); +// loginInfo = call.execute().body(); +// LogUtil.print("loginInfo=" + loginInfo.toString()); +// +// loginInfo.setPassword(password); +// CacheManager.saveLoginInfo(loginInfo); +// return loginInfo.getSession(); +// } + return ""; + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/UrlResetInterceptor.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/UrlResetInterceptor.java new file mode 100644 index 0000000..b454d6a --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/UrlResetInterceptor.java @@ -0,0 +1,47 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor; + +import java.io.IOException; + +import okhttp3.HttpUrl; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +/* +实际的开发过程中,我们在网络请求中会添加一些公共参数,对于一些可变的公共参数,在缓存数据和访问缓存数据的 +过程中需要删除,比如网络类型,有网络时其值为Wifi或4G等,无网络时可能为none, 这时访问缓存时就会因url不一致导致访问缓存失败 +*/ + +public class UrlResetInterceptor implements Interceptor { + @Override + public Response intercept(Chain chain) throws IOException { + + + Response response = chain.proceed(chain.request()); + HttpUrl newUrl = chain.request().url().newBuilder() + .removeAllQueryParameters("network") + .build(); // 缓存数据前删除可变的公共参数 + Request newRequest = chain.request().newBuilder() + .url(newUrl) + .build(); + return response.newBuilder() + .request(newRequest) + .removeHeader("Pragma") + .header("Cache-Control", "public, max-age=" + 1) + .build(); + + +// Request request = chain.request(); +// HttpUrl url = request.url(); +// String s = url.url().toString(); +// //———请求之前—– +// Response response = null; +// //如果Url中没有包含androidxx关键字,则修改请求链接为http://www.androidxx.cn +// if (s.contains("androidxx")) { +// request = request.newBuilder().url("http://www.androidxx.cn").build(); +// } +// response = chain.proceed(request); +// //———请求之后———— +// return response; + } +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/util/ProgressListener.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/util/ProgressListener.java new file mode 100644 index 0000000..7b57ea6 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/util/ProgressListener.java @@ -0,0 +1,16 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.util; + +/** + * @author guolin + * @since 2017/11/5 + */ +public interface ProgressListener { + + /** + * 当下载进度发生变化时,会回调此方法。 + * @param progress + * 当前的下载进度,参数值的范围是0-100。 + */ + void onProgress(int progress); + +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/util/ProgressResponseBody.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/util/ProgressResponseBody.java new file mode 100644 index 0000000..c9e75b8 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/retrofit/interceptor/util/ProgressResponseBody.java @@ -0,0 +1,86 @@ +package com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.util; + +import android.util.Log; + +import com.gaolei.mvpmodel.thirdframe.retrofit.interceptor.ProgressInterceptor; + +import java.io.IOException; + +import okhttp3.MediaType; +import okhttp3.ResponseBody; +import okio.Buffer; +import okio.BufferedSource; +import okio.ForwardingSource; +import okio.Okio; +import okio.Source; + +/** + * @author guolin + * @since 2017/11/5 + */ +public class ProgressResponseBody extends ResponseBody { + + private static final String TAG = "ProgressResponseBody"; + + private BufferedSource bufferedSource; + + private ResponseBody responseBody; + + private ProgressListener listener; + + public ProgressResponseBody(String url, ResponseBody responseBody) { + this.responseBody = responseBody; + listener = ProgressInterceptor.LISTENER_MAP.get(url); + } + + @Override + public MediaType contentType() { + return responseBody.contentType(); + } + + @Override + public long contentLength() { + return responseBody.contentLength(); + } + + @Override + public BufferedSource source() { + if (bufferedSource == null) { + bufferedSource = Okio.buffer(new ProgressSource(responseBody.source())); + } + return bufferedSource; + } + + private class ProgressSource extends ForwardingSource { + + long totalBytesRead = 0; + + int currentProgress; + + ProgressSource(Source source) { + super(source); + } + + @Override + public long read(Buffer sink, long byteCount) throws IOException { + long bytesRead = super.read(sink, byteCount); + long fullLength = responseBody.contentLength(); + if (bytesRead == -1) { + totalBytesRead = fullLength; + } else { + totalBytesRead += bytesRead; + } + int progress = (int) (100f * totalBytesRead / fullLength); + Log.d(TAG, "download progress is " + progress); + if (listener != null && progress != currentProgress) { + listener.onProgress(progress); + } + if (listener != null && totalBytesRead == fullLength) { + listener = null; + } + currentProgress = progress; + return bytesRead; + } + } + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/rxjava/BaseObserver.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/rxjava/BaseObserver.java new file mode 100644 index 0000000..2e83904 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/thirdframe/rxjava/BaseObserver.java @@ -0,0 +1,62 @@ +package com.gaolei.mvpmodel.thirdframe.rxjava; + +import android.app.Dialog; +import android.content.Context; + +import com.gaolei.mvpmodel.base.activity.BaseActivity; +import com.gaolei.mvpmodel.base.mview.BaseView; +import com.gaolei.mvpmodel.base.utils.NetUtils; +import com.gaolei.mvpmodel.base.utils.Utils; +import com.gaolei.mvpmodel.base.view.CustomProgressDialog; + +import java.io.IOException; + +import io.reactivex.observers.ResourceObserver; +import retrofit2.HttpException; + +public abstract class BaseObserver extends ResourceObserver { + + protected String errMsg = ""; + private boolean isShowError = true; + private Context context; + Dialog prgressDialog; + + protected BaseObserver(boolean isShowDialog){ + // context在CustomProgressDialog中用到 + this.context=context; + } + protected BaseObserver(BaseView view, boolean isShowError){ + this.isShowError = isShowError; + } + + + + @Override + public void onNext(T t) { + + } + + @Override + public void onError(Throwable e) { + CustomProgressDialog.cancel(); + + if (!NetUtils.isConnected()) { + errMsg = "网络连接出错,请检查网络"; + + } else if (e instanceof HttpException) { + errMsg = "服务器访问异常(HttpException)"; + } else if (e instanceof IOException) { + errMsg = "服务器访问异常(IOException)"; + } + + Utils.showToast(errMsg); + + } + + @Override + public void onComplete() { + CustomProgressDialog.cancel(); + + } + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/CrashHandler.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/CrashHandler.java new file mode 100644 index 0000000..1b93df6 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/CrashHandler.java @@ -0,0 +1,158 @@ +package com.gaolei.mvpmodel.base.utils; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.Environment; +import android.os.Looper; + + +import com.gaolei.mvpmodel.base.application.CustomApplication; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; + +import cat.ereza.customactivityoncrash.activity.DefaultErrorActivity; + +public class CrashHandler implements Thread.UncaughtExceptionHandler { + /** + * 系统默认的异常处理类 + */ + private Thread.UncaughtExceptionHandler mDefaultHandler; + Context mcontext; + private static CrashHandler INSTANCE = new CrashHandler(); + String errorSavePath; + //用来存储设备信息和异常信息 + private Map infos = new LinkedHashMap(); + + public static CrashHandler getInstance() { + return INSTANCE; + } + + public void init(Context context) { + mcontext = context; + mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 获取默认的异常处理类 + Thread.setDefaultUncaughtExceptionHandler(this);// 设置当前处理类为默认的异常处理类 + } + + @Override + public void uncaughtException(Thread thread, Throwable ex) { + saveCrashInfoIntoSd(ex); +// showToast(mcontext, "程序出错了,请先用其它功能,我们会尽快修复!"); + Intent intent = new Intent(CustomApplication.context, DefaultErrorActivity.class); + CustomApplication.context.startActivity(intent); + try { + Thread.sleep(2000); + } catch (Exception e) { + // TODO: handle exception + } + + + //崩溃后,重启应用 + + +// intent.putExtra("error_reboot", true); +// +// PendingIntent pendingIntent = PendingIntent.getActivity( +// mcontext.getApplicationContext(), 0, intent, +// PendingIntent.FLAG_ONE_SHOT); +// AlarmManager mgr = (AlarmManager) mcontext +// .getSystemService(Context.ALARM_SERVICE); +// mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, +// pendingIntent); // 1秒钟后重启应用 +// android.os.Process.killProcess(android.os.Process.myPid()); +// System.exit(10); +// } +// ExitAppUtils.getInstance().exit(); + } + + private void showToast(final Context context, final String msg) { + new Thread(new Runnable() { + + @Override + public void run() { + Looper.prepare(); +// Toast.makeText(context, msg, Toast.LENGTH_LONG).show(); + Intent intent = new Intent(CustomApplication.context, DefaultErrorActivity.class); + CustomApplication.context.startActivity(intent); + Looper.loop(); + } + }).start(); + } + + + // 收集设备、软件参数信息 + private void collectDeviceInfo() { + try { + PackageManager pm = CustomApplication.context.getPackageManager(); + PackageInfo pi = pm.getPackageInfo(CustomApplication.context.getPackageName(), PackageManager.GET_ACTIVITIES); + if (pi != null) { + String versionName = pi.versionName == null ? "null" : pi.versionName; + String versionCode = pi.versionCode + ""; + infos.put("systemVersion", SystemUtil.getSystemVersion()); + infos.put("deviceModel", SystemUtil.getSystemModel()); + infos.put("deviceBrand", SystemUtil.getDeviceBrand()); + infos.put("versionName", versionName); + infos.put("versionCode", versionCode); + } + } catch (PackageManager.NameNotFoundException e) { + } + + } + + // 保存错误信息到SD卡文件中 + private void saveCrashInfoIntoSd(Throwable ex) { + collectDeviceInfo(); + //创建文件夹 + errorSavePath = Environment.getExternalStorageDirectory().getPath() + "/" + mcontext.getPackageName() + "/crash"; + File dir = new File(errorSavePath); + if (!dir.exists()) dir.mkdirs(); + + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String time = formatter.format(new Date()); + StringBuffer sb = new StringBuffer(); + sb.append("\n" + time + "\n"); + for (Map.Entry entry : infos.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + sb.append(key + "=" + value + "\n"); + } + + sb.append(getCrashInfo(ex)); + + try { + //创建文件 + String fileName = "crash-" + time + ".txt"; + File file = new File(errorSavePath + "//" + fileName); + if (!file.exists()) file.createNewFile(); + + FileOutputStream fos = new FileOutputStream(file); + fos.write(sb.toString().getBytes()); + fos.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 得到程序崩溃的详细信息 + */ + public String getCrashInfo(Throwable ex) { + Writer result = new StringWriter(); + PrintWriter printWriter = new PrintWriter(result); + ex.setStackTrace(ex.getStackTrace()); + ex.printStackTrace(printWriter); + printWriter.close(); + return result.toString(); + } + + +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/ExitAppUtils.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/ExitAppUtils.java new file mode 100644 index 0000000..d2d81c5 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/ExitAppUtils.java @@ -0,0 +1,36 @@ +package com.gaolei.mvpmodel.base.utils; + +import android.app.Activity; + +import java.util.LinkedList; +import java.util.List; + +public class ExitAppUtils { + + private List mActivityList = new LinkedList(); + private static ExitAppUtils instance = new ExitAppUtils(); + + private ExitAppUtils(){}; + + public static ExitAppUtils getInstance(){ + return instance; + } + + public void addActivity(Activity activity){ + mActivityList.add(activity); + } + + public void delActivity(Activity activity){ + mActivityList.remove(activity); + } + + public void exit(){ + for(Activity activity : mActivityList){ + activity.finish(); + } + + System.exit(0); + } + + +} \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/LogUtil.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/LogUtil.java new file mode 100644 index 0000000..6647457 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/LogUtil.java @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2006-2014 Tuniu All rights reserved + */ +package com.gaolei.mvpmodel.base.utils; + +import android.util.Log; + +import com.gaolei.basemodule.BuildConfig; + + +public class LogUtil { + + private static boolean isDebug = BuildConfig.DEBUG; + private static final String TAG = "zmy"; + + public static void init(boolean isPrintable) { + isDebug = isPrintable; + } + + public static void d(String msg) { + if (!isDebug) { + return; + } + Log.e(TAG, msg); + } + + public static void v(String msg) { + if (!isDebug) { + return; + } + Log.v(TAG, msg); + } + + + public static void i(String tag, String msg) { + if (!isDebug) { + return; + } + Log.i(tag, msg); + } + + + public static void w(String msg) { + if (!isDebug) { + return; + } + Log.w(TAG, msg); + } + + + public static void e(String msg) { + if (!isDebug) { + return; + } + Log.e(TAG, msg); + } + + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/NetUtils.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/NetUtils.java new file mode 100644 index 0000000..37fa070 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/NetUtils.java @@ -0,0 +1,76 @@ +package com.gaolei.mvpmodel.base.utils; + + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +import com.gaolei.mvpmodel.base.application.CustomApplication; + +/** + * 跟网络相关的工具类 + * + * + * + */ +public class NetUtils +{ + private NetUtils() + { + /* cannot be instantiated */ + throw new UnsupportedOperationException("cannot be instantiated"); + } + + + public static boolean isConnected() + { + + ConnectivityManager connectivity = (ConnectivityManager) CustomApplication.context + .getSystemService(Context.CONNECTIVITY_SERVICE); + + if (null != connectivity) + { + + NetworkInfo info = connectivity.getActiveNetworkInfo(); + if (null != info && info.isConnected()) + { + if (info.getState() == NetworkInfo.State.CONNECTED) + { + return true; + } + } + } + return false; + } + + /** + * 判断是否是wifi连接 + */ + public static boolean isWifi() + { + ConnectivityManager cm = (ConnectivityManager) CustomApplication.context + .getSystemService(Context.CONNECTIVITY_SERVICE); + + if (cm == null) + return false; + return cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI; + + } + + /** + * 打开网络设置界面 + */ + public static void openSetting(Activity activity) + { + Intent intent = new Intent("/"); + ComponentName cm = new ComponentName("com.android.settings", + "com.android.settings.WirelessSettings"); + intent.setComponent(cm); + intent.setAction("android.intent.action.VIEW"); + activity.startActivityForResult(intent, 0); + } + +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/PermissionUtil.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/PermissionUtil.java new file mode 100644 index 0000000..8903691 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/PermissionUtil.java @@ -0,0 +1,139 @@ +package com.gaolei.mvpmodel.base.utils; + + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.support.v4.app.ActivityCompat; + +public class +PermissionUtil { + + private static String denyRequestContent = "%s权限 为必要权限,开通才可以正常使用相应功能"; + private static String foreverDenyRequestContent = "%s权限 为必要权限,开通才可以正常使用相应功能。\n \n 请点击 \"设置\"-\"权限\"-打开所需权限。"; + public static final int PERMISSION_CODE = 10001; + + public static void gotoDetailSettingIntent(Activity context) { + Intent intent = new Intent(); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (Build.VERSION.SDK_INT >= 9) { + intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); + intent.setData(Uri.fromParts("package", context.getPackageName(), null)); + } else if (Build.VERSION.SDK_INT <= 8) { + intent.setAction(Intent.ACTION_VIEW); + intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails"); + intent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName()); + } + context.startActivity(intent); + +// Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); +// Uri uri = Uri.fromParts("package", context.getPackageName(), null); +// intent.setData(uri); + } + + public static void requestDenyDialog(final Activity activity, final String... permissions) { + + String content = getContent(denyRequestContent, permissions); + + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + + builder.setTitle("权限申请") + .setMessage(content) + .setPositiveButton("申请", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + ActivityCompat.requestPermissions(activity, permissions, PERMISSION_CODE); + dialog.dismiss(); + } + }) + .setNegativeButton("取消", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + if (Utils.getTopActivity(activity).equals("MainActivity")) { + activity.finish(); + } + dialog.dismiss(); + } + }); + builder.show(); + } + + public static void requestForeverDenyDialog(final Activity activity, final String... permissions) { + + String content = getContent(foreverDenyRequestContent, permissions); + + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + + builder.setTitle("权限设置") + .setMessage(content) + .setPositiveButton("设置", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + gotoDetailSettingIntent(activity); + dialog.dismiss(); + } + }) + .setNegativeButton("取消", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + if (Utils.getTopActivity(activity).equals("MainActivity")) { + activity.finish(); + } + dialog.dismiss(); + } + }); + builder.show(); + } + + public static String getContent(String ifForeverDeny, String... permissions) { + String content = ""; + + if (permissions.length == 1) { + if (permissions[0].equals(Manifest.permission.CAMERA)) + content = String.format(ifForeverDeny, "相机"); + if (permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) + content = String.format(ifForeverDeny, "存储"); + if (permissions[0].equals(Manifest.permission.READ_PHONE_STATE)) + content = String.format(ifForeverDeny, "电话"); + } + if (permissions.length > 1) { + StringBuilder stringBuilder = new StringBuilder(); + int length = permissions.length; + for (int i = 0; i < length; i++) { + if (permissions[i].equals(Manifest.permission.CAMERA)) + stringBuilder = stringBuilder.append("相机"); + if (permissions[i].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) + stringBuilder = stringBuilder.append("存储"); + if (permissions[i].equals(Manifest.permission.READ_PHONE_STATE)) + stringBuilder = stringBuilder.append("电话"); + if (permissions[i].equals(Manifest.permission.ACCESS_FINE_LOCATION)) + stringBuilder = stringBuilder.append("位置"); + if (permissions[i].equals(Manifest.permission.WRITE_CONTACTS)) + stringBuilder = stringBuilder.append("联系人"); + if (i < length - 1) + stringBuilder = stringBuilder.append("、"); + } + content = String.format(ifForeverDeny, stringBuilder.toString()); + if(content.endsWith("、")){ + content=content.substring(0,content.length()-1); + } + } + return content; + + } + + /** + * 权限请求结果回调接口 + */ + public interface RequestPermissionCallBack { + /** + * 同意授权 + */ + public void granted(); + + /** + * 取消授权 + */ + public void denied(); + } +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/SPUtils.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/SPUtils.java new file mode 100644 index 0000000..3b2b10f --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/SPUtils.java @@ -0,0 +1,172 @@ +package com.gaolei.mvpmodel.base.utils; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.gaolei.mvpmodel.base.application.CustomApplication; + +public class SPUtils +{ + /** + * 保存在手机里面的文件名 + */ + public static final String FILE_NAME = "share_data"; + + + public static void put(String key, Object object) + { + + SharedPreferences sp = CustomApplication.context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + + if (object instanceof String) + { + editor.putString(key, (String) object); + } else if (object instanceof Integer) + { + editor.putInt(key, (Integer) object); + } else if (object instanceof Boolean) + { + editor.putBoolean(key, (Boolean) object); + } else if (object instanceof Float) + { + editor.putFloat(key, (Float) object); + } else if (object instanceof Long) + { + editor.putLong(key, (Long) object); + } else + { + editor.putString(key, object.toString()); + } + + SharedPreferencesCompat.apply(editor); + } + + + public static Object get(String key, Object defaultObject) + { + SharedPreferences sp = CustomApplication.context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + + if (defaultObject instanceof String) + { + return sp.getString(key, (String) defaultObject); + } else if (defaultObject instanceof Integer) + { + return sp.getInt(key, (Integer) defaultObject); + } else if (defaultObject instanceof Boolean) + { + return sp.getBoolean(key, (Boolean) defaultObject); + } else if (defaultObject instanceof Float) + { + return sp.getFloat(key, (Float) defaultObject); + } else if (defaultObject instanceof Long) + { + return sp.getLong(key, (Long) defaultObject); + } + + return null; + } + + + public static void remove( String key) + { + SharedPreferences sp = CustomApplication.context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.remove(key); + SharedPreferencesCompat.apply(editor); + } + + /** + * 清除所有数据 + */ + public static void clear() + { + SharedPreferences sp = CustomApplication.context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.clear(); + SharedPreferencesCompat.apply(editor); + } + + /** + * 查询某个key是否已经存在 + */ + public static boolean contains(String key) + { + SharedPreferences sp = CustomApplication.context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + return sp.contains(key); + } + + /** + * 返回所有的键值对 + */ + public static Map getAll() + { + SharedPreferences sp = CustomApplication.context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + return sp.getAll(); + } + + /** + * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类 + * + * @author zhy + * + */ + private static class SharedPreferencesCompat + { + private static final Method sApplyMethod = findApplyMethod(); + + /** + * 反射查找apply的方法 + * + * @return + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + private static Method findApplyMethod() + { + try + { + Class clz = SharedPreferences.Editor.class; + return clz.getMethod("apply"); + } catch (NoSuchMethodException e) + { + } + + return null; + } + + /** + * 如果找到则使用apply执行,否则使用commit + * + * @param editor + */ + public static void apply(SharedPreferences.Editor editor) + { + try + { + if (sApplyMethod != null) + { + sApplyMethod.invoke(editor); + return; + } + } catch (IllegalArgumentException e) + { + } catch (IllegalAccessException e) + { + } catch (InvocationTargetException e) + { + } + editor.commit(); + } + } + +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/utils/StatusBarUtil.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/StatusBarUtil.java similarity index 98% rename from MVPModel/app/src/main/java/com/gaolei/mvpmodel/utils/StatusBarUtil.java rename to MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/StatusBarUtil.java index 77f27da..6065506 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/utils/StatusBarUtil.java +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/StatusBarUtil.java @@ -1,8 +1,6 @@ -package com.gaolei.mvpmodel.utils; +package com.gaolei.mvpmodel.base.utils; + -/** - * Created by caiwancheng on 2017/7/24. - */ import android.app.Activity; import android.content.Context; diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/utils/StatusBarView.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/StatusBarView.java similarity index 79% rename from MVPModel/app/src/main/java/com/gaolei/mvpmodel/utils/StatusBarView.java rename to MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/StatusBarView.java index ed81b15..c863f94 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/utils/StatusBarView.java +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/StatusBarView.java @@ -1,12 +1,10 @@ -package com.gaolei.mvpmodel.utils; +package com.gaolei.mvpmodel.base.utils; import android.content.Context; import android.util.AttributeSet; import android.view.View; -/** - * Created by liuhaiyang on 17/8/30. - */ + public class StatusBarView extends View { public StatusBarView(Context context, AttributeSet attrs) { super(context, attrs); diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/SystemUtil.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/SystemUtil.java new file mode 100644 index 0000000..936efdb --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/SystemUtil.java @@ -0,0 +1,69 @@ +package com.gaolei.mvpmodel.base.utils; + +import android.app.Activity; +import android.content.Context; +import android.telephony.TelephonyManager; + +import java.util.Locale; + + +public class SystemUtil { + + /** + * 获取当前手机系统语言。 + * + * @return 返回当前系统语言。例如:当前设置的是“中文-中国”,则返回“zh-CN” + */ + public static String getSystemLanguage() { + return Locale.getDefault().getLanguage(); + } + + /** + * 获取当前系统上的语言列表(Locale列表) + * + * @return 语言列表 + */ + public static Locale[] getSystemLanguageList() { + return Locale.getAvailableLocales(); + } + + /** + * 获取当前手机系统版本号 + * + * @return 系统版本号 + */ + public static String getSystemVersion() { + return android.os.Build.VERSION.RELEASE; + } + + /** + * 获取手机型号 + * + * @return 手机型号 + */ + public static String getSystemModel() { + return android.os.Build.MODEL; + } + + /** + * 获取手机厂商 + * + * @return 手机厂商 + */ + public static String getDeviceBrand() { + return android.os.Build.BRAND; + } + + /** + * 获取手机IMEI(需要“android.permission.READ_PHONE_STATE”权限) + * + * @return 手机IMEI + */ + public static String getIMEI(Context ctx) { + TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Activity.TELEPHONY_SERVICE); + if (tm != null) { + return tm.getDeviceId(); + } + return null; + } +} diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/Utils.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/Utils.java new file mode 100644 index 0000000..05b59a3 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/utils/Utils.java @@ -0,0 +1,56 @@ +package com.gaolei.mvpmodel.base.utils; + +import android.app.ActivityManager; +import android.content.ComponentName; +import android.content.Context; +import android.widget.Toast; + +import com.gaolei.mvpmodel.base.application.CustomApplication; + +import java.security.MessageDigest; + +/** + * Created by gaolei on 2018/6/15. + */ + +public class Utils { + + public static void showToast(String content){ + Toast.makeText(CustomApplication.context, content, Toast.LENGTH_SHORT).show(); + } + /** + * md5 加密 + * + * @param str 要加密的字符串 + * @return + */ + public static String md5Encode(String str) { + StringBuffer buf = new StringBuffer(); + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(str.getBytes()); + byte[] bytes = md5.digest(); + for (int i = 0; i < bytes.length; i++) { + String s = Integer.toHexString(bytes[i] & 0xff); + if (s.length() == 1) { + buf.append("0"); + } + buf.append(s); + } + + } catch (Exception ex) { + } + return buf.toString(); + } + public static String getTopActivity(Context context) { + ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager.RunningTaskInfo taskInfo = manager.getRunningTasks(1).get(0); + ComponentName componentInfo = taskInfo.topActivity; + String shortClassName = componentInfo.getShortClassName(); //类名 +// String className = info.topActivity.getClassName(); //完整类名 +// String packageName = info.topActivity.getPackageName(); + int index=shortClassName.lastIndexOf("."); + shortClassName=shortClassName.substring(index+1); + return shortClassName; + } +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/BottomNavigationViewHelper.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/BottomNavigationViewHelper.java similarity index 94% rename from MVPModel/app/src/main/java/com/gaolei/mvpmodel/BottomNavigationViewHelper.java rename to MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/BottomNavigationViewHelper.java index 828bc21..8468bb9 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/BottomNavigationViewHelper.java +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/BottomNavigationViewHelper.java @@ -1,4 +1,4 @@ -package com.gaolei.mvpmodel; +package com.gaolei.mvpmodel.base.view; /** * Created by gaolei on 2018/4/26. @@ -9,6 +9,7 @@ import android.support.design.internal.BottomNavigationMenuView; import android.support.design.widget.BottomNavigationView; import android.util.Log; + import java.lang.reflect.Field; public class BottomNavigationViewHelper { @@ -24,7 +25,7 @@ public static void disableShiftMode(BottomNavigationView view) { for (int i = 0; i < menuView.getChildCount(); i++) { BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i); //noinspection RestrictedApi - item.setShiftingMode(false); + item.setShifting(false); // set once again checked value, so view will be updated //noinspection RestrictedApi item.setChecked(item.getItemData().isChecked()); diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/CustomProgressDialog.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/CustomProgressDialog.java new file mode 100644 index 0000000..31d4888 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/CustomProgressDialog.java @@ -0,0 +1,58 @@ +package com.gaolei.mvpmodel.base.view; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.gaolei.basemodule.R; + + +public class CustomProgressDialog { + public static Dialog loadingDialog; + + public static Dialog createLoadingDialog(Context context) { + if (context == null) return null; + LayoutInflater inflater = LayoutInflater.from(context); + View v = inflater.inflate(R.layout.dialog_loading, null);// 得到加载view + LinearLayout layout = (LinearLayout) v.findViewById(R.id.dialog_view);// 加载布局 + // main.xml中的ImageView + ImageView spaceshipImage = (ImageView) v.findViewById(R.id.img); + TextView tipTextView = (TextView) v.findViewById(R.id.tipTextView);// 提示文字 + // 加载动画 + Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation( + context, R.anim.anim_dialog_load); + // 使用ImageView显示动画 + spaceshipImage.startAnimation(hyperspaceJumpAnimation); + + loadingDialog = new Dialog(context, R.style.loading_dialog);// 创建自定义样式dialog + + loadingDialog.setCancelable(true);// 不可以用“返回键”取消 + loadingDialog.setContentView(layout, new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT));// 设置布局 + return loadingDialog; + + } + + public static void show(Activity activity) { + if (loadingDialog != null) return; + if (loadingDialog != null && loadingDialog.isShowing()) return; + loadingDialog = CustomProgressDialog.createLoadingDialog(activity); + loadingDialog.show();//显示 + } + + public static void cancel() { + if (loadingDialog != null) { + loadingDialog.cancel(); + loadingDialog = null; + } + } +} + diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/HeaderView.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/HeaderView.java new file mode 100644 index 0000000..849a069 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/HeaderView.java @@ -0,0 +1,4 @@ +package com.gaolei.mvpmodel.base.view; + +public class HeaderView { +} diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/view/Html5Webview.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/Html5Webview.java similarity index 99% rename from MVPModel/app/src/main/java/com/gaolei/mvpmodel/view/Html5Webview.java rename to MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/Html5Webview.java index 71b378c..1862c17 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/view/Html5Webview.java +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/Html5Webview.java @@ -1,9 +1,8 @@ -package com.gaolei.mvpmodel.view; +package com.gaolei.mvpmodel.base.view; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; -import android.graphics.Color; import android.net.Uri; import android.os.Build; import android.os.Message; diff --git a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/view/ProgressView.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/ProgressView.java similarity index 97% rename from MVPModel/app/src/main/java/com/gaolei/mvpmodel/view/ProgressView.java rename to MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/ProgressView.java index 4f546a9..bae9677 100644 --- a/MVPModel/app/src/main/java/com/gaolei/mvpmodel/view/ProgressView.java +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/ProgressView.java @@ -1,4 +1,4 @@ -package com.gaolei.mvpmodel.view; +package com.gaolei.mvpmodel.base.view; import android.content.Context; import android.graphics.Canvas; diff --git a/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/TitleView.java b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/TitleView.java new file mode 100644 index 0000000..c24af84 --- /dev/null +++ b/MVPModel/basemodule/src/main/java/com/gaolei/mvpmodel/base/view/TitleView.java @@ -0,0 +1,38 @@ +package com.gaolei.mvpmodel.base.view; + +import android.app.Activity; +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import com.gaolei.basemodule.R; + +public class TitleView extends FrameLayout { + + private ImageView iv_back; + + private TextView title; + + public TitleView(Context context, AttributeSet attrs) { + super(context, attrs); + LayoutInflater.from(context).inflate(R.layout.title_view, this); + iv_back =findViewById(R.id.iv_back); + title =findViewById(R.id.title); + iv_back.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + ((Activity) getContext()).finish(); + } + }); + } + + public void setTitleText(String text) { + title.setText(text); + } + +} diff --git a/MVPModel/basemodule/src/main/res/anim/anim_dialog_load.xml b/MVPModel/basemodule/src/main/res/anim/anim_dialog_load.xml new file mode 100644 index 0000000..51a4d13 --- /dev/null +++ b/MVPModel/basemodule/src/main/res/anim/anim_dialog_load.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/MVPModel/basemodule/src/main/res/anim/anim_progress_load.xml b/MVPModel/basemodule/src/main/res/anim/anim_progress_load.xml new file mode 100644 index 0000000..cd19eeb --- /dev/null +++ b/MVPModel/basemodule/src/main/res/anim/anim_progress_load.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/res/color/selector_tab_text.xml b/MVPModel/basemodule/src/main/res/color/selector_tab_text.xml new file mode 100644 index 0000000..ce3a9cd --- /dev/null +++ b/MVPModel/basemodule/src/main/res/color/selector_tab_text.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/res/drawable-xhdpi/common_icon_loading.png b/MVPModel/basemodule/src/main/res/drawable-xhdpi/common_icon_loading.png new file mode 100644 index 0000000..5b66329 Binary files /dev/null and b/MVPModel/basemodule/src/main/res/drawable-xhdpi/common_icon_loading.png differ diff --git a/MVPModel/basemodule/src/main/res/drawable-xhdpi/customactivityoncrash_error_image.png b/MVPModel/basemodule/src/main/res/drawable-xhdpi/customactivityoncrash_error_image.png new file mode 100644 index 0000000..2bcb6fa Binary files /dev/null and b/MVPModel/basemodule/src/main/res/drawable-xhdpi/customactivityoncrash_error_image.png differ diff --git a/MVPModel/basemodule/src/main/res/drawable-xhdpi/default_page_network.png b/MVPModel/basemodule/src/main/res/drawable-xhdpi/default_page_network.png new file mode 100644 index 0000000..7b38142 Binary files /dev/null and b/MVPModel/basemodule/src/main/res/drawable-xhdpi/default_page_network.png differ diff --git a/MVPModel/basemodule/src/main/res/drawable-xhdpi/ic_launcher.png b/MVPModel/basemodule/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 Binary files /dev/null and b/MVPModel/basemodule/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/MVPModel/basemodule/src/main/res/drawable-xhdpi/ic_launcher_round.png b/MVPModel/basemodule/src/main/res/drawable-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/MVPModel/basemodule/src/main/res/drawable-xhdpi/ic_launcher_round.png differ diff --git a/MVPModel/basemodule/src/main/res/drawable-xxhdpi/icon_maintain.jpeg b/MVPModel/basemodule/src/main/res/drawable-xxhdpi/icon_maintain.jpeg new file mode 100644 index 0000000..a14d826 Binary files /dev/null and b/MVPModel/basemodule/src/main/res/drawable-xxhdpi/icon_maintain.jpeg differ diff --git a/MVPModel/basemodule/src/main/res/drawable-xxhdpi/progress_dialog_icon.png b/MVPModel/basemodule/src/main/res/drawable-xxhdpi/progress_dialog_icon.png new file mode 100644 index 0000000..ccc722b Binary files /dev/null and b/MVPModel/basemodule/src/main/res/drawable-xxhdpi/progress_dialog_icon.png differ diff --git a/MVPModel/basemodule/src/main/res/drawable-xxxhdpi/progress_dialog_icon.png b/MVPModel/basemodule/src/main/res/drawable-xxxhdpi/progress_dialog_icon.png new file mode 100644 index 0000000..ccc722b Binary files /dev/null and b/MVPModel/basemodule/src/main/res/drawable-xxxhdpi/progress_dialog_icon.png differ diff --git a/MVPModel/basemodule/src/main/res/drawable/bt_refresh_selector.xml b/MVPModel/basemodule/src/main/res/drawable/bt_refresh_selector.xml new file mode 100644 index 0000000..3448e49 --- /dev/null +++ b/MVPModel/basemodule/src/main/res/drawable/bt_refresh_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/res/drawable/common_bg_loading.xml b/MVPModel/basemodule/src/main/res/drawable/common_bg_loading.xml new file mode 100644 index 0000000..ab8a6bf --- /dev/null +++ b/MVPModel/basemodule/src/main/res/drawable/common_bg_loading.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/MVPModel/retrofitdemo/build/generated/res/pngs/debug/drawable-anydpi-v21/ic_launcher_background.xml b/MVPModel/basemodule/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from MVPModel/retrofitdemo/build/generated/res/pngs/debug/drawable-anydpi-v21/ic_launcher_background.xml rename to MVPModel/basemodule/src/main/res/drawable/ic_launcher_background.xml diff --git a/MVPModel/basemodule/src/main/res/drawable/nav_item_color_state.xml b/MVPModel/basemodule/src/main/res/drawable/nav_item_color_state.xml new file mode 100644 index 0000000..344fa05 --- /dev/null +++ b/MVPModel/basemodule/src/main/res/drawable/nav_item_color_state.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/MVPModel/basemodule/src/main/res/drawable/selected_radius.xml b/MVPModel/basemodule/src/main/res/drawable/selected_radius.xml new file mode 100644 index 0000000..53aa850 --- /dev/null +++ b/MVPModel/basemodule/src/main/res/drawable/selected_radius.xml @@ -0,0 +1,5 @@ + + + + diff --git a/MVPModel/basemodule/src/main/res/drawable/shape_stroke_state_normal.xml b/MVPModel/basemodule/src/main/res/drawable/shape_stroke_state_normal.xml new file mode 100644 index 0000000..f4bb1d7 --- /dev/null +++ b/MVPModel/basemodule/src/main/res/drawable/shape_stroke_state_normal.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/res/drawable/shape_stroke_state_press.xml b/MVPModel/basemodule/src/main/res/drawable/shape_stroke_state_press.xml new file mode 100644 index 0000000..7681cc9 --- /dev/null +++ b/MVPModel/basemodule/src/main/res/drawable/shape_stroke_state_press.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/res/drawable/unselected_radius.xml b/MVPModel/basemodule/src/main/res/drawable/unselected_radius.xml new file mode 100644 index 0000000..9b23c49 --- /dev/null +++ b/MVPModel/basemodule/src/main/res/drawable/unselected_radius.xml @@ -0,0 +1,5 @@ + + + + diff --git a/MVPModel/basemodule/src/main/res/layout/activity_base.xml b/MVPModel/basemodule/src/main/res/layout/activity_base.xml new file mode 100644 index 0000000..06e439e --- /dev/null +++ b/MVPModel/basemodule/src/main/res/layout/activity_base.xml @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/MVPModel/basemodule/src/main/res/layout/dialog_loading.xml b/MVPModel/basemodule/src/main/res/layout/dialog_loading.xml new file mode 100644 index 0000000..15bdcfd --- /dev/null +++ b/MVPModel/basemodule/src/main/res/layout/dialog_loading.xml @@ -0,0 +1,30 @@ + + + + + + + + + diff --git a/MVPModel/basemodule/src/main/res/layout/fragment_base.xml b/MVPModel/basemodule/src/main/res/layout/fragment_base.xml new file mode 100644 index 0000000..33e70f2 --- /dev/null +++ b/MVPModel/basemodule/src/main/res/layout/fragment_base.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MVPModel/basemodule/src/main/res/layout/layout_error_page.xml b/MVPModel/basemodule/src/main/res/layout/layout_error_page.xml new file mode 100644 index 0000000..e9c3c90 --- /dev/null +++ b/MVPModel/basemodule/src/main/res/layout/layout_error_page.xml @@ -0,0 +1,37 @@ + + + + + + + +