蒋洪波

修改忽略文件

正在显示 54 个修改的文件 包含 4791 行增加0 行删除

要显示太多修改。

为保证性能只显示 54 of 54+ 个文件。

  1 +# Auto detect text files and perform LF normalization
  2 +* text=auto
  3 +
  4 +# Custom for Visual Studio
  5 +*.cs diff=csharp
  6 +
  7 +# Standard to msysgit
  8 +*.doc diff=astextplain
  9 +*.DOC diff=astextplain
  10 +*.docx diff=astextplain
  11 +*.DOCX diff=astextplain
  12 +*.dot diff=astextplain
  13 +*.DOT diff=astextplain
  14 +*.pdf diff=astextplain
  15 +*.PDF diff=astextplain
  16 +*.rtf diff=astextplain
  17 +*.RTF diff=astextplain
  1 +# Built application files
  2 +*.apk
  3 +*.ap_
  4 +
  5 +# Files for the Dalvik VM
  6 +*.dex
  7 +
  8 +# Java class files
  9 +*.class
  10 +
  11 +# Generated files
  12 +bin/
  13 +gen/
  14 +out/
  15 +
  16 +# Gradle files
  17 +.gradle/
  18 +build/
  19 +
  20 +# Local configuration file (sdk path, etc)
  21 +local.properties
  22 +
  23 +# Proguard folder generated by Eclipse
  24 +proguard/
  25 +
  26 +# Log Files
  27 +*.log
  28 +
  29 +# Android Studio Navigation editor temp files
  30 +.navigation/
  31 +
  32 +# Android Studio captures folder
  33 +captures/
  34 +
  35 +# Intellij
  36 +*.iml
  37 +
  38 +# Keystore files
  39 +#*.jks
  40 +
  41 +# =========================
  42 +# Operating System Files
  43 +# =========================
  44 +
  45 +# OSX
  46 +# =========================
  47 +
  48 +.DS_Store
  49 +.AppleDouble
  50 +.LSOverride
  51 +
  52 +# Thumbnails
  53 +._*
  54 +
  55 +# Files that might appear in the roo of a volume
  56 +.DocumentRevisions-V100
  57 +.fseventsd
  58 +.Spotlight-V100
  59 +.TemporaryItems
  60 +.Trashes
  61 +.VolumeIcon.icns
  62 +
  63 +# Directories potentially created on remote AFP share
  64 +.AppleDB
  65 +.AppleDesktop
  66 +Network Trash Folder
  67 +Temporary Items
  68 +.apdisk
  69 +
  70 +# Windows
  71 +# =========================
  72 +
  73 +# Windows image file caches
  74 +Thumbs.db
  75 +ehthumbs.db
  76 +
  77 +# Folder config file
  78 +Desktop.ini
  79 +
  80 +# Recycle Bin used on file shares
  81 +$RECYCLE.BIN/
  82 +
  83 +# Windows Installer files
  84 +*.cab
  85 +*.msi
  86 +*.msm
  87 +*.msp
  88 +
  89 +# Windows shortcuts
  90 +*.lnk
  91 +
  92 +
  93 +#我加上避免漏掉
  94 +*.iml
  95 +*.properties
  96 +!gradle-wrapper.properties
  97 +.gradle
  98 +.idea
  99 +/local.properties
  100 +/.idea/workspace.xml
  101 +/.idea/libraries
  102 +.DS_Store
  103 +/build
  104 +
  105 +gradlew
  106 +*.bat
  107 +/captures
  108 +
  109 +#Freeline ignore 忽略freeline的文件
  110 +*.py
  111 +/freeline
  112 +/freeline_core
  113 +
  114 +freeline_project_description.json
  115 +
  116 +
  117 +maindexlist.txt
  118 +main/maindexlist.txt
  1 +apply plugin: 'com.android.library'
  2 +apply plugin: 'com.neenbedankt.android-apt'
  3 +
  4 +android {
  5 + publishNonDefault true
  6 + useLibrary 'org.apache.http.legacy'
  7 + compileSdkVersion rootProject.ext.android["compileSdkVersion"]
  8 + buildToolsVersion rootProject.ext.android["buildToolsVersion"]
  9 +
  10 + defaultConfig {
  11 + minSdkVersion rootProject.ext.android["minSdkVersion"]
  12 + targetSdkVersion rootProject.ext.android["targetSdkVersion"]
  13 + versionCode rootProject.ext.android["versionCode"]
  14 + versionName rootProject.ext.android["versionName"]
  15 + }
  16 + buildTypes {
  17 + release {
  18 + minifyEnabled false
  19 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  20 + }
  21 + debug {
  22 + minifyEnabled false
  23 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  24 + }
  25 + }
  26 +}
  27 +buildscript {
  28 + repositories {
  29 + jcenter()
  30 + mavenCentral()
  31 + }
  32 + dependencies {
  33 + classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  34 + }
  35 +}
  36 +
  37 +dependencies {
  38 + compile fileTree(dir: 'libs', include: ['*.jar'])
  39 + testCompile rootProject.ext.dependencies["junit"]
  40 + compile project(':Fragmentation')
  41 + compile project(':UIModule')
  42 + compile project(':UtilModule')
  43 + compile project(':NetWorkModule')
  44 + compile rootProject.ext.dependencies["rxlifecycle"]
  45 + compile rootProject.ext.dependencies["rxlifecycle-components"]
  46 + //Sysmtem bar
  47 + compile rootProject.ext.dependencies["systembar"]
  48 + provided rootProject.ext.dependencies["javax.annotation"]
  49 + compile rootProject.ext.dependencies["dagger2"]
  50 + apt rootProject.ext.dependencies["dagger2-apt-compiler"]
  51 + compile rootProject.ext.dependencies["glide"]
  52 + //butterknife
  53 +// compile rootProject.ext.dependencies["butterknife"]
  54 +// compile rootProject.ext.dependencies["butterknife-apt"]
  55 +
  56 + compile ("com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.1.3")
  57 + compile 'org.greenrobot:eventbus:3.0.0'
  58 + apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
  59 + compile rootProject.ext.dependencies["nineoldandroids"]
  60 + //PG工具
  61 + provided 'com.baoyz.pg:compiler:2.1.1'
  62 + compile 'com.baoyz.pg:core:2.1.1'
  63 +
  64 +}
  1 +# Add project specific ProGuard rules here.
  2 +# By default, the flags in this file are appended to flags specified
  3 +# in C:\Users\jianghongbo\SDK/tools/proguard/proguard-android.txt
  4 +# You can edit the include path and order by changing the proguardFiles
  5 +# directive in build.gradle.
  6 +#
  7 +# For more details, see
  8 +# http://developer.android.com/guide/developing/tools/proguard.html
  9 +
  10 +# Add any project specific keep options here:
  11 +
  12 +# If your project uses WebView with JS, uncomment the following
  13 +# and specify the fully qualified class name to the JavaScript interface
  14 +# class:
  15 +#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
  16 +# public *;
  17 +#}
  1 +package com.xdy.commonlibrary;
  2 +
  3 +import android.app.Application;
  4 +import android.test.ApplicationTestCase;
  5 +
  6 +/**
  7 + * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
  8 + */
  9 +public class ApplicationTest extends ApplicationTestCase<Application> {
  10 + public ApplicationTest() {
  11 + super(Application.class);
  12 + }
  13 +}
  1 +<manifest package="com.xdy.commonlibrary"
  2 + xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <application />
  4 +</manifest>
  1 +package com.xdy.commonlibrary.adapter; import android.os.Handler;import android.os.Looper;import android.support.annotation.NonNull;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter; import com.xdy.commonlibrary.mvp.BasePresenter; import java.lang.ref.WeakReference;import java.util.ArrayList;import java.util.Collection;import java.util.List; /** * <pre> * 千万不要重载{@link LIBBaseAdapter#getView(int, View, ViewGroup)} * </pre> * @author lixi * @Description <通用的Adapter> * @date 2017-5-19 */public abstract class LIBBaseAdapter<T, P extends BasePresenter> extends BaseAdapter implements LIBViewHolder.OnDatasetChangeListener { protected List<T> mData; protected WeakReference<P> mPresenter; private Handler uiHandler; public void setPresenter(P presenter) { this.mPresenter = new WeakReference<>(presenter); } protected synchronized final Handler getHandler() { if (uiHandler == null) { uiHandler = new Handler(Looper.getMainLooper()); } return uiHandler; } public LIBBaseAdapter() { this(null); } public LIBBaseAdapter(List<T> list) { if (list == null) { mData = new ArrayList<T>(); } else { mData = list; } init(); } protected void init() { } /** * 直接使用外部的List,自动调用notifyDataSetChanged */ public void setData(@NonNull List<T> list) { mData = list; notifyDataSetChanged(); } public List<T> getList() { return mData; } /** * 添加数据 ,自动调用notifyDataSetChanged */ public boolean addData(Collection<? extends T> collection) { return addData(collection, false); } /** * 如果是第一笔数据,则会清空之前数据,自动调用notifyDataSetChanged */ public boolean addData(Collection<? extends T> collection, boolean isFirstData) { if (null == collection || collection.isEmpty()) { return false; } if (isFirstData) { mData.clear(); } mData.addAll(collection); notifyDataSetChanged(); return true; } /** * 添加1个数据,自动调用notifyDataSetChanged */ public void addData(T data) { mData.add(data); notifyDataSetChanged(); } /** * 移除1个数据,自动调用notifyDataSetChanged */ public T remove(int index) { T t = this.mData.remove(index); notifyDataSetChanged(); return t; } /** * 移除1个数据,外部调用notifyDataSetChanged,需重载 {@link Object#equals(Object)} */ public T remove(Object object) { if (null == object) { return null; } for (int i = 0, size = null == mData ? 0 : mData.size(); i < size; i++) { T t = mData.get(i); if (null != t && t.equals(object)) { return mData.remove(i); } } return null; } /** * 添加数据,自动调用notifyDataSetChanged */ public void addData(int position, T data) { mData.add(position, data); notifyDataSetChanged(); } /** * 添加数据,自动调用notifyDataSetChanged */ public boolean addData(int position, Collection<? extends T> collection) { if (null == collection || collection.isEmpty()) { return false; } mData.addAll(position, collection); notifyDataSetChanged(); return true; } /** * 清空数据,自动调用notifyDataSetChanged */ public void clear() { mData.clear(); notifyDataSetChanged(); } @Override public int getCount() { return mData.size(); } public int getSize() { return mData.size(); } @Override public T getItem(int position) { return mData.get(position); } /** * 获得某个item,需重载 {@link Object#equals(Object)} */ public T getItem(Object object) { if (object == null) { return null; } for (int i = 0, size = null != mData ? mData.size() : 0; i < size; i++) { T t = getItem(i); if (null != t && t.equals(object)) { return t; } } return null; } public T getLastItem() { return mData.get(mData.size() - 1); } @Override public long getItemId(int position) { return position; } private ArrayList<LIBViewHolder> holders = new ArrayList<LIBViewHolder>(); private LIBViewHolder getHolder(Object data) { if (null == data) { return null; } for (int i = 0, size = holders.size(); i < size; i++) { LIBViewHolder holder = holders.get(i); if (holder.equals(data)) { return holder; } } return null; } @Override public final void onChange(final LIBViewHolder holder) { if (Looper.myLooper() != Looper.getMainLooper()) {// 如果不是主线程,就交给Handler做处理 getHandler().post(new Runnable() { @Override public void run() { onChange(holder); } }); return; } T data = holder.getTag(); holder.markRecyclerHolder();// 标记当前是重用状态 convert(holder, data, holder.getItemViewType(), holder.getPosition());// 转换布局 holder.resetRecyclerHolder();// 重置标记 } @Override public final synchronized void notifyDataSetChanged() { if (Looper.myLooper() != Looper.getMainLooper()) {// 如果不是主线程,就交给Handler做处理 getHandler().post(new Runnable() { @Override public void run() { LIBBaseAdapter.super.notifyDataSetChanged(); } }); return; } else { super.notifyDataSetChanged(); } } /** * 刷新Item,需重写 {@link Object#equals(Object)} */ public final synchronized void refreshItem(final Object item) { LIBViewHolder holder = getHolder(item);// 查找Holder,根据Holder缓存的Tag和当前传入的item匹配 if (null == holder) {// 如果找不到Holder,则刷新全部 notifyDataSetChanged(); return; } else { onChange(holder); return; } } private static final int FLAG_NONE = 0; private static final int FLAG_BASE_ENTITY = 1; private static final int FLAG_OTHER_ENTITY = 2; private int mFlag = FLAG_NONE; public void setNoRecycleFlag(boolean mNoRecycleFlag) { this.mNoRecycleFlag = mNoRecycleFlag; } private boolean mNoRecycleFlag = false;//不回收标示默认为FALSE @Deprecated @Override public View getView(int position, View convertView, ViewGroup parent) { T data = getItem(position); int itemViewType = getItemViewType(position); LIBViewHolder holder = LIBViewHolder.getHolder(convertView, parent, getLayoutId(data, itemViewType, position), position, itemViewType, mNoRecycleFlag); setTag(data, holder); if (!holder.isRecyleHolder()) { holders.add(holder);// 缓存Holder holder.setListener(this);// 设置刷新监听 } convert(holder, data, itemViewType, position);// 回调UI return holder.getConvertView();// 返回主布局,即ConvertView } private final void setTag(T data, LIBViewHolder holder) { switch (mFlag) { case FLAG_NONE: if (data instanceof LIBBaseEntity) { ((LIBBaseEntity) data).registerObserver(holder); mFlag = FLAG_BASE_ENTITY; } else { mFlag = FLAG_OTHER_ENTITY; } break; case FLAG_BASE_ENTITY: ((LIBBaseEntity) data).registerObserver(holder); break; default: break; } holder.setTag(data); } /** * 转换布局 */ public abstract void convert(LIBViewHolder holder, T data, int itemViewType, int position); /** * 获取布局id */ public abstract int getLayoutId(T data, int itemViewType, int position); }
  1 +package com.xdy.commonlibrary.adapter; import java.lang.ref.SoftReference; /** * 通过实体类,缓存ViewHolder的引用 * * @Description <LIBBaseEntity> * @author lixi * @date 2017年7月17日 */public abstract class LIBBaseEntity { private SoftReference<LIBViewHolder> observer; public final void registerObserver(LIBViewHolder observer) { unregisterAll(); this.observer = new SoftReference<LIBViewHolder>(observer); } public final LIBViewHolder getObserver() { if (null == observer) { return null; } return observer.get(); } /** * @return False ,entity is not visible */ public final boolean refresh() { LIBViewHolder holder = getObserver(); if (null != holder && equals(holder.getTag())) { return holder.refresh(); } else { unregisterAll(); return false; } } private final void unregisterAll() { if (null != observer) { observer.clear(); } this.observer = null; } }
  1 +package com.xdy.commonlibrary.adapter;
  2 +
  3 +import android.content.Context;
  4 +import android.content.res.Resources;
  5 +import android.util.SparseArray;
  6 +import android.view.LayoutInflater;
  7 +import android.view.View;
  8 +import android.view.View.OnClickListener;
  9 +import android.view.ViewGroup;
  10 +import android.widget.ImageView;
  11 +import android.widget.TextView;
  12 +
  13 +
  14 +/**
  15 + * <pre>
  16 + * <B>非与LIBBaseAdapter使用时,下列方法将会失效 </B>
  17 + * 1.{@link #refresh()}
  18 + * 2.{@link #isRecyleHolder()}
  19 + * 3.{@link #getPosition()}
  20 + * 4.{@link #getTag()}
  21 + * 5.{@link #getItemViewType()}
  22 + * <B>若主布局只有一个View时,外部不能调用{@link View#setTag(Object)} </B>
  23 + * </pre>
  24 + * @author lixi
  25 + * @Description <LIBViewHolder>
  26 + * @date 2017-5-19
  27 + */
  28 +public class LIBViewHolder {
  29 +
  30 + private View mConvertView;// 主布局
  31 + private LIBBaseAdapter adapter;// 主布局
  32 + private Context context;//上下文
  33 + private SparseArray<View> mCacheViews;// 缓存容器
  34 + private int layoutId;// 布局ID
  35 +
  36 + private boolean isMarkRecycler;// 标记当前在Adapter中是否是重用的ViewHolder
  37 + private Object tag;// 实体类缓存 只有在Adapter中才会缓存实体类
  38 + private int position;// 在Adapter中的位置
  39 + private boolean isRecyle;// 在Adapter中是否是重用的ViewHolder
  40 + private int itemViewType; // 在Adapter中的布局类型
  41 + private OnDatasetChangeListener listener;// Adapter中数据变更监听
  42 +
  43 + private LIBViewHolder(Context context, ViewGroup parentView, int layoutId, int position, boolean attachToRoot, int itemViewType) {
  44 + this.context = context;
  45 + this.itemViewType = itemViewType;
  46 + this.layoutId = layoutId;
  47 + mCacheViews = new SparseArray<View>();
  48 + setConvertView(context, layoutId, parentView, attachToRoot);
  49 + }
  50 +
  51 + /** 设置主布局,若为null */
  52 + private void setConvertView(Context context, int layoutId, ViewGroup parentView, boolean attachToRoot) {
  53 + if (layoutId > 0) {
  54 + View convertView = LayoutInflater.from(context).inflate(layoutId, parentView, attachToRoot);
  55 + setConvertView(convertView);
  56 + }
  57 + }
  58 +
  59 + /**
  60 + * @return 是否已经设置的主布局
  61 + */
  62 + public final boolean hasAlreadySetConvertView() {
  63 + return null != mConvertView;
  64 + }
  65 +
  66 + /** 设置主布局,若为null,不会覆盖原有布局 */
  67 + public final void setConvertView(View view) {
  68 + if (null == view) {
  69 + return;
  70 + }
  71 + if (null != mConvertView) {
  72 + mCacheViews.clear();
  73 + mConvertView = null;
  74 + }
  75 + mConvertView = view;
  76 + mConvertView.setTag(this);
  77 + }
  78 +
  79 + /**
  80 + * 获得ViewHolder,BaseAdapter中使用 ,attachToRoot=<code>false</code>
  81 + */
  82 + public static LIBViewHolder getHolder(View convertView, ViewGroup parentView, int layoutId, int position, int itemViewType, boolean noRecycle) {
  83 + return getHolder(convertView, parentView, layoutId, position, false, itemViewType, noRecycle);
  84 + }
  85 +
  86 + /**
  87 + * 获得ViewHolder,BaseAdapter中使用
  88 + */
  89 + public static LIBViewHolder getHolder(View convertView, ViewGroup parentView, int layoutId, int position, boolean attachToRoot, int itemViewType, boolean noRecycle) {
  90 + LIBViewHolder holder = null;
  91 + if (convertView == null || noRecycle) {
  92 + holder = new LIBViewHolder(parentView.getContext(), parentView, layoutId, position, attachToRoot, itemViewType);
  93 + holder.isRecyle = false;
  94 + return holder;
  95 + } else {
  96 + holder = (LIBViewHolder) convertView.getTag();
  97 + holder.position = position;
  98 + holder.isRecyle = true;
  99 + holder.itemViewType = itemViewType;
  100 + return holder;
  101 + }
  102 + }
  103 +
  104 + /**
  105 + * 获得ViewHolder,在某些情况下使用.
  106 + * <p/>
  107 + * <pre>
  108 + * <B>注意:以下方法将会不工作</B>
  109 + * {@link #refresh()} {@link #isRecyleHolder()}
  110 + * {@link #getPosition()} {@link #getTag()} {@link #getItemViewType()}
  111 + * </pre>
  112 + */
  113 + public static LIBViewHolder getHolder(Context context, ViewGroup parentView, int layoutId, boolean attachToRoot) {
  114 + return new LIBViewHolder(context, parentView, layoutId, 0, attachToRoot, 0);
  115 + }
  116 +
  117 + /** 获得当前在Adapter中的布局类型 */
  118 + public int getItemViewType() {
  119 + return itemViewType;
  120 + }
  121 +
  122 + /** 设置在Adapter中缓存的实体类 */
  123 + protected void setTag(Object tag) {
  124 + this.tag = tag;
  125 + }
  126 +
  127 + ;
  128 +
  129 + /** 获得在Adapter中缓存的实体类 */
  130 + @SuppressWarnings("unchecked")
  131 + public <T> T getTag() {
  132 + return (T) tag;
  133 + }
  134 +
  135 + /** 获得Resources资源 */
  136 + public Resources getResources() {
  137 + return mConvertView.getResources();
  138 + }
  139 +
  140 + /** Adapter中数据变更监听 */
  141 + protected static interface OnDatasetChangeListener {
  142 + void onChange(LIBViewHolder holder);
  143 + }
  144 +
  145 + /** 设置Adapter中数据变更监听 */
  146 + protected void setListener(OnDatasetChangeListener listener) {
  147 + this.listener = listener;
  148 + }
  149 +
  150 + /** 标记当前的ViewHolder,在Adapter中是重用的 */
  151 + protected void markRecyclerHolder() {
  152 + if (isRecyle) {
  153 + return;
  154 + }
  155 + isMarkRecycler = true;
  156 + }
  157 +
  158 + /** 重置在Adapter中重用标记 */
  159 + protected void resetRecyclerHolder() {
  160 + isMarkRecycler = false;
  161 + }
  162 +
  163 + /** R.layout.id */
  164 + public int getLayoutID() {
  165 + return layoutId;
  166 + }
  167 +
  168 + /** 获得上下文Context */
  169 + public Context getContext() {
  170 + return context;
  171 + }
  172 +
  173 + /** 在Adapter中是否是重用的ViewHolder,若不是重用的Item 在Refresh的时候 会标记为TRUE,Refresh后会重置标记 */
  174 + public boolean isRecyleHolder() {
  175 + return isMarkRecycler ? true : isRecyle;
  176 + }
  177 +
  178 + /**
  179 + * 刷新item,会回调{@link LIBBaseAdapter#convert(LIBViewHolder, Object, int, int)}
  180 + * ,此时{@link #isRecyleHolder()}暂时标记为TRUE,Refresh后会重置该标记
  181 + */
  182 + public boolean refresh() {
  183 + if (null != listener) {
  184 + listener.onChange(this);
  185 + return true;
  186 + } else {
  187 + return false;
  188 + }
  189 + }
  190 +
  191 + /** 获得当前在Adapter中的位置 */
  192 + public int getPosition() {
  193 + return position;
  194 + }
  195 +
  196 + /** 获得当前的View */
  197 + public View getConvertView() {
  198 + return mConvertView;
  199 + }
  200 +
  201 + /** 获得某个View */
  202 + @SuppressWarnings("unchecked")
  203 + public <T extends View> T getView(int id) {
  204 + View view = mCacheViews.get(id);
  205 + if (view == null) {
  206 + view = mConvertView.findViewById(id);
  207 + }
  208 + return (T) view;
  209 + }
  210 +
  211 + /** 获得某个View, 只有在初始化View 的时候才会对view设置监听事件 */
  212 + public <T extends View> T getView(int id, OnClickListener clickListener) {
  213 + return getView(id, clickListener, isRecyleHolder());
  214 + }
  215 +
  216 + /** 获得某个View, 只有在初始化View 的时候才会对view设置监听事件 */
  217 + public <T extends View> T getView(int id, OnClickListener clickListener, boolean isRecycleHolder) {
  218 + T view = getView(id);
  219 + if (isRecycleHolder == false) {
  220 + view.setOnClickListener(clickListener);
  221 + view.setClickable(clickListener != null);
  222 + }
  223 + return view;
  224 + }
  225 +
  226 + /** 设置文本,必须是TextView */
  227 + public TextView setText(int id, CharSequence sequence) {
  228 + return setText(id, sequence, false);
  229 + }
  230 +
  231 + /** 设置文本,必须是TextView */
  232 + public TextView setText(int id, CharSequence sequence, boolean isAutoChangeVisibleAndGone) {
  233 + TextView textView = getView(id);
  234 + textView.setText(sequence);
  235 + if (isAutoChangeVisibleAndGone) {
  236 + textView.setVisibility(null == sequence || sequence.length() < 1 ? View.GONE : View.VISIBLE);
  237 + }
  238 + return textView;
  239 + }
  240 +
  241 + /** 加载图片,必须是ImageView */
  242 + public ImageView loadImage(int id, int defaultResId) {
  243 + ImageView imageView = getView(id);
  244 + imageView.setImageResource(defaultResId);
  245 + return imageView;
  246 + }
  247 +
  248 + ;
  249 +
  250 + /** 加载图片,必须是ImageView */
  251 + public ImageView loadImage(int id, String url, int defaultResId) {
  252 + return loadImage(id, url, defaultResId, 640);
  253 + }
  254 +
  255 + ;
  256 +
  257 + /** 加载图片,必须是ImageView */
  258 + public ImageView loadImage(int id, String url, int defaultResId, int width) {
  259 + ImageView imageView = getView(id);
  260 + //RKImageLoader.getInstance().loadImage(url, imageView, defaultResId, width);
  261 + return imageView;
  262 + }
  263 +
  264 + ;
  265 +
  266 + /** 设置View的可见性 */
  267 + public LIBViewHolder setVisibility(int id, int visibility) {
  268 + View view = getView(id);
  269 + if (view.getVisibility() != visibility) {
  270 + view.setVisibility(visibility);
  271 + }
  272 + return this;
  273 + }
  274 +
  275 + @Override
  276 + public boolean equals(Object o) {
  277 + if (null == o) {
  278 + return false;
  279 + }
  280 + if (this == o) {
  281 + return true;
  282 + }
  283 + if (null != tag && tag.equals(o)) {
  284 + return true;
  285 + }
  286 + if (o instanceof Integer) {
  287 + if (position == (Integer) o) {
  288 + return true;
  289 + }
  290 + }
  291 + return false;
  292 + }
  293 +
  294 + public LIBBaseAdapter getAdapter() {
  295 + return adapter;
  296 + }
  297 +
  298 + public void setAdapter(LIBBaseAdapter adapter) {
  299 + this.adapter = adapter;
  300 + }
  301 +
  302 + @SuppressWarnings("unchecked")
  303 + public static <T extends View> T get(View view, int id) {
  304 + SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
  305 + if (viewHolder == null) {
  306 + viewHolder = new SparseArray<View>();
  307 + view.setTag(viewHolder);
  308 + }
  309 + View childView = viewHolder.get(id);
  310 + if (childView == null) {
  311 + childView = view.findViewById(id);
  312 + viewHolder.put(id, childView);
  313 + }
  314 + return (T) childView;
  315 + }
  316 +}
  1 +package com.xdy.commonlibrary.adapter;
  2 +
  3 +import android.view.View;
  4 +
  5 +/**
  6 + * @author 蒋洪波
  7 + * @version 版本号
  8 + * @file 文件名
  9 + * @brief 简要说明
  10 + * 详细说明,如果没有请删除
  11 + * @date 2017/10/28
  12 + * Copyright (c) 2017, 上品折扣[]
  13 + * All rights reserved.
  14 + */
  15 +public interface OnItemClickListener<T> {
  16 + void onItemClick(View v, int position, T t);
  17 +}
  1 +package com.xdy.commonlibrary.adapter;
  2 +
  3 +import android.text.Editable;
  4 +import android.text.TextWatcher;
  5 +import android.widget.EditText;
  6 +
  7 +import java.lang.ref.WeakReference;
  8 +
  9 +/**
  10 + * Created by Administrator on 2017/5/20.
  11 + */
  12 +public class PriceTextWatcher<T extends PriceTextWatcher.UpdateEntityPrice> implements TextWatcher {
  13 +
  14 + private WeakReference<EditText> mEditText;
  15 + private T t;
  16 +
  17 + private int numMax = 8;//默认可以输入8位小数
  18 +
  19 + public PriceTextWatcher(EditText editText) {
  20 + mEditText = new WeakReference<>(editText);
  21 + }
  22 +
  23 + public void setNumMax(int numMax) {
  24 + if (numMax > 0)
  25 + this.numMax = numMax;
  26 + }
  27 +
  28 + public void setSyncEntity(T t) {
  29 + this.t = t;
  30 + }
  31 +
  32 + @Override
  33 + public void beforeTextChanged(CharSequence s, int start, int count, int after) {
  34 +
  35 + }
  36 +
  37 + @Override
  38 + public void onTextChanged(CharSequence s, int start, int before, int count) {
  39 +
  40 + //如果有小数点的情况下
  41 + EditText editText = null;
  42 + if ((editText = mEditText.get()) != null) {
  43 +
  44 + //如果有小数点的情况下
  45 + if (s.toString().contains(".")) {
  46 +
  47 + if (s.length() - 1 - s.toString().indexOf(".") > 2) {
  48 + s = s.toString().subSequence(0,
  49 + s.toString().indexOf(".") + 3);
  50 + editText.setText(s);
  51 + editText.setSelection(s.length());
  52 + }
  53 + } else {
  54 + if (s.toString().length() > numMax) {
  55 + s = s.toString().subSequence(0, numMax);
  56 + editText.setText(s);
  57 + editText.setSelection(s.length());
  58 + }
  59 + }
  60 +
  61 + //当是“.”开头的时候 直接输入为0.XX
  62 + if (s.toString().trim().substring(0).equals(".")) {
  63 + s = "0" + s;
  64 + editText.setText(s);
  65 + editText.setSelection(2);
  66 + }
  67 + // 如果是0开头的话 只能输入 0.XX
  68 + if (s.toString().startsWith("0")
  69 + && s.toString().trim().length() > 1) {
  70 + if (!s.toString().substring(1, 2).equals(".")) {
  71 + editText.setText(s.subSequence(0, 1));
  72 + editText.setSelection(1);
  73 + return;
  74 + }
  75 + }
  76 + }
  77 + }
  78 +
  79 + @Override
  80 + public void afterTextChanged(Editable s) {
  81 +// String temp = s.toString();
  82 +// if (!TextUtils.isEmpty(temp)) {
  83 +// Double price = Double.valueOf(s.toString());
  84 +// if (price > 0) {
  85 +// if (t != null)
  86 +// t.setPrice(price);
  87 +// }
  88 +// }
  89 + }
  90 +
  91 +
  92 + public interface UpdateEntityPrice {
  93 + public void setPrice(double price);
  94 + }
  95 +}
  1 +package com.xdy.commonlibrary.api;
  2 +
  3 +import com.xdy.util.AppUtil;
  4 +import com.xdy.util.StringUtils;
  5 +import com.xdy.commonlibrary.core.CommonAppLike;
  6 +
  7 +import java.io.File;
  8 +
  9 +/**
  10 + * 主要定义与服务器交互的主要参数
  11 + */
  12 +public class Api {
  13 + //主机地址
  14 + public final static String APP_HOST = "http://172.16.103.145:9002/";
  15 +// public final static String APP_HOST = "http://172.16.102.77:8080/";
  16 + //只有在达人时用到的地址
  17 + public final static String APP_HOST_TALENT = "http://192.168.205.132:9002/";
  18 + //图片主机,图片拼接规则 HOST+{proPictDir}+{proPictName}
  19 + public final static String IMAGE_HOST = "http://images.shopin.net/images";
  20 + //测试数据文件位置
  21 + public final static String API_TEST = "api/test/";
  22 +
  23 + //首页地址
  24 + public final static String SUFFIX_H5_URL = "http://172.16.103.145:9002/h5/";
  25 + public final static String SUFFIX_CMS_URL = "http://172.16.200.2/";
  26 + //! H5 example:http://172.16.103.145:9002/h5/v1_0_0/html
  27 + public static final String BASE_H5_URL = StringUtils.concat(SUFFIX_H5_URL,
  28 + "v", AppUtil.getVersionName(CommonAppLike.getContext()).replace(".", "_")
  29 + , File.separator, "html", File.separator);
  30 +
  31 + public final static String MALE_STYLE = StringUtils.concat(SUFFIX_CMS_URL, "index.html");
  32 + public final static String FEMALE_STYLE = StringUtils.concat(SUFFIX_CMS_URL, "index_wm.html");
  33 + public final static String CHILD_STYLE = StringUtils.concat(SUFFIX_CMS_URL, "index_kid.html");
  34 + //门店对应的地址
  35 + public final static String MALL_LGY = "http://news.baidu.com/";
  36 + public final static String MALL_WFJ = "http://www.baidu.com/";
  37 + public final static String MALL_WKS = "http://news.baidu.com/";
  38 + public final static String MALL_SLH = "http:/www.sina.com.cn/";
  39 +
  40 + //帖子发布评论
  41 + public final static String PUBLISH_COMMENT = StringUtils.concat(APP_HOST_TALENT, "fashion/commentInvitation");
  42 + //获取帖子详情
  43 + public final static String GETINVITATIONINFO = StringUtils.concat(APP_HOST_TALENT, "fashion/getInvitationInfo");
  44 + //发布 上传图片
  45 + public final static String RELASEINVITATION = StringUtils.concat(APP_HOST_TALENT, "fashion/relaseInvitation");
  46 + //达人的发布
  47 + public final static String PUBLICINVITATION = StringUtils.concat(APP_HOST_TALENT, "fashion/publicInvitation");
  48 + //点赞
  49 + public final static String PRAISEINVITATION = StringUtils.concat(APP_HOST_TALENT, "fashion/publicInvitation");
  50 + //取消点赞
  51 + public final static String CANCELPRAISE = StringUtils.concat(APP_HOST_TALENT, "fashion/cancelPraise");
  52 + //关注
  53 + public final static String ATTENTIONINVITATION = StringUtils.concat(APP_HOST_TALENT, "fashion/attentionInvitation");
  54 + //取消关注
  55 + public final static String CANCELATTENTION = StringUtils.concat(APP_HOST_TALENT, "fashion/cancelAttention");
  56 + //修改帖子
  57 + public final static String UPDATEINVITATION = StringUtils.concat(APP_HOST_TALENT, "fashion/updateInvitation");
  58 + //帖子的删除
  59 + public final static String DELETEINVITATION = StringUtils.concat(APP_HOST_TALENT, "fashion/deleteInvitation");
  60 + //获取帖子分享到第三方需要的资料
  61 + public final static String SHARESANINVITATION = StringUtils.concat(APP_HOST_TALENT, "fashion/shareSanInvitation");
  62 + //用户签到
  63 + public final static String ADDDAILYSIGN = StringUtils.concat(APP_HOST_TALENT, "member/addDailysign");
  64 + //获取用户本月所有的签到信息
  65 + public final static String GETDAILYSIGN = StringUtils.concat(APP_HOST_TALENT, "member/getDailysign");
  66 + //意见反馈接口
  67 + public final static String ADDFEEDBACK = StringUtils.concat(APP_HOST_TALENT, "member/addFeedback");
  68 +
  69 +
  70 + //商品详情
  71 + public static final String H5_GOOD_DETAIL = StringUtils.concat(BASE_H5_URL + "goodsDetail.html?productSid=%1$s&supplySid=%2$s&channelMark=%3$s& optUserName=%4$s");
  72 + //待支付
  73 + public static final String H5_ORDER_UNPAY = StringUtils.concat(BASE_H5_URL + "order.html?k=waitpay");
  74 + //待提货
  75 + public static final String H5_ORDER_UNRECEIVER = StringUtils.concat(BASE_H5_URL + "order.html?k=waitpick");
  76 + //配送中
  77 + public static final String H5_ORDER_ONTHEWAY = StringUtils.concat(BASE_H5_URL + "order.html?k=delivering");
  78 + //全部订单
  79 + public static final String H5_ORDER_ALL = StringUtils.concat(BASE_H5_URL + "order.html?k=allorder");
  80 + //退货订单
  81 + public static final String H5_ORDER_REFUND = StringUtils.concat(BASE_H5_URL + "refundOrder.html");
  82 + //订单回收站
  83 + public static final String H5_ORDER_RECYCLE = StringUtils.concat(BASE_H5_URL + "order.html?k=recycle");
  84 + //积分
  85 + public static final String H5_JIFEN = StringUtils.concat(BASE_H5_URL + "jifen.html");
  86 + //我的券
  87 + public static final String H5_MY_COUPON = StringUtils.concat(BASE_H5_URL + "myCoupon.html");
  88 + //领取券
  89 + public static final String H5_GET_COUPON = StringUtils.concat(BASE_H5_URL + "getCoupon.html");
  90 + //关于
  91 + public static final String H5_ABOUT = StringUtils.concat(BASE_H5_URL + "about.html");
  92 + //帮助中心
  93 + public static final String H5_HELP = StringUtils.concat(BASE_H5_URL + "help.html");
  94 +}
  1 +package com.xdy.commonlibrary.api;
  2 +
  3 +import com.google.gson.Gson;
  4 +import com.google.gson.GsonBuilder;
  5 +import com.google.gson.JsonDeserializer;
  6 +import com.google.gson.TypeAdapter;
  7 +import com.google.gson.reflect.TypeToken;
  8 +import com.xdy.network.WrapGsonDeserializerInfo;
  9 +import com.xdy.commonlibrary.utils.dataprocess.DoubleMayBeEmptyStringDeserializer;
  10 +import com.xdy.commonlibrary.utils.dataprocess.IntegerMayBeEmptyStringDeserializer;
  11 +
  12 +import java.lang.annotation.Annotation;
  13 +import java.lang.reflect.Type;
  14 +import java.util.List;
  15 +
  16 +import okhttp3.RequestBody;
  17 +import okhttp3.ResponseBody;
  18 +import retrofit2.Converter;
  19 +import retrofit2.Retrofit;
  20 +
  21 +/**
  22 + * @author jianghongbo
  23 + * @version 1.0
  24 + * @file ShopinGsonConverterFactory.java
  25 + * @brief
  26 + * @date 2017/1/8
  27 + * Copyright (c) 2017, 上品折扣
  28 + * All rights reserved.
  29 + */
  30 +public class ShopinGsonConverterFactory extends Converter.Factory {
  31 +
  32 + static IntegerMayBeEmptyStringDeserializer emptyStringDeserializer = new IntegerMayBeEmptyStringDeserializer();
  33 + static DoubleMayBeEmptyStringDeserializer doubleEmptyStringDeserializer = new DoubleMayBeEmptyStringDeserializer();
  34 +
  35 + /**
  36 + * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
  37 + * decoding from JSON (when no charset is specified by a header) will use UTF-8.
  38 + */
  39 + public static ShopinGsonConverterFactory create(List<WrapGsonDeserializerInfo> info) {
  40 + GsonBuilder gsonBuilder = new GsonBuilder().serializeNulls();
  41 + //默认注册两个
  42 + gsonBuilder.registerTypeAdapter(int.class, emptyStringDeserializer);
  43 + gsonBuilder.registerTypeAdapter(double.class, doubleEmptyStringDeserializer);
  44 +
  45 + if (info != null && info.size() > 0) {
  46 + for (WrapGsonDeserializerInfo wrapGsonDeserializerInfo : info) {
  47 + JsonDeserializer deserializer = wrapGsonDeserializerInfo.getDeserializer();
  48 + Class cls = wrapGsonDeserializerInfo.getClazz();
  49 + gsonBuilder.registerTypeAdapter(cls, deserializer);
  50 + }
  51 + }
  52 +
  53 + Gson gson = gsonBuilder.create();
  54 + return new ShopinGsonConverterFactory(gson);
  55 + }
  56 +
  57 + /**
  58 + * Create an instance using {@code gson} for conversion. Encoding to JSON and
  59 + * decoding from JSON (when no charset is specified by a header) will use UTF-8.
  60 + */
  61 + public static ShopinGsonConverterFactory create() {
  62 + return ShopinGsonConverterFactory.create(null);
  63 + }
  64 +
  65 + private final Gson gson;
  66 +
  67 + private ShopinGsonConverterFactory(Gson gson) {
  68 + if (gson == null) throw new NullPointerException("gson == null");
  69 + this.gson = gson;
  70 + }
  71 +
  72 + @Override
  73 + public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
  74 + Retrofit retrofit) {
  75 + TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
  76 + return new ShopinGsonResponseBodyConverter<>(gson, adapter);
  77 + }
  78 +
  79 + @Override
  80 + public Converter<?, RequestBody> requestBodyConverter(Type type,
  81 + Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
  82 + TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
  83 + //在这里需要判断一下请求不同类型的数据了文件了,返回不同的转换
  84 + return new ShopinGsonRequestBodyConverter<>(gson, adapter);
  85 + }
  86 +}
  1 +/*
  2 + * Copyright (C) 2017 Square, Inc.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package com.xdy.commonlibrary.api;
  17 +
  18 +import com.google.gson.Gson;
  19 +import com.google.gson.TypeAdapter;
  20 +import com.google.gson.stream.JsonWriter;
  21 +
  22 +import java.io.IOException;
  23 +import java.io.OutputStreamWriter;
  24 +import java.io.Writer;
  25 +import java.nio.charset.Charset;
  26 +
  27 +import okhttp3.MediaType;
  28 +import okhttp3.RequestBody;
  29 +import okio.Buffer;
  30 +import retrofit2.Converter;
  31 +
  32 +final class ShopinGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
  33 + private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=UTF-8");
  34 + private static final MediaType MEDIA_TYPE_FILE = MediaType.parse("application/otcet-stream");
  35 + private static final Charset UTF_8 = Charset.forName("UTF-8");
  36 +
  37 + private final Gson gson;
  38 + private final TypeAdapter<T> adapter;
  39 +
  40 + ShopinGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
  41 + this.gson = gson;
  42 + this.adapter = adapter;
  43 + }
  44 +
  45 + @Override
  46 + public RequestBody convert(T value) throws IOException {
  47 + //请求的类型我们还不清楚,我们应该判断使用何种MEDIA_TYPE进行请求,默认是JSON的形式
  48 + Buffer buffer = new Buffer();
  49 + Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
  50 + JsonWriter jsonWriter = gson.newJsonWriter(writer);
  51 + adapter.write(jsonWriter, value);
  52 + jsonWriter.close();
  53 +
  54 +// return RequestBody.create(MEDIA_TYPE_FILE, file);
  55 + return RequestBody.create(MEDIA_TYPE_JSON, buffer.readByteString());
  56 + }
  57 +}
  1 +/*
  2 + * Copyright (C) 2017 Square, Inc.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package com.xdy.commonlibrary.api;
  17 +
  18 +import com.google.gson.Gson;
  19 +import com.google.gson.TypeAdapter;
  20 +import com.google.gson.stream.JsonReader;
  21 +
  22 +import java.io.IOException;
  23 +
  24 +import okhttp3.ResponseBody;
  25 +import retrofit2.Converter;
  26 +
  27 +final class ShopinGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  28 + private final Gson gson;
  29 + private final TypeAdapter<T> adapter;
  30 +
  31 + ShopinGsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
  32 + this.gson = gson;
  33 + this.adapter = adapter;
  34 + }
  35 +
  36 + @Override
  37 + public T convert(ResponseBody value) throws IOException {
  38 + //可以在这里通过异常的方式处理,也可以通过工具类统一的map变换一下。
  39 +// String response = value.string();
  40 +// ResultEntity result = gson.fromJson(response, ResultEntity.class);
  41 +// if (result != null && !result.isValidate(result.code)) {
  42 +// value.close();
  43 +// ResultException resultException = new ResultException(result.errorMessage);
  44 +// resultException.setResultCode(result.code);
  45 +// resultException.setErrorMessage(result.errorMessage);
  46 +// throw resultException;
  47 +// }
  48 +
  49 + //这里我们可以考虑直接T extentd BaseEntity 然后返回那个data
  50 + //返回正常结果
  51 + JsonReader jsonReader = gson.newJsonReader(value.charStream());
  52 + try {
  53 + return adapter.read(jsonReader);
  54 + } finally {
  55 + value.close();
  56 + }
  57 + }
  58 +}
  1 +package com.xdy.commonlibrary.api;
  2 +
  3 +import android.support.annotation.NonNull;
  4 +import android.text.TextUtils;
  5 +
  6 +import com.xdy.network.HttpConstants;
  7 +import com.xdy.util.AppUtil;
  8 +import com.xdy.commonlibrary.core.CommonAppLike;
  9 +import com.xdy.commonlibrary.utils.dataprocess.GsonUtil;
  10 +
  11 +import java.io.File;
  12 +import java.net.FileNameMap;
  13 +import java.net.URLConnection;
  14 +import java.util.List;
  15 +import java.util.Map;
  16 +import java.util.TreeMap;
  17 +
  18 +import okhttp3.MediaType;
  19 +import okhttp3.MultipartBody;
  20 +import okhttp3.RequestBody;
  21 +
  22 +/**
  23 + * @author jianghongbo
  24 + * @version 1.0
  25 + * @file ShopinRequestParams.java
  26 + * @brief 封装请求参数
  27 + * @date 2017/1/8
  28 + * Copyright (c) 2017, 上品折扣
  29 + * All rights reserved.
  30 + */
  31 +public class ShopinRequestParams {
  32 +
  33 + private ShopinRequestParams() {
  34 + }
  35 +
  36 + public static Builder build() {
  37 + return new Builder();
  38 + }
  39 +
  40 + public static class Builder {
  41 + public Builder() {
  42 + }
  43 +
  44 + Map<String, Object> map = new TreeMap<>();
  45 +
  46 + public Builder add(String key, Object value) {
  47 + if (!TextUtils.isEmpty(key) && value != null) {
  48 + map.put(key, value);
  49 + }
  50 + return this;
  51 + }
  52 +
  53 + /**
  54 + * 用于content type为json的post请求,service方法为@Body类型的参数
  55 + * @return
  56 + */
  57 + public RequestBody body() {
  58 + //添加公共参数
  59 + addCommonParams();
  60 + String body = GsonUtil.bean2json(map);
  61 + return RequestBody.create(MediaType.parse(HttpConstants.CONTENT_TYPE_FORM), body);
  62 + }
  63 +
  64 + /**
  65 + * 返回一个map用于QueryMap注解的参数类型
  66 + * @return
  67 + */
  68 + public Map<String, Object> paramsMap() {
  69 + //添加公共参数
  70 + addCommonParams();
  71 + return map;
  72 + }
  73 +
  74 + public MultipartBody.Builder filesToMultipartBody(@NonNull List<File> files) {
  75 + MultipartBody.Builder builder = new MultipartBody.Builder();
  76 +
  77 + for (int i = 0; i < files.size(); i++) {
  78 + File file = files.get(i);
  79 + // 这里为了简单起见,没有判断file的类型,并且按照本项目只能上传一个文件 并且name为file修改
  80 + RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);
  81 + //文件以file0,1,2这样命名
  82 + builder.addFormDataPart("file", file.getName(), requestBody);
  83 + }
  84 + builder.setType(MultipartBody.FORM);
  85 + return builder;
  86 + }
  87 +
  88 + private void addCommonParams() {
  89 + add("deviceType", "1")
  90 + .add("deviceSn", AppUtil.getDeviceId(CommonAppLike.getContext()))
  91 + .add("appVersion", AppUtil.getVersionName(CommonAppLike.getContext()))
  92 + .add("systemVersion", AppUtil.getOSVersion())
  93 + .add("versionNo", String.valueOf(AppUtil.getVersionCode(CommonAppLike.getContext())));
  94 + }
  95 +
  96 + public Builder addAudio(String key, String path) {
  97 + File file = new File(path);
  98 + FileNameMap fileNameMap = URLConnection.getFileNameMap();
  99 + String contentTypeFor = fileNameMap.getContentTypeFor(path);
  100 + RequestBody requestBody =
  101 + RequestBody.create(MediaType.parse(contentTypeFor), file);
  102 + map.put(key + "\";filename=\"" + file.getName(), requestBody);
  103 + return this;
  104 + }
  105 +
  106 + public Builder addPic(String key, List<File> fileList) {
  107 + for (int i = 0; i < fileList.size(); i++) {
  108 + RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpg"), fileList.get(i));
  109 + map.put(key + "[" + i + "]" + "\";filename=\"" + fileList.get(i).getName(), requestBody);
  110 + }
  111 + return this;
  112 + }
  113 +
  114 + public Builder addSinglePic(String key, File file) {
  115 + RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpg"), file);
  116 + map.put(key + "\";filename=\"" + file.getName(), requestBody);
  117 + return this;
  118 + }
  119 +
  120 +
  121 + public Builder addGif(String key, File file) {
  122 + RequestBody requestBody = RequestBody.create(MediaType.parse("image/gif"), file);
  123 + map.put(key + "\";filename=\"" + file.getName(), requestBody);
  124 + return this;
  125 + }
  126 +
  127 + public Builder addVideo(String key, String path) {
  128 + File file = new File(path);
  129 + RequestBody requestBody = RequestBody.create(MediaType.parse("video/mp4"), file);
  130 + map.put(key + "\";filename=\"" + file.getName(), requestBody);
  131 + return this;
  132 + }
  133 + }
  134 +
  135 +
  136 +}
  1 +package com.xdy.commonlibrary.api.interceptor;
  2 +
  3 +import android.text.TextUtils;
  4 +
  5 +import com.xdy.util.AppUtil;
  6 +import com.xdy.util.StringUtils;
  7 +import com.xdy.commonlibrary.core.CommonAppLike;
  8 +
  9 +import org.json.JSONArray;
  10 +import org.json.JSONException;
  11 +import org.json.JSONObject;
  12 +
  13 +import java.io.IOException;
  14 +import java.util.ArrayList;
  15 +import java.util.Arrays;
  16 +import java.util.HashMap;
  17 +import java.util.Iterator;
  18 +import java.util.List;
  19 +import java.util.Map;
  20 +
  21 +import okhttp3.FormBody;
  22 +import okhttp3.Headers;
  23 +import okhttp3.HttpUrl;
  24 +import okhttp3.Interceptor;
  25 +import okhttp3.MediaType;
  26 +import okhttp3.Request;
  27 +import okhttp3.RequestBody;
  28 +import okhttp3.Response;
  29 +import okio.Buffer;
  30 +
  31 +
  32 +/**
  33 + * Created by jk.yeo on 16/3/4 15:28.
  34 + * Mail to ykooze@gmail.com
  35 + */
  36 +public class BasicParamsInterceptor implements Interceptor {
  37 +
  38 + Map<String, String> queryParamsMap = new HashMap<>();
  39 + Map<String, String> paramsMap = new HashMap<>();
  40 + Map<String, String> headerParamsMap = new HashMap<>();
  41 + List<String> headerLinesList = new ArrayList<>();
  42 +
  43 + private BasicParamsInterceptor() {
  44 +
  45 + }
  46 +
  47 + @Override
  48 + public Response intercept(Chain chain) throws IOException {
  49 +
  50 + Request request = chain.request();
  51 + Request.Builder requestBuilder = request.newBuilder();
  52 +
  53 + /*
  54 + * process header params inject ,
  55 + * 支持完整的请求头参数和name value两种形式
  56 + * 如 可以通过headerLineList 直接加入 content-type:application/json
  57 + * 也可以通过headerParamsMap加入name为content-type value为applicaiton/json的头
  58 + *
  59 + */
  60 + Headers.Builder headerBuilder = request.headers().newBuilder();
  61 + if (headerParamsMap.size() > 0) {
  62 + Iterator iterator = headerParamsMap.entrySet().iterator();
  63 + while (iterator.hasNext()) {
  64 + Map.Entry entry = (Map.Entry) iterator.next();
  65 + headerBuilder.add((String) entry.getKey(), (String) entry.getValue());
  66 + }
  67 + }
  68 +
  69 + if (headerLinesList.size() > 0) {
  70 + for (String line : headerLinesList) {
  71 + headerBuilder.add(line);
  72 + }
  73 + requestBuilder.headers(headerBuilder.build());
  74 + }
  75 + // process header params end
  76 +
  77 +
  78 + /*
  79 + process queryParams inject whatever it's GET ,如果POST也要加到URL中把第二个判断条件去掉即可
  80 + 是否在query参数中加入公共参数,稍微改一下只加入到URL上面
  81 + */
  82 + if (queryParamsMap.size() > 0 && canInjectIntoUrl(request)) {
  83 + //根据需要加入设备ID
  84 + addDeviceId(queryParamsMap);
  85 + request = injectParamsIntoUrl(request.url().newBuilder(), requestBuilder, queryParamsMap);
  86 + }
  87 +
  88 + // process post body inject
  89 + if (paramsMap.size() > 0) {
  90 + //根据需要加入设备ID
  91 + addDeviceId(paramsMap);
  92 +
  93 + if (canInjectIntoFormBody(request)) {
  94 +
  95 + //表单提交公共参数
  96 + FormBody.Builder formBodyBuilder = new FormBody.Builder();
  97 + for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
  98 + formBodyBuilder.add((String) entry.getKey(), (String) entry.getValue());
  99 + }
  100 +
  101 + RequestBody formBody = formBodyBuilder.build();
  102 + String postBodyString = bodyToString(request.body());
  103 + postBodyString += StringUtils.concat(postBodyString.length() > 0 ? "&" : "", bodyToString(formBody));
  104 + requestBuilder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString));
  105 + } else if (canInjectIntoJsonBody(request)) {
  106 + String postBodyString = bodyToString(request.body());
  107 + if (!TextUtils.isEmpty(postBodyString)) {
  108 + int i = postBodyString.lastIndexOf('}');
  109 + if (i != -1) {
  110 + try {
  111 + JSONObject object = new JSONObject(postBodyString);
  112 + for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
  113 + object.put(entry.getKey(), entry.getValue());
  114 + }
  115 +
  116 + postBodyString = object.toString();
  117 + } catch (JSONException e) {
  118 + e.printStackTrace();
  119 + }
  120 + }
  121 + }
  122 +
  123 + requestBuilder.post(RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), postBodyString));
  124 + }
  125 + }
  126 +
  127 + request = requestBuilder.build();
  128 + return chain.proceed(request);
  129 + }
  130 +
  131 + private void addDeviceId(Map<String, String> map) {
  132 + boolean hasDeviceId = !TextUtils.isEmpty(map.get("deviceSn"));
  133 + if (!hasDeviceId) {
  134 + String deviceId = AppUtil.getDeviceId(CommonAppLike.getContext());
  135 + map.put("deviceSn", deviceId);
  136 + }
  137 + }
  138 +
  139 + /**
  140 + * 是否能加入到BODY中,必须是POST FORM表单提交参数才能添加
  141 + * @param request
  142 + * @return
  143 + */
  144 + private boolean canInjectIntoFormBody(Request request) {
  145 + if (request == null) {
  146 + return false;
  147 + }
  148 + if (!TextUtils.equals(request.method(), "POST")) {
  149 + return false;
  150 + }
  151 + RequestBody body = request.body();
  152 + if (body == null) {
  153 + return false;
  154 + }
  155 + MediaType mediaType = body.contentType();
  156 + if (mediaType == null) {
  157 + return false;
  158 + }
  159 +
  160 + if (!TextUtils.equals(mediaType.subtype(), "x-www-form-urlencoded")) {
  161 + return false;
  162 + }
  163 + return true;
  164 + }
  165 +
  166 + /**
  167 + * 是否能加入到请求地址中
  168 + * @param request
  169 + * @return
  170 + */
  171 + private boolean canInjectIntoUrl(Request request) {
  172 + if (request == null) {
  173 + return false;
  174 + }
  175 + if (!TextUtils.equals(request.method(), "GET")) {
  176 + return false;
  177 + }
  178 + return true;
  179 + }
  180 +
  181 + /**
  182 + * 是否能加入到JSON格式中,必须是POST JSON提交参数才能添加
  183 + * @param request
  184 + * @return
  185 + */
  186 + private boolean canInjectIntoJsonBody(Request request) {
  187 +// if (paramsMap.size() == 0) {
  188 +// return false;
  189 +// }
  190 +
  191 + if (request == null) {
  192 + return false;
  193 + }
  194 + if (!TextUtils.equals(request.method(), "POST")) {
  195 + return false;
  196 + }
  197 + RequestBody body = request.body();
  198 + if (body == null) {
  199 + return false;
  200 + }
  201 + MediaType mediaType = body.contentType();
  202 + if (mediaType == null) {
  203 + return false;
  204 + }
  205 +
  206 + //判断子类型是不是json格式 格式为 [type]/[subType]
  207 + if (!TextUtils.equals(mediaType.subtype(), "json")) {
  208 + return false;
  209 + }
  210 + return true;
  211 + }
  212 +
  213 + // func to inject params into url
  214 + private Request injectParamsIntoUrl(HttpUrl.Builder httpUrlBuilder, Request.Builder requestBuilder, Map<String, String> paramsMap) {
  215 + if (paramsMap.size() > 0) {
  216 + Iterator iterator = paramsMap.entrySet().iterator();
  217 + while (iterator.hasNext()) {
  218 + Map.Entry entry = (Map.Entry) iterator.next();
  219 + httpUrlBuilder.addQueryParameter((String) entry.getKey(), (String) entry.getValue());
  220 + }
  221 + requestBuilder.url(httpUrlBuilder.build());
  222 + return requestBuilder.build();
  223 + }
  224 +
  225 + return null;
  226 + }
  227 +
  228 + private static String bodyToString(final RequestBody request) {
  229 + try {
  230 + final RequestBody copy = request;
  231 + final Buffer buffer = new Buffer();
  232 + if (copy != null)
  233 + copy.writeTo(buffer);
  234 + else
  235 + return "";
  236 + return buffer.readUtf8();
  237 + } catch (final IOException e) {
  238 + return "did not work";
  239 + }
  240 + }
  241 +
  242 + public static class Builder {
  243 +
  244 + BasicParamsInterceptor interceptor;
  245 +
  246 + public Builder() {
  247 + interceptor = new BasicParamsInterceptor();
  248 + }
  249 +
  250 + public Builder addParam(String key, String value) {
  251 + interceptor.paramsMap.put(key, value);
  252 + return this;
  253 + }
  254 +
  255 + public Builder addParamsMap(Map<String, String> paramsMap) {
  256 + interceptor.paramsMap.putAll(paramsMap);
  257 + return this;
  258 + }
  259 +
  260 + public Builder addHeaderParam(String key, String value) {
  261 + interceptor.headerParamsMap.put(key, value);
  262 + return this;
  263 + }
  264 +
  265 + public Builder addHeaderParamsMap(Map<String, String> headerParamsMap) {
  266 + interceptor.headerParamsMap.putAll(headerParamsMap);
  267 + return this;
  268 + }
  269 +
  270 + public Builder addHeaderLine(String headerLine) {
  271 + int index = headerLine.indexOf(":");
  272 + if (index == -1) {
  273 + throw new IllegalArgumentException("Unexpected header: " + headerLine);
  274 + }
  275 + interceptor.headerLinesList.add(headerLine);
  276 + return this;
  277 + }
  278 +
  279 + public Builder addHeaderLinesList(List<String> headerLinesList) {
  280 + for (String headerLine : headerLinesList) {
  281 + int index = headerLine.indexOf(":");
  282 + if (index == -1) {
  283 + throw new IllegalArgumentException("Unexpected header: " + headerLine);
  284 + }
  285 + interceptor.headerLinesList.add(headerLine);
  286 + }
  287 + return this;
  288 + }
  289 +
  290 + public Builder addQueryParam(String key, String value) {
  291 + interceptor.queryParamsMap.put(key, value);
  292 + return this;
  293 + }
  294 +
  295 + public Builder addQueryParamsMap(Map<String, String> queryParamsMap) {
  296 + interceptor.queryParamsMap.putAll(queryParamsMap);
  297 + return this;
  298 + }
  299 +
  300 + public BasicParamsInterceptor build() {
  301 + return interceptor;
  302 + }
  303 +
  304 + }
  305 +
  306 +
  307 + /**
  308 + * @param obj
  309 + * @return
  310 + * @brief 对JSONOBJECT内部进行排序
  311 + */
  312 + public static String sortJSONObject(JSONObject obj) {
  313 + try {
  314 + if (obj == null)
  315 + return null;
  316 +
  317 + Iterator<String> keys = obj.keys();
  318 + String[] keySort = new String[obj.length()];
  319 +
  320 + //把KEY取出来
  321 + for (int i = 0; i < keySort.length; i++) {
  322 + keySort[i] = keys.next();
  323 + }
  324 + //对Key进行排序
  325 + Arrays.sort(keySort);
  326 +
  327 + StringBuilder sb = new StringBuilder();
  328 + for (int i = 0; i < keySort.length; i++) {
  329 + sb.append(keySort[i]);
  330 + sb.append("=");
  331 + //先取值的类型
  332 + Object opt = obj.opt(keySort[i]);
  333 + if (opt instanceof Number) {
  334 + //对于数字类型的数据要用JSONObject处理数字方式重新处理,否则会与传递给服务器的不一样,因为在put参数的时候会按这样的方式做检查处理,会导致舍弃精度的操作。
  335 + String num = JSONObject.numberToString((Number) opt);
  336 + sb.append(num);
  337 + } else if (opt instanceof JSONArray) {//判断是否是JSONArray
  338 + //提供一个方法用于返回JSONArray的值,此处按理来说应该递归sortJSONArray,但是后台为了简单点处理,直接把第二层做字符串拼接起来
  339 + String result = sortJSONArray((JSONArray) opt);
  340 + sb.append(result);
  341 + } else {
  342 + sb.append(obj.optString(keySort[i]));
  343 + }
  344 + }
  345 + return sb.toString();
  346 + } catch (JSONException e) {
  347 + e.printStackTrace();
  348 + return null;
  349 + }
  350 + }
  351 +
  352 + public static String sortJSONArray(JSONArray value) {
  353 + StringBuilder jsonString = new StringBuilder();
  354 + for (int i = 0; i < value.length(); i++) {
  355 + String s = sortJSONObject(value.optJSONObject(i));
  356 + //如果为空,取字符串
  357 + if (TextUtils.isEmpty(s)) {
  358 + s = value.optString(i);
  359 + }
  360 + jsonString.append(s);
  361 + }
  362 + return jsonString.toString();
  363 + }
  364 +}
  1 +package com.xdy.commonlibrary.api.interceptor;
  2 +
  3 +import android.support.annotation.NonNull;
  4 +
  5 +import com.xdy.network.http.GlobeHttpHandler;
  6 +import com.xdy.util.LogUtil;
  7 +import com.xdy.util.StringUtils;
  8 +import com.xdy.commonlibrary.utils.ZipHelper;
  9 +
  10 +import java.io.IOException;
  11 +import java.io.UnsupportedEncodingException;
  12 +import java.net.URLDecoder;
  13 +import java.nio.charset.Charset;
  14 +
  15 +import javax.inject.Inject;
  16 +import javax.inject.Singleton;
  17 +
  18 +import okhttp3.Interceptor;
  19 +import okhttp3.MediaType;
  20 +import okhttp3.Request;
  21 +import okhttp3.RequestBody;
  22 +import okhttp3.Response;
  23 +import okhttp3.ResponseBody;
  24 +import okio.Buffer;
  25 +import okio.BufferedSource;
  26 +
  27 +
  28 +@Singleton
  29 +public class RequestIntercept implements Interceptor {
  30 + private GlobeHttpHandler mHandler;
  31 +
  32 + @Inject
  33 + public RequestIntercept(GlobeHttpHandler handler) {
  34 + this.mHandler = handler;
  35 + }
  36 +
  37 + @Override
  38 + public Response intercept(Chain chain) throws IOException {
  39 + Request request = chain.request();
  40 +
  41 + if (mHandler != null)//在请求服务器之前可以拿到request,做一些操作比如给request添加header,如果不做操作则返回参数中的request
  42 + request = mHandler.onHttpRequestBefore(chain, request);
  43 +
  44 + Buffer requestbuffer = new Buffer();
  45 + if (request.body() != null) {
  46 + request.body().writeTo(requestbuffer);
  47 + }
  48 + LogUtil.i("Request", "Sending Request %s %n Params ---> %s", request.url()
  49 + , request.body() != null ? parseParams(request.body(), requestbuffer) : "null");
  50 +
  51 + long t1 = System.nanoTime();
  52 + Response originalResponse = chain.proceed(request);
  53 + long t2 = System.nanoTime();
  54 + LogUtil.i("Request", "Sending Request %s %nReceived response in %.1fms"
  55 + , request.url()
  56 + , (t2 - t1) / 1e6d);
  57 +
  58 + //读取服务器返回的结果
  59 + ResponseBody responseBody = originalResponse.body();
  60 + BufferedSource source = responseBody.source();
  61 + source.request(Long.MAX_VALUE); // Buffer the entire body.
  62 + Buffer buffer = source.buffer();
  63 +
  64 + //获取content的压缩类型
  65 + String encoding = originalResponse
  66 + .headers()
  67 + .get("Content-Encoding");
  68 +
  69 + Buffer clone = buffer.clone();
  70 + String bodyString;
  71 +
  72 + //解析response content
  73 + if (encoding != null && encoding.equalsIgnoreCase("gzip")) {//content使用gzip压缩
  74 + bodyString = ZipHelper.decompressForGzip(clone.readByteArray());//解压
  75 + } else if (encoding != null && encoding.equalsIgnoreCase("zlib")) {//content使用zlib压缩
  76 + bodyString = ZipHelper.decompressToStringForZlib(clone.readByteArray());//解压
  77 + } else {//content没有被压缩
  78 + Charset charset = Charset.forName("UTF-8");
  79 + MediaType contentType = responseBody.contentType();
  80 + if (contentType != null) {
  81 + charset = contentType.charset(charset);
  82 + }
  83 + bodyString = clone.readString(charset);
  84 + LogUtil.i("Result", StringUtils.jsonFormat(bodyString));
  85 + }
  86 +
  87 +
  88 + if (mHandler != null)//这里可以比客户端提前一步拿到服务器返回的结果,可以做一些操作,比如token超时,重新获取
  89 + return mHandler.onHttpResultResponse(bodyString, chain, originalResponse);
  90 +
  91 + return originalResponse;
  92 +// return originalResponse.newBuilder()
  93 +// .body(ResponseBody.create(MediaType.parse("UTF-8"), bodyString))
  94 +// .build();
  95 + }
  96 +
  97 + @NonNull
  98 + public static String parseParams(RequestBody body, Buffer requestbuffer) throws UnsupportedEncodingException {
  99 + if (body.contentType() != null && !body.contentType().toString().contains("multipart")) {
  100 + return URLDecoder.decode(requestbuffer.readUtf8(), "UTF-8");
  101 + }
  102 + return "null";
  103 + }
  104 +
  105 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +/**
  4 + * @author jianghongbo
  5 + * @version 1.0
  6 + * @file AbsCrashHandler.java
  7 + * @brief
  8 + * @date 2017/12/19
  9 + * Copyright (c) 2017
  10 + * All rights reserved.
  11 + */
  12 +public abstract class AbsCrashHandler implements Thread.UncaughtExceptionHandler {
  13 +
  14 + public void init() {
  15 + Thread.currentThread().setUncaughtExceptionHandler(this);
  16 + }
  17 +
  18 + /**
  19 + * 当UncaughtException发生时会转入该函数来处理
  20 + */
  21 + @Override
  22 + public void uncaughtException(final Thread thread, final Throwable throwable) {
  23 + handleException(throwable);
  24 + }
  25 +
  26 + /**
  27 + * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑
  28 + * @param throwable
  29 + */
  30 + private void handleException(final Throwable throwable) {
  31 + if (!AppConfig.LOCAL_FILE_DIR.exists())
  32 + AppConfig.LOCAL_FILE_DIR.mkdirs();
  33 + saveCrash(throwable);
  34 + }
  35 +
  36 + /**
  37 + * 保存崩溃的信息
  38 + */
  39 + abstract void saveCrash(Throwable throwable);
  40 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import android.app.Dialog;
  4 +import android.os.Bundle;
  5 +import android.support.annotation.Nullable;
  6 +import android.support.annotation.StringRes;
  7 +
  8 +import com.flyco.systembar.SystemBarHelper;
  9 +import com.xdy.commonlibrary.core.di.AppComponent;
  10 +import com.xdy.commonlibrary.mvp.BasePresenter;
  11 +import com.xdy.commonlibrary.mvp.BaseView;
  12 +import com.xdy.ui.loading.LoadingDialogUtils;
  13 +import com.xdy.util.ActivityUtil;
  14 +import com.xdy.util.ResUtil;
  15 +import com.xdy.util.ToastUtil;
  16 +import com.xdy.util.UIUtils;
  17 +
  18 +import javax.inject.Inject;
  19 +
  20 +
  21 +/**
  22 + * @author jianghongbo
  23 + * @version 1.0
  24 + * @file AppBaseActivity.java
  25 + * @brief Activity业务基类
  26 + * @date 2017/12/25
  27 + * Copyright (c) 2017,上品折扣
  28 + * All rights reserved.
  29 + */
  30 +public abstract class AppBaseActivity<P extends BasePresenter> extends com.xdy.commonlibrary.core.BaseActivity implements BaseView {
  31 +
  32 + protected com.xdy.commonlibrary.core.CommonAppLike mApplication;
  33 +
  34 + @Inject
  35 + protected P mPresenter;
  36 + //状态深色样式
  37 + public static final int TITLE_STYLE_DARK = 0x0;
  38 + //浅色样式
  39 + public static final int TITLE_STYLE_LIGHT = 0x1;
  40 + //男士标题
  41 + public static final int TITLE_STYLE_MALE = 0x2;
  42 + //女士标题
  43 + public static final int TITLE_STYLE_FEMAL = 0x3;
  44 + //儿童标题
  45 + public static final int TITLE_STYLE_CHILD = 0x4;
  46 +
  47 + //透明
  48 + protected static final int TITLE_STYLE_TRANSPARENT = 0x2;
  49 +
  50 + //是否活动的标记
  51 + private boolean isActive;
  52 + //加载进度条
  53 + private Dialog loadingDialog;
  54 +
  55 + @Override
  56 + protected void onCreate(@Nullable Bundle savedInstanceState) {
  57 + super.onCreate(savedInstanceState);
  58 + isActive = true;
  59 + // 添加Activity到堆栈
  60 + ActivityUtil.getInstance().addActivity(this);
  61 + getIntentParams();
  62 + initBaseLayout();
  63 + setStatusBarStyle();//不能加到前面
  64 + bindView();
  65 + initViews(savedInstanceState);
  66 + initComponent();
  67 + initData();
  68 + }
  69 +
  70 + private void initComponent() {
  71 + AppComponent appComponent = com.xdy.commonlibrary.core.CommonAppLike.getInstance().getAppComponent();
  72 + setupActivityComponent(appComponent);//依赖注入
  73 + }
  74 +
  75 + private void bindView() {
  76 + }
  77 +
  78 + //提供AppComponent(提供所有的单例对象)给子类,进行Component依赖
  79 + protected abstract void setupActivityComponent(AppComponent appComponent);
  80 +
  81 + /**
  82 + * 获得整个布局ID
  83 + * @return
  84 + */
  85 + protected abstract int getLayoutId();
  86 +
  87 + @Override
  88 + protected void onDestroy() {
  89 + if (mPresenter != null) mPresenter.onDestroy();//释放资源
  90 + this.mPresenter = null;
  91 + this.mApplication = null;
  92 + isActive = false;
  93 + ActivityUtil.getInstance().finishActivity(this);
  94 + super.onDestroy();
  95 +
  96 + }
  97 +
  98 + /**
  99 + * 提供给子类初始化基类布局使用
  100 + */
  101 + protected void initBaseLayout() {
  102 + }
  103 +
  104 + /**
  105 + * 获取标题栏样式
  106 + * @return
  107 + */
  108 + protected int getTitleBarStyle() {
  109 + return TITLE_STYLE_DARK;
  110 + }
  111 +
  112 + private void setStatusBarStyle() {
  113 + //此项目只根据主题类型设置
  114 + int titleBarStyle = getTitleBarStyle();
  115 + switch (titleBarStyle) {
  116 + case TITLE_STYLE_TRANSPARENT:
  117 + SystemBarHelper.immersiveStatusBar(this, 0f);
  118 + break;
  119 + default:
  120 + break;
  121 + }
  122 + }
  123 +
  124 + @Override
  125 + public void showLoading() {
  126 + if (loadingDialog != null && loadingDialog.isShowing())
  127 + return;
  128 + if (loadingDialog == null)
  129 + loadingDialog = LoadingDialogUtils.createLoadingDialog(this, null);
  130 + loadingDialog.show();
  131 + }
  132 +
  133 + @Override
  134 + public void hideLoading() {
  135 + UIUtils.closeDialog(loadingDialog);
  136 + }
  137 +
  138 + @Override
  139 + public void showMessage(String message) {
  140 + ToastUtil.showToast(getBaseContext(),message);
  141 + }
  142 +
  143 + public void showMessage(@StringRes int res) {
  144 + showMessage(ResUtil.get().getString(res));
  145 + }
  146 +
  147 + @Override
  148 + public boolean isActive() {
  149 + return isActive;
  150 + }
  151 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import android.os.Bundle;
  4 +import android.support.annotation.LayoutRes;
  5 +import android.support.annotation.NonNull;
  6 +import android.support.annotation.Nullable;
  7 +import android.support.annotation.StringRes;
  8 +import android.view.LayoutInflater;
  9 +import android.view.View;
  10 +import android.view.ViewGroup;
  11 +
  12 +import com.xdy.ui.viewgroup.CodeMultipleStatusView;
  13 +import com.xdy.util.ResUtil;
  14 +import com.xdy.commonlibrary.core.di.AppComponent;
  15 +import com.xdy.commonlibrary.mvp.BasePresenter;
  16 +import com.xdy.commonlibrary.mvp.BaseView;
  17 +
  18 +import javax.inject.Inject;
  19 +
  20 +
  21 +/**
  22 + * @author jianghongbo
  23 + * @version 1.0
  24 + * @file AppBaseFragment.java
  25 + * @brief
  26 + * @date 2017/12/25
  27 + * Copyright (c) 2017
  28 + * All rights reserved.
  29 + */
  30 +public abstract class AppBaseFragment<P extends BasePresenter> extends BaseFragment implements BaseView {
  31 +
  32 + protected BaseActivity mActivity;
  33 + protected CodeMultipleStatusView mRootView;
  34 + protected final String TAG = this.getClass().getSimpleName();
  35 + @Inject
  36 + protected P mPresenter;
  37 +
  38 + public <T extends View> T $(View v, int id) {
  39 + return (T) v.findViewById(id);
  40 + }
  41 +
  42 + @Override
  43 + public void onDestroyView() {
  44 + super.onDestroyView();
  45 + }
  46 +
  47 + @Override
  48 + public void onDestroy() {
  49 + super.onDestroy();
  50 + if (mPresenter != null) mPresenter.onDestroy();//释放资源
  51 + this.mPresenter = null;
  52 + this.mActivity = null;
  53 + this.mRootView = null;
  54 + }
  55 +
  56 + @Override
  57 + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  58 + mRootView = new CodeMultipleStatusView(getContext());
  59 + return mRootView;
  60 + }
  61 +
  62 + @Override
  63 + public void onActivityCreated(Bundle savedInstanceState) {
  64 + mActivity = (BaseActivity) getActivity();
  65 + initComponent();
  66 + super.onActivityCreated(savedInstanceState);
  67 + }
  68 +
  69 + @Override
  70 + public void onLazyInitView(@Nullable Bundle savedInstanceState) {
  71 + super.onLazyInitView(savedInstanceState);
  72 + //加载我们自己的布局
  73 + View view = View.inflate(getContext(), this.getLayoutId(), null);
  74 + mRootView.setContentView(view);
  75 + mRootView.showContent();
  76 + mRootView.setOnRetryClickListener(new View.OnClickListener() {
  77 + @Override
  78 + public void onClick(View v) {
  79 + retry();
  80 + }
  81 + });
  82 + initView(view, savedInstanceState);
  83 + initData();
  84 + }
  85 +
  86 + private void initComponent() {
  87 + AppComponent appComponent = CommonAppLike.getInstance().getAppComponent();
  88 + setupFragmentComponent(appComponent);
  89 + }
  90 +
  91 + protected void setHeaderTitle(String title) {
  92 + if (getBaseActivity() instanceof TitleBaseActivity) {
  93 + ((TitleBaseActivity) getBaseActivity()).setHeaderTitle(title);
  94 + }
  95 + }
  96 +
  97 + protected void setHeaderTitle(@StringRes int res) {
  98 + if (getBaseActivity() instanceof TitleBaseActivity) {
  99 + ((TitleBaseActivity) getBaseActivity()).setHeaderTitle(res);
  100 + }
  101 + }
  102 +
  103 + /**
  104 + * 注入Fragment的组件
  105 + * @param appComponent
  106 + */
  107 + protected abstract void setupFragmentComponent(AppComponent appComponent);
  108 +
  109 + /**
  110 + * 初始化控件
  111 + */
  112 + protected abstract void initView(View v, Bundle savedInstanceState);
  113 +
  114 + /**
  115 + * 初始化数据
  116 + */
  117 + protected abstract void initData();
  118 +
  119 + /**
  120 + * 获得Fragment布局ID,除了TitleBaseFragment。
  121 + * @return
  122 + */
  123 + @NonNull
  124 + @LayoutRes
  125 + protected abstract int getLayoutId();
  126 +
  127 + /**
  128 + * 获得所属Activity,有可能为空
  129 + * @return
  130 + */
  131 + protected AppBaseActivity getBaseActivity() {
  132 + if (getActivity() instanceof AppBaseActivity)
  133 + return (AppBaseActivity) getActivity();
  134 + return null;
  135 + }
  136 +
  137 +
  138 + @Override
  139 + public void showLoading() {
  140 + AppBaseActivity baseActivity = getBaseActivity();
  141 + if (baseActivity != null && baseActivity.isActive())
  142 + baseActivity.showLoading();
  143 + }
  144 +
  145 + @Override
  146 + public void hideLoading() {
  147 + AppBaseActivity baseActivity = getBaseActivity();
  148 + if (baseActivity != null && baseActivity.isActive())
  149 + baseActivity.hideLoading();
  150 + }
  151 +
  152 + @Override
  153 + public void showMessage(String message) {
  154 + if (getBaseActivity() != null) {
  155 + getBaseActivity().showMessage(message);
  156 + }
  157 + }
  158 +
  159 + public void showMessage(@StringRes int res) {
  160 + showMessage(ResUtil.get().getString(res));
  161 + }
  162 +
  163 + @Override
  164 + public boolean isActive() {
  165 + return this.isAdded();
  166 + }
  167 +
  168 + protected void showFragmentEmpty() {
  169 + mRootView.showEmpty();
  170 + }
  171 +
  172 + protected void showFragmentError() {
  173 + mRootView.showError();
  174 + }
  175 +
  176 + protected void showFragmentNoNetwork() {
  177 + mRootView.showNoNetwork();
  178 + }
  179 +
  180 + protected void showFragmentLoading() {
  181 + mRootView.showLoading();
  182 + }
  183 +
  184 + protected void showFragmentContent() {
  185 + mRootView.showContent();
  186 + }
  187 +
  188 + /**
  189 + * 状态不为正常内容处理点击需要重写的方法
  190 + */
  191 + protected void retry() {
  192 + }
  193 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +
  4 +import android.os.Environment;
  5 +
  6 +import java.io.File;
  7 +
  8 +/**
  9 + * @author 蒋洪波
  10 + * @version 1.0
  11 + * @file AppConfig.java
  12 + * @brief 配置应用关键参数
  13 + * @date 2017/10/17
  14 + * Copyright (c) 2017
  15 + * All rights reserved.
  16 + */
  17 +public class AppConfig {
  18 +
  19 + //应用编码方式
  20 + public static final String ENCODING = "utf-8";
  21 + //本地数据库名称
  22 + public static final String DATABASE_NAME = "database";
  23 +
  24 + //! 设备类型 1.IPHONE 2.IPAD 3.ANDROID
  25 + public static final String IPHONE = "1";
  26 + public static final String IPAD = "2";
  27 + public static final String ANDROID = "3";
  28 + public static final String ANDROID_UPGRADE = "2";
  29 + //! 屏幕类型 1 小屏 2 大屏
  30 + public static final String HD = "1";
  31 + public static final String FULLHD = "2";
  32 + //! APP_KEY
  33 + public static final String APP_KEY = "123456";
  34 + //! APPSecret
  35 + public static final String APP_SECRET = "1dfa5cd879df472484138b41dbb6197e";
  36 +
  37 +
  38 + //SD卡 统一文件夹名称
  39 + public static final String SHOPIN_DIR = "shopin";
  40 + //本地文件夹位置
  41 + public static final File LOCAL_FILE_DIR = new File(Environment.getExternalStorageDirectory(), SHOPIN_DIR);
  42 +
  43 + //辨识系统常量,在某些页面需要针对
  44 + public static final CharSequence SAMSUNG_BRAND = "samsung";
  45 + public static final CharSequence K_TOUCH_BRAND = "K-Touch";
  46 + public static final CharSequence HUAWEI = "huawei";
  47 + public static final CharSequence HONOR = "honor";
  48 + //不适配机型集合
  49 + public static final CharSequence[] INCOMPATIBILITY_PHONE = {SAMSUNG_BRAND, K_TOUCH_BRAND, HUAWEI, HONOR};
  50 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import android.app.ActivityManager;
  4 +import android.app.Application;
  5 +import android.content.Context;
  6 +import android.content.Intent;
  7 +import android.os.Message;
  8 +
  9 +import java.util.Iterator;
  10 +import java.util.LinkedList;
  11 +import java.util.List;
  12 +
  13 +import javax.inject.Inject;
  14 +import javax.inject.Singleton;
  15 +
  16 +
  17 +/**
  18 + * 用于管理所有activity,和在前台的 activity
  19 + * 可以通过直接持有AppManager对象执行对应方法
  20 + * 也可以通过eventbus post事件,远程遥控执行对应方法
  21 + * Created by jess on 14/12/2017 13:50
  22 + * Contact with jess.yan.effort@gmail.com
  23 + */
  24 +@Singleton
  25 +public class AppManager {
  26 + protected final String TAG = this.getClass().getSimpleName();
  27 + public static final String APPMANAGER_MESSAGE = "appmanager_message";
  28 + public static final int START_ACTIVITY = 0;
  29 + public static final int SHOW_SNACKBAR = 1;
  30 + public static final int KILL_ALL = 2;
  31 + public static final int APP_EXIT = 3;
  32 + private Application mApplication;
  33 +
  34 + //管理所有activity
  35 + public List<BaseActivity> mActivityList;
  36 + //当前在前台的activity
  37 + private BaseActivity mCurrentActivity;
  38 +
  39 + @Inject
  40 + public AppManager(Application application) {
  41 + this.mApplication = application;
  42 + }
  43 +
  44 +
  45 + private void dispatchStart(Message message) {
  46 + if (message.obj instanceof Intent)
  47 + startActivity((Intent) message.obj);
  48 + else if (message.obj instanceof Class)
  49 + startActivity((Class) message.obj);
  50 + return;
  51 + }
  52 +
  53 +
  54 + /**
  55 + * 使用snackbar显示内容
  56 + *
  57 + * @param message
  58 + * @param isLong
  59 + */
  60 + public void showSnackbar(String message, boolean isLong) {
  61 +// if (getCurrentActivity() == null) {
  62 +// return;
  63 +// }
  64 +// View view = getCurrentActivity().getWindow().getDecorView().findViewById(android.R.id.content);
  65 +// Snackbar.make(view, message, isLong ? Snackbar.LENGTH_LONG : Snackbar.LENGTH_SHORT).show();
  66 + }
  67 +
  68 +
  69 + /**
  70 + * 让在前台的activity,打开下一个activity
  71 + *
  72 + * @param intent
  73 + */
  74 + public void startActivity(Intent intent) {
  75 + if (getCurrentActivity() == null) {
  76 + //如果没有前台的activity就使用new_task模式启动activity
  77 + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  78 + mApplication.startActivity(intent);
  79 + return;
  80 + }
  81 + getCurrentActivity().startActivity(intent);
  82 + }
  83 +
  84 + /**
  85 + * 让在前台的activity,打开下一个activity
  86 + *
  87 + * @param activityClass
  88 + */
  89 + public void startActivity(Class activityClass) {
  90 + startActivity(new Intent(mApplication, activityClass));
  91 + }
  92 +
  93 + /**
  94 + * 释放资源
  95 + */
  96 + public void release() {
  97 + mActivityList.clear();
  98 + mActivityList = null;
  99 + mCurrentActivity = null;
  100 + mApplication = null;
  101 + }
  102 +
  103 + /**
  104 + * 将在前台的activity保存
  105 + *
  106 + * @param currentActivity
  107 + */
  108 + public void setCurrentActivity(BaseActivity currentActivity) {
  109 + this.mCurrentActivity = currentActivity;
  110 + }
  111 +
  112 + /**
  113 + * 获得当前在前台的activity
  114 + *
  115 + * @return
  116 + */
  117 + public BaseActivity getCurrentActivity() {
  118 + return mCurrentActivity;
  119 + }
  120 +
  121 + /**
  122 + * 返回一个存储所有未销毁的activity的集合
  123 + *
  124 + * @return
  125 + */
  126 + public List<BaseActivity> getActivityList() {
  127 + if (mActivityList == null) {
  128 + mActivityList = new LinkedList<>();
  129 + }
  130 + return mActivityList;
  131 + }
  132 +
  133 +
  134 + /**
  135 + * 添加Activity到集合
  136 + */
  137 + public void addActivity(BaseActivity activity) {
  138 + if (mActivityList == null) {
  139 + mActivityList = new LinkedList<>();
  140 + }
  141 + synchronized (AppManager.class) {
  142 + if (!mActivityList.contains(activity)) {
  143 + mActivityList.add(activity);
  144 + }
  145 + }
  146 + }
  147 +
  148 + /**
  149 + * 删除集合里的指定activity
  150 + *
  151 + * @param activity
  152 + */
  153 + public void removeActivity(BaseActivity activity) {
  154 + if (mActivityList == null) {
  155 + return;
  156 + }
  157 + synchronized (AppManager.class) {
  158 + if (mActivityList.contains(activity)) {
  159 + mActivityList.remove(activity);
  160 + }
  161 + }
  162 + }
  163 +
  164 + /**
  165 + * 删除集合里的指定位置的activity
  166 + *
  167 + * @param location
  168 + */
  169 + public BaseActivity removeActivity(int location) {
  170 + if (mActivityList == null) {
  171 + return null;
  172 + }
  173 + synchronized (AppManager.class) {
  174 + if (location > 0 && location < mActivityList.size()) {
  175 + return mActivityList.remove(location);
  176 + }
  177 + }
  178 + return null;
  179 + }
  180 +
  181 + /**
  182 + * 关闭指定activity
  183 + *
  184 + * @param activityClass
  185 + */
  186 + public void killActivity(Class<?> activityClass) {
  187 + if (mActivityList == null) {
  188 + return;
  189 + }
  190 + for (BaseActivity activity : mActivityList) {
  191 + if (activity.getClass().equals(activityClass)) {
  192 + activity.finish();
  193 + }
  194 + }
  195 + }
  196 +
  197 +
  198 + /**
  199 + * 指定的activity实例是否存活
  200 + *
  201 + * @param activity
  202 + * @return
  203 + */
  204 + public boolean activityInstanceIsLive(BaseActivity activity) {
  205 + if (mActivityList == null) {
  206 + return false;
  207 + }
  208 + return mActivityList.contains(activity);
  209 + }
  210 +
  211 +
  212 + /**
  213 + * 指定的activity class是否存活(一个activity可能有多个实例)
  214 + *
  215 + * @param activityClass
  216 + * @return
  217 + */
  218 + public boolean activityClassIsLive(Class<?> activityClass) {
  219 + if (mActivityList == null) {
  220 + return false;
  221 + }
  222 + for (BaseActivity activity : mActivityList) {
  223 + if (activity.getClass().equals(activityClass)) {
  224 + return true;
  225 + }
  226 + }
  227 +
  228 + return false;
  229 + }
  230 +
  231 +
  232 + /**
  233 + * 关闭所有activity
  234 + */
  235 + public void killAll() {
  236 +// while (getActivityList().size() != 0) { //此方法只能兼容LinkedList
  237 +// getActivityList().remove(0).finish();
  238 +// }
  239 +
  240 + Iterator<BaseActivity> iterator = getActivityList().iterator();
  241 + while (iterator.hasNext()) {
  242 + iterator.next().finish();
  243 + iterator.remove();
  244 + }
  245 +
  246 + }
  247 +
  248 +
  249 + /**
  250 + * 退出应用程序
  251 + */
  252 + public void AppExit() {
  253 + try {
  254 + killAll();
  255 + if (mActivityList != null)
  256 + mActivityList = null;
  257 + ActivityManager activityMgr =
  258 + (ActivityManager) mApplication.getSystemService(Context.ACTIVITY_SERVICE);
  259 + activityMgr.killBackgroundProcesses(mApplication.getPackageName());
  260 + System.exit(0);
  261 + } catch (Exception e) {
  262 + e.printStackTrace();
  263 + }
  264 + }
  265 +
  266 +
  267 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import android.content.Context;
  4 +import android.content.Intent;
  5 +import android.os.Bundle;
  6 +import android.os.IBinder;
  7 +import android.support.annotation.CallSuper;
  8 +import android.support.annotation.CheckResult;
  9 +import android.support.annotation.NonNull;
  10 +import android.view.MotionEvent;
  11 +import android.view.View;
  12 +import android.view.inputmethod.InputMethodManager;
  13 +import android.widget.EditText;
  14 +
  15 +import com.trello.rxlifecycle.ActivityEvent;
  16 +import com.trello.rxlifecycle.ActivityLifecycleProvider;
  17 +import com.trello.rxlifecycle.LifecycleTransformer;
  18 +import com.trello.rxlifecycle.RxLifecycle;
  19 +import com.xdy.commonlibrary.permission.PermissifyActivity;
  20 +
  21 +import rx.Observable;
  22 +import rx.subjects.BehaviorSubject;
  23 +
  24 +/**
  25 + * @author jianghongbo
  26 + * @version 1.0
  27 + * @file BaseActivity.java
  28 + * @brief Activity无关业务基类
  29 + * @date 2017/12/25
  30 + * Copyright (c) 2017,上品折扣
  31 + * All rights reserved.
  32 + */
  33 +public abstract class BaseActivity extends PermissifyActivity implements ActivityLifecycleProvider {
  34 +
  35 + private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
  36 + //! 当前Activity的TAG标签
  37 + protected final String TAG = this.getClass().getSimpleName();
  38 +
  39 + /**
  40 + * 为了减少findViewById太冗余,直接在Activity提供该方法
  41 + * @param id
  42 + * @param <T>
  43 + * @return
  44 + */
  45 + public <T extends View> T $(int id) {
  46 + return (T) findViewById(id);
  47 + }
  48 +
  49 + @Override
  50 + @NonNull
  51 + @CheckResult
  52 + public final Observable<ActivityEvent> lifecycle() {
  53 + return lifecycleSubject.asObservable();
  54 + }
  55 +
  56 + @Override
  57 + @NonNull
  58 + @CheckResult
  59 + public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
  60 + return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
  61 + }
  62 +
  63 + @Override
  64 + @NonNull
  65 + @CheckResult
  66 + public final <T> LifecycleTransformer<T> bindToLifecycle() {
  67 + return RxLifecycle.bindActivity(lifecycleSubject);
  68 + }
  69 +
  70 + @Override
  71 + @CallSuper
  72 + protected void onCreate(Bundle savedInstanceState) {
  73 + super.onCreate(savedInstanceState);
  74 + lifecycleSubject.onNext(ActivityEvent.CREATE);
  75 + }
  76 +
  77 + @Override
  78 + @CallSuper
  79 + protected void onStart() {
  80 + super.onStart();
  81 + lifecycleSubject.onNext(ActivityEvent.START);
  82 + }
  83 +
  84 + @Override
  85 + @CallSuper
  86 + protected void onResume() {
  87 + super.onResume();
  88 + lifecycleSubject.onNext(ActivityEvent.RESUME);
  89 + }
  90 +
  91 + @Override
  92 + @CallSuper
  93 + protected void onPause() {
  94 + lifecycleSubject.onNext(ActivityEvent.PAUSE);
  95 + super.onPause();
  96 + }
  97 +
  98 + @Override
  99 + @CallSuper
  100 + protected void onStop() {
  101 + lifecycleSubject.onNext(ActivityEvent.STOP);
  102 + super.onStop();
  103 + }
  104 +
  105 + @Override
  106 + @CallSuper
  107 + protected void onDestroy() {
  108 + lifecycleSubject.onNext(ActivityEvent.DESTROY);
  109 + super.onDestroy();
  110 + }
  111 +
  112 + /**
  113 + * 封装获取意图参数
  114 + */
  115 + protected void getIntentParams() {
  116 + Intent intent = getIntent();
  117 + initIntentParams(intent);
  118 + }
  119 +
  120 + /**
  121 + * 初始化意图参数
  122 + * @param intent
  123 + */
  124 + protected abstract void initIntentParams(Intent intent);
  125 +
  126 + /**
  127 + * 初始化控件方法,需实现
  128 + * @param savedInstanceState
  129 + */
  130 + protected abstract void initViews(Bundle savedInstanceState);
  131 +
  132 + /**
  133 + * 初始化数据方法
  134 + */
  135 + protected abstract void initData();
  136 +
  137 +
  138 + // 空白处隐藏软键盘--开始--------------------------------
  139 + @Override
  140 + public boolean dispatchTouchEvent(MotionEvent ev) {
  141 + if (ev.getAction() == MotionEvent.ACTION_UP) {
  142 + // 获得当前得到焦点的View,一般情况下就是EditText(特殊情况就是轨迹求或者实体案件会移动焦点)
  143 + View v = getCurrentFocus();
  144 +
  145 + if (isShouldHideInput(v, ev)) {
  146 + hideAndLostFocus(v);
  147 + }
  148 + }
  149 + return super.dispatchTouchEvent(ev);
  150 + }
  151 +
  152 + public void hideAndLostFocus(View v) {
  153 + hideSoftInput(v.getWindowToken());
  154 + //使EditText失去焦点
  155 + View parent = (View) v.getParent();
  156 + if (parent != null) {
  157 + parent.setFocusable(true);
  158 + parent.setFocusableInTouchMode(true);
  159 + //请求焦点前一定要先设置上面两个方法
  160 + parent.requestFocus();
  161 + parent.requestFocusFromTouch();
  162 + }
  163 + }
  164 +
  165 + /**
  166 + * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时没必要隐藏
  167 + * @param v
  168 + * @param event
  169 + * @return
  170 + */
  171 + private boolean isShouldHideInput(View v, MotionEvent event) {
  172 + if (v != null && (v instanceof EditText)) {
  173 + int[] l = {0, 0};
  174 + v.getLocationInWindow(l);
  175 + int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left
  176 + + v.getWidth();
  177 + return !(event.getX() > left && event.getX() < right
  178 + && event.getY() > top && event.getY() < bottom);
  179 + }
  180 + // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditView上,和用户用轨迹球选择其他的焦点
  181 + return false;
  182 + }
  183 +
  184 + /**
  185 + * 多种隐藏软件盘方法的其中一种
  186 + * @param token
  187 + */
  188 + public void hideSoftInput(IBinder token) {
  189 + if (token != null) {
  190 + InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
  191 + im.hideSoftInputFromWindow(token,
  192 + InputMethodManager.HIDE_NOT_ALWAYS);
  193 + }
  194 + }
  195 + // 空白处隐藏软键盘--结束--------------------------------
  196 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import com.tencent.tinker.loader.app.TinkerApplication;
  4 +import com.tencent.tinker.loader.shareutil.ShareConstants;
  5 +
  6 +/**
  7 + * @author jianghongbo
  8 + * @version 1.0
  9 + * @file BaseApplication.java
  10 + * @brief 请勿修改此类!
  11 + * @date 2017/3/16
  12 + * Copyright (c) 2017, 上品折扣
  13 + * All rights reserved.
  14 + */
  15 +public class BaseApplication extends TinkerApplication {
  16 +
  17 + /**
  18 + * 这个方法只提供给组件APPLICATION继承使用,其他人勿用
  19 + */
  20 + public BaseApplication() {
  21 + super(
  22 + //tinkerFlags, tinker支持的类型,dex,library,还是全部都支持!
  23 + ShareConstants.TINKER_ENABLE_ALL,
  24 + //ApplicationLike的实现类,只能传递字符串,不能使用class.getName()
  25 + "com.xdy.commonlibrary.core.CommonAppLike",
  26 + //加载Tinker的主类名,对于特殊需求可能需要使用自己的加载类。需要注意的是:
  27 + //这个类以及它使用的类都是不能被补丁修改的,并且我们需要将它们加到dex.loader[]中。
  28 + //一般来说,我们使用默认即可。
  29 + "com.tencent.tinker.loader.TinkerLoader",
  30 + //由于合成过程中我们已经校验了各个文件的Md5,并将它们存放在/data/data/..目录中。
  31 + // 默认每次加载时我们并不会去校验tinker文件的Md5,但是你也可通过开启loadVerifyFlag强制每次加载时校验,
  32 + // 但是这会带来一定的时间损耗。
  33 + false);
  34 + }
  35 +
  36 + public BaseApplication(int tinkerFlags, String delegateClassName, String loaderClassName, boolean tinkerLoadVerifyFlag) {
  37 + super(tinkerFlags, delegateClassName, loaderClassName, tinkerLoadVerifyFlag);
  38 + }
  39 +
  40 + @Override
  41 + public void onCreate() {
  42 + super.onCreate();
  43 + }
  44 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import android.os.Bundle;
  4 +import android.support.annotation.CheckResult;
  5 +import android.support.annotation.NonNull;
  6 +import android.support.annotation.Nullable;
  7 +import android.view.View;
  8 +
  9 +import com.trello.rxlifecycle.FragmentEvent;
  10 +import com.trello.rxlifecycle.FragmentLifecycleProvider;
  11 +import com.trello.rxlifecycle.LifecycleTransformer;
  12 +import com.trello.rxlifecycle.RxLifecycle;
  13 +
  14 +import me.yokeyword.fragmentation.SupportFragment;
  15 +import rx.Observable;
  16 +import rx.subjects.BehaviorSubject;
  17 +
  18 +/**
  19 + * @author jianghongbo
  20 + * @version 1.0
  21 + * @file BaseFragment.java
  22 + * @brief 无关业务的Fragment基类
  23 + * @date 2017/6/4
  24 + * Copyright (c) 2017, 上品折扣[]
  25 + * All rights reserved.
  26 + */
  27 +public abstract class BaseFragment extends SupportFragment implements FragmentLifecycleProvider {
  28 +
  29 + //! 当前Fragment的TAG标签
  30 + protected String TAG= this.getClass().getSimpleName();
  31 +
  32 + @Override
  33 + public void onLazyInitView(@Nullable Bundle savedInstanceState) {
  34 + super.onLazyInitView(savedInstanceState);
  35 + }
  36 +
  37 +
  38 + private final BehaviorSubject<FragmentEvent> lifecycleSubject = BehaviorSubject.create();
  39 +
  40 + @Override
  41 + @NonNull
  42 + @CheckResult
  43 + public final Observable<FragmentEvent> lifecycle() {
  44 + return lifecycleSubject.asObservable();
  45 + }
  46 +
  47 + @Override
  48 + @NonNull
  49 + @CheckResult
  50 + public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull FragmentEvent event) {
  51 + return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
  52 + }
  53 +
  54 + @Override
  55 + @NonNull
  56 + @CheckResult
  57 + public final <T> LifecycleTransformer<T> bindToLifecycle() {
  58 + return RxLifecycle.bindFragment(lifecycleSubject);
  59 + }
  60 +
  61 + @Override
  62 + public void onAttach(android.app.Activity activity) {
  63 + super.onAttach(activity);
  64 + lifecycleSubject.onNext(FragmentEvent.ATTACH);
  65 + }
  66 +
  67 + @Override
  68 + public void onCreate(Bundle savedInstanceState) {
  69 + super.onCreate(savedInstanceState);
  70 + lifecycleSubject.onNext(FragmentEvent.CREATE);
  71 + }
  72 +
  73 + @Override
  74 + public void onViewCreated(View view, Bundle savedInstanceState) {
  75 + super.onViewCreated(view, savedInstanceState);
  76 + lifecycleSubject.onNext(FragmentEvent.CREATE_VIEW);
  77 + }
  78 +
  79 + @Override
  80 + public void onStart() {
  81 + super.onStart();
  82 + lifecycleSubject.onNext(FragmentEvent.START);
  83 + }
  84 +
  85 + @Override
  86 + public void onResume() {
  87 + super.onResume();
  88 + lifecycleSubject.onNext(FragmentEvent.RESUME);
  89 + }
  90 +
  91 + @Override
  92 + public void onPause() {
  93 + lifecycleSubject.onNext(FragmentEvent.PAUSE);
  94 + super.onPause();
  95 + }
  96 +
  97 + @Override
  98 + public void onStop() {
  99 + lifecycleSubject.onNext(FragmentEvent.STOP);
  100 + super.onStop();
  101 + }
  102 +
  103 + @Override
  104 + public void onDestroyView() {
  105 + lifecycleSubject.onNext(FragmentEvent.DESTROY_VIEW);
  106 + super.onDestroyView();
  107 + }
  108 +
  109 + @Override
  110 + public void onDestroy() {
  111 + lifecycleSubject.onNext(FragmentEvent.DESTROY);
  112 + super.onDestroy();
  113 + }
  114 +
  115 + @Override
  116 + public void onDetach() {
  117 + lifecycleSubject.onNext(FragmentEvent.DETACH);
  118 + super.onDetach();
  119 + }
  120 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import java.lang.ref.WeakReference;
  4 +
  5 +/**
  6 + * @author jianghongbo
  7 + * @version 1.0
  8 + * @file BaseRunnable.java
  9 + * @brief runnable简单封装好使用
  10 + * @date 2017/12/25
  11 + * Copyright (c) 2017,上品折扣
  12 + * All rights reserved.
  13 + */
  14 +public abstract class BaseRunnable<T> implements Runnable {
  15 +
  16 + WeakReference<T> weakReference;
  17 +
  18 + public BaseRunnable() {
  19 +
  20 + }
  21 +
  22 + public BaseRunnable(T t) {
  23 + weakReference = new WeakReference<>(t);
  24 + }
  25 +
  26 + @Override
  27 + public void run() {
  28 + T t = null;
  29 + if (weakReference != null && (t = weakReference.get()) != null) {
  30 + handle(t);
  31 + } else {
  32 + handle(null);
  33 + }
  34 + }
  35 +
  36 + protected abstract void handle(T t);
  37 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import android.app.Service;
  4 +import android.content.Intent;
  5 +import android.os.IBinder;
  6 +import android.support.annotation.Nullable;
  7 +
  8 +import rx.Subscription;
  9 +
  10 +/**
  11 + * Created by jess on 16/5/6.
  12 + */
  13 +public abstract class BaseService extends Service {
  14 + protected final String TAG = this.getClass().getSimpleName();
  15 +
  16 + @Nullable
  17 + @Override
  18 + public IBinder onBind(Intent intent) {
  19 + return null;
  20 + }
  21 +
  22 + @Override
  23 + public void onCreate() {
  24 + super.onCreate();
  25 + init();
  26 + }
  27 +
  28 + @Override
  29 + public void onDestroy() {
  30 + super.onDestroy();
  31 + }
  32 +
  33 + public void unSubscribe(Subscription subscription) {
  34 + if (subscription != null && !subscription.isUnsubscribed()) {
  35 + subscription.unsubscribe();//保证service结束时取消所有正在执行的订阅
  36 + }
  37 + }
  38 +
  39 + /**
  40 + * 初始化
  41 + */
  42 + abstract public void init();
  43 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import android.Manifest;
  4 +import android.annotation.TargetApi;
  5 +import android.app.Application;
  6 +import android.content.Context;
  7 +import android.content.Intent;
  8 +import android.os.Build;
  9 +import android.text.TextUtils;
  10 +
  11 +import com.tencent.tinker.loader.app.DefaultApplicationLike;
  12 +import com.xdy.commonlibrary.BuildConfig;
  13 +import com.xdy.commonlibrary.R;
  14 +import com.xdy.commonlibrary.api.Api;
  15 +import com.xdy.commonlibrary.api.interceptor.BasicParamsInterceptor;
  16 +import com.xdy.commonlibrary.core.di.AppComponent;
  17 +import com.xdy.commonlibrary.core.di.AppModule;
  18 +import com.xdy.commonlibrary.core.di.ClientModule;
  19 +import com.xdy.commonlibrary.core.di.DaggerAppComponent;
  20 +import com.xdy.commonlibrary.core.di.DaggerBaseComponent;
  21 +import com.xdy.commonlibrary.core.di.GlobeConfigModule;
  22 +import com.xdy.commonlibrary.core.di.ImageModule;
  23 +import com.xdy.commonlibrary.entity.BaseEntity;
  24 +import com.xdy.commonlibrary.event.CheckUpgradeEvent;
  25 +import com.xdy.commonlibrary.exception.ResultException;
  26 +import com.xdy.commonlibrary.mvp.GlobalDialogActivity;
  27 +import com.xdy.commonlibrary.permission.DialogText;
  28 +import com.xdy.commonlibrary.permission.PermissifyConfig;
  29 +import com.xdy.network.CacheModule;
  30 +import com.xdy.network.ServiceModule;
  31 +import com.xdy.network.http.GlobeHttpHandler;
  32 +import com.xdy.util.AppUtil;
  33 +import com.xdy.util.LogUtil;
  34 +import com.xdy.util.ResUtil;
  35 +import com.xdy.util.ToastUtil;
  36 +import com.zhy.changeskin.SkinManager;
  37 +
  38 +import org.greenrobot.eventbus.EventBus;
  39 +
  40 +import java.io.IOException;
  41 +import java.lang.reflect.Field;
  42 +import java.lang.reflect.Method;
  43 +import java.net.URLDecoder;
  44 +import java.util.HashMap;
  45 +
  46 +import javax.inject.Inject;
  47 +
  48 +import me.jessyan.rxerrorhandler.handler.listener.ResponseErroListener;
  49 +import okhttp3.Interceptor;
  50 +import okhttp3.Request;
  51 +import okhttp3.RequestBody;
  52 +import okhttp3.Response;
  53 +import okio.Buffer;
  54 +
  55 +
  56 +/**
  57 + * @author jianghongbo
  58 + * @version 1.0
  59 + * @file AppLike.java
  60 + * @brief 不要在这里初始化组件里的任何东西
  61 + * @date 2017/12/16
  62 + * Copyright (c) 2017
  63 + * All rights reserved.
  64 + */
  65 +public class CommonAppLike extends DefaultApplicationLike {
  66 +
  67 + private static Boolean isDebug;
  68 + private static CommonAppLike appLike;
  69 +
  70 + //单位,小时
  71 + private int tinkerUpdateInterval = 3;
  72 + private String versionName;
  73 +
  74 + public CommonAppLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag,
  75 + long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
  76 + super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
  77 + appLike = this;
  78 + }
  79 +
  80 + /**
  81 + * install multiDex before install tinker
  82 + * so we don't need to put the tinker lib classes in the main dex
  83 + */
  84 + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
  85 + @Override
  86 + public void onBaseContextAttached(Context base) {
  87 + super.onBaseContextAttached(base);
  88 + }
  89 +
  90 + @Override
  91 + public void onCreate() {
  92 + super.onCreate();
  93 + CrashHandler.getInstance().init();
  94 + ResUtil.init(getApplication());
  95 + LogUtil.init(isDebug());
  96 + initPermission();
  97 + initDagger();
  98 + initSkin();
  99 + }
  100 +
  101 + private void initSkin() {
  102 + SkinManager.getInstance().init(getApplication());
  103 + }
  104 +
  105 + private void initPermission() {
  106 + PermissifyConfig permissifyConfig = new PermissifyConfig.Builder()
  107 + .withDefaultTextForPermissions(new HashMap<String, DialogText>() {{
  108 + put(Manifest.permission_group.STORAGE, new DialogText(R.string.storage_rational, R.string.storage_deny_dialog));
  109 + put(Manifest.permission_group.CONTACTS, new DialogText(R.string.contact_rational, R.string.contact_deny_dialog));
  110 + put(Manifest.permission_group.PHONE, new DialogText(R.string.phone_rational, R.string.phone_deny_dialog));
  111 + put(Manifest.permission_group.SMS, new DialogText(R.string.sms_rational, R.string.sms_deny_dialog));
  112 + put(Manifest.permission_group.CAMERA, new DialogText(R.string.camera_rational, R.string.camera_deny_dialog));
  113 + put(Manifest.permission_group.LOCATION, new DialogText(R.string.location_rational, R.string.location_deny_dialog));
  114 + }})
  115 + .build();
  116 +
  117 + PermissifyConfig.initDefault(permissifyConfig);
  118 + }
  119 +
  120 + private void initDagger() {
  121 + //这块本应该放入到commonLib中,但是Tinker必须继承他的Application
  122 + this.mAppModule = new AppModule(getApplication());//提供application
  123 + DaggerBaseComponent
  124 + .builder()
  125 + .appModule(mAppModule)
  126 + .build()
  127 + .inject(this);
  128 + this.mImagerModule = new ImageModule();//图片加载框架默认使用glide
  129 + this.mClientModule = new ClientModule(mAppManager);//用于提供okhttp和retrofit的单例
  130 + this.mGlobeConfigModule = createGlobeConfigModule();
  131 +
  132 + mAppComponent = DaggerAppComponent
  133 + .builder()
  134 + .appModule(getAppModule())//baseApplication提供
  135 + .clientModule(getClientModule())//baseApplication提供
  136 + .imageModule(getImageModule())//baseApplication提供
  137 + .globeConfigModule(mGlobeConfigModule)//Retrofit的全局配置,为clientModule提供Retrofit
  138 + .serviceModule(new ServiceModule())//需自行创建,可以创建对应的ServiceManager
  139 + .cacheModule(new CacheModule())//需自行创建
  140 + .build();
  141 + }
  142 +
  143 + @Override
  144 + public void onTerminate() {
  145 + super.onTerminate();
  146 + if (mAppComponent != null)
  147 + this.mAppComponent = null;
  148 + if (mClientModule != null)
  149 + this.mClientModule = null;
  150 + if (mAppModule != null)
  151 + this.mAppModule = null;
  152 + if (mImagerModule != null)
  153 + this.mImagerModule = null;
  154 + if (mAppManager != null) {//释放资源
  155 + this.mAppManager.release();
  156 + this.mAppManager = null;
  157 + }
  158 + if (appLike != null)
  159 + this.appLike = null;
  160 + }
  161 +
  162 + private ClientModule mClientModule;
  163 + private AppModule mAppModule;
  164 + private ImageModule mImagerModule;
  165 + private GlobeConfigModule mGlobeConfigModule;
  166 + @Inject
  167 + protected AppManager mAppManager;
  168 +
  169 + private static AppComponent mAppComponent;
  170 +
  171 + /**
  172 + * 将app的全局配置信息封装进module(使用Dagger注入到需要配置信息的地方)
  173 + * @return
  174 + */
  175 + private GlobeConfigModule createGlobeConfigModule() {
  176 + return GlobeConfigModule
  177 + .buidler()
  178 + .baseurl(Api.APP_HOST)
  179 + .globeHttpHandler(new GlobeHttpHandler() {// 这里可以提供一个全局处理http响应结果的处理类,
  180 + // 这里可以比客户端提前一步拿到服务器返回的结果,可以做一些操作,比如token超时,重新获取
  181 + @Override
  182 + public Response onHttpResultResponse(String httpResult, Interceptor.Chain chain, Response response) {
  183 + //这里可以先客户端一步拿到每一次http请求的结果,可以解析成json,做一些操作,如检测到token过期后
  184 + //重新请求token,并重新执行请求
  185 +// try {
  186 +// } catch (JSONException e) {
  187 +// e.printStackTrace();
  188 +// return response;
  189 +// }
  190 +
  191 +
  192 + //这里如果发现token过期,可以先请求最新的token,然后在拿新的token放入request里去重新请求
  193 + //注意在这个回调之前已经调用过proceed,所以这里必须自己去建立网络请求,如使用okhttp使用新的request去请求
  194 + // create a new request and modify it accordingly using the new token
  195 +// Request newRequest = chain.request().newBuilder().header("token", newToken)
  196 +// .build();
  197 +
  198 +// // retry the request
  199 +//
  200 +// response.body().close();
  201 + //如果使用okhttp将新的请求,请求成功后,将返回的response return出去即可
  202 +
  203 + //如果不需要返回新的结果,则直接把response参数返回出去
  204 + return response;
  205 + }
  206 +
  207 + // 这里可以在请求服务器之前可以拿到request,做一些操作比如给request统一添加token或者header
  208 + @Override
  209 + public Request onHttpRequestBefore(Interceptor.Chain chain, Request request) {
  210 + //如果需要再请求服务器之前做一些操作,则重新返回一个新的requeat如增加header,不做操作则返回request
  211 +// RequestBody body = request.body();
  212 +// Request.Builder requestBuilder = request.newBuilder();
  213 +// if (body != null && body.contentType() != null) {
  214 +// HttpUrl.Builder urlBuilder = null;
  215 +// //Application/json类型
  216 +// if (body.contentType().toString().contains("json")) {
  217 +// urlBuilder = postJson(request);
  218 +// requestBuilder
  219 +// .url(urlBuilder.build());//使用新拼接的url
  220 +// }
  221 +// }
  222 +
  223 + return request;
  224 + }
  225 + })
  226 + //此公共参数是表单提交时候使用,普通使用ShopinRequestBody封装POST参数,但是get请求暂时没有添加公参
  227 + .addInterceptor(createCommonParamIntercept())
  228 +// .addInterceptor(new OkHttpMockInterceptor(getContext(), 1))
  229 + .responseErroListener(new ResponseErroListener() {
  230 + // 用来提供处理所有错误的监听
  231 + // rxjava必要要使用ErrorHandleSubscriber(默认实现Subscriber的onError方法),此监听才生效
  232 + @Override
  233 + public void handleResponseError(Context context, Exception e) {
  234 + //所有异常在这里处理
  235 + if (e instanceof ResultException) {
  236 + String resultCode = ((ResultException) e).getResultCode();
  237 + String message = e.getMessage();
  238 + if (!TextUtils.isEmpty(message)) {
  239 + ToastUtil.showToast(getApplication(), message);
  240 + }
  241 + LogUtil.e("code:" + resultCode + "msg:" + message);
  242 +
  243 + if (TextUtils.equals(resultCode, BaseEntity.LACK_PARAMS)) {
  244 + //缺少必要参数
  245 + LogUtil.i(ResUtil.get().getString(R.string.lack_params));
  246 + } else if (TextUtils.equals(BaseEntity.INVALID_TOKENID, resultCode)) {
  247 + //不合法的TOKEN
  248 + Intent intent = new Intent(getContext(), GlobalDialogActivity.class);
  249 + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  250 + intent.putExtra(GlobalDialogActivity.INTENT, GlobalDialogActivity.INVALIDATE_TOKEN);
  251 + if (!TextUtils.isEmpty(message)) {
  252 + intent.putExtra(BaseEntity.ERROR_MESSAGE, message);
  253 + }
  254 + getContext().startActivity(intent);
  255 + } else if (TextUtils.equals(BaseEntity.FORCE_UPGRADE, resultCode)) {
  256 + //强制更新 发一个EventBus通知主页和登陆页面,保证有一方会接收到通知。
  257 + EventBus.getDefault().post(new CheckUpgradeEvent());
  258 + } else if (TextUtils.equals(BaseEntity.FIX_TIME, resultCode)) {
  259 + //客制化
  260 + Intent intent = new Intent(getContext(), GlobalDialogActivity.class);
  261 + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  262 + intent.putExtra(GlobalDialogActivity.INTENT, GlobalDialogActivity.CUSTOM);
  263 + if (!TextUtils.isEmpty(message)) {
  264 + intent.putExtra(GlobalDialogActivity.CONTENT, message);
  265 + }
  266 + getContext().startActivity(intent);
  267 + }
  268 + } else {
  269 + LogUtil.e(e.getMessage());
  270 + }
  271 + }
  272 + }).build();
  273 + }
  274 +
  275 + public static AppComponent getAppComponent() {
  276 + return mAppComponent;
  277 + }
  278 +
  279 + public Interceptor createCommonParamIntercept() {
  280 + boolean readPhonePermission = false;
  281 +// if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_PHONE_STATE)
  282 +// == PackageManager.PERMISSION_GRANTED) {
  283 +// readPhonePermission = true;
  284 +// }
  285 + BasicParamsInterceptor interceptor = new BasicParamsInterceptor
  286 + .Builder()
  287 + .addParam("deviceType", "1")
  288 + .addParam("deviceSn", readPhonePermission ? AppUtil.getDeviceId(CommonAppLike.getContext()) : "")
  289 + .addParam("appVersion", AppUtil.getVersionName(getContext()))
  290 + .addParam("systemVersion", AppUtil.getOSVersion())
  291 + .addParam("versionNo", String.valueOf(AppUtil.getVersionCode(getContext())))
  292 + .addQueryParam("deviceType", "1")
  293 + .addQueryParam("deviceSn", readPhonePermission ? AppUtil.getDeviceId(CommonAppLike.getContext()) : "")
  294 + .addQueryParam("appVersion", AppUtil.getVersionName(getContext()))
  295 + .addQueryParam("systemVersion", AppUtil.getOSVersion())
  296 + .addQueryParam("versionNo", String.valueOf(AppUtil.getVersionCode(getContext())))
  297 + .build();
  298 + return interceptor;
  299 + }
  300 +
  301 +
  302 + private String bodyToString(RequestBody body) {
  303 + String postBodyString = null;
  304 + if (body != null) {
  305 + try {
  306 + Buffer requestbuffer = new Buffer();
  307 + body.writeTo(requestbuffer);
  308 + if (body.contentType() != null && !body.contentType().toString().contains("multipart")) {
  309 + postBodyString = URLDecoder.decode(requestbuffer.readUtf8(), "UTF-8");
  310 + }
  311 + } catch (IOException e) {
  312 + e.printStackTrace();
  313 + }
  314 + }
  315 + return postBodyString;
  316 + }
  317 +
  318 +
  319 + public ClientModule getClientModule() {
  320 + return mClientModule;
  321 + }
  322 +
  323 + public AppModule getAppModule() {
  324 + return mAppModule;
  325 + }
  326 +
  327 + public ImageModule getImageModule() {
  328 + return mImagerModule;
  329 + }
  330 +
  331 +
  332 + public AppManager getAppManager() {
  333 + return mAppManager;
  334 + }
  335 +
  336 + public GlobeConfigModule getGlobeConfigModule() {
  337 + return mGlobeConfigModule;
  338 + }
  339 +
  340 + /**
  341 + * 返回上下文
  342 + * @return
  343 + */
  344 + public static Context getContext() {
  345 + return appLike.getApplication();
  346 + }
  347 +
  348 + public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback) {
  349 + getApplication().registerActivityLifecycleCallbacks(callback);
  350 + }
  351 +
  352 +
  353 + public static CommonAppLike getInstance() {
  354 + return appLike;
  355 + }
  356 +
  357 + public static boolean isDebug() {
  358 + if (isDebug == null) {
  359 + try {
  360 + final Class<?> activityThread = Class.forName("android.app.ActivityThread");
  361 + final Method currentPackage = activityThread.getMethod("currentPackageName");
  362 + final String packageName = (String) currentPackage.invoke(null, (Object[]) null);
  363 + final Class<?> buildConfig = Class.forName(packageName + ".BuildConfig");
  364 + final Field DEBUG = buildConfig.getField("DEBUG");
  365 + DEBUG.setAccessible(true);
  366 + isDebug = DEBUG.getBoolean(null);
  367 + } catch (final Throwable t) {
  368 + final String message = t.getMessage();
  369 + if (message != null && message.contains("BuildConfig")) {
  370 + // Proguard obfuscated build. Most likely a production build.
  371 + isDebug = false;
  372 + } else {
  373 + isDebug = BuildConfig.DEBUG;
  374 + }
  375 + }
  376 + }
  377 + return isDebug;
  378 + }
  379 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +
  4 +import com.xdy.util.AppUtil;
  5 +import com.xdy.util.LogUtil;
  6 +
  7 +import java.io.ByteArrayOutputStream;
  8 +import java.io.IOException;
  9 +import java.io.PrintStream;
  10 +
  11 +/**
  12 + * UncaughtExceptionHandler:线程未捕获异常控制器是用来处理未捕获异常的。 如果程序出现了未捕获异常默认情况下则会出现强行关闭对话框
  13 + * 实现该接口并注册为程序中的默认未捕获异常处理 这样当未捕获异常发生时,就可以做些异常处理操作 例如:收集异常信息,发送错误报告 等。
  14 + * <p/>
  15 + * UncaughtException处理类,当程序发生Uncaught异常的时候,由该类来接管程序,并记录发送错误报告.
  16 + */
  17 +public class CrashHandler extends AbsCrashHandler {
  18 +
  19 + public static final String TAG = "CrashHandler";
  20 + private static CrashHandler INSTANCE;
  21 +
  22 + private CrashHandler() {
  23 + }
  24 +
  25 + public static CrashHandler getInstance() {
  26 + if (CrashHandler.INSTANCE == null) {
  27 + CrashHandler.INSTANCE = new CrashHandler();
  28 + }
  29 + return CrashHandler.INSTANCE;
  30 + }
  31 +
  32 + @Override
  33 + public void saveCrash(Throwable throwable) {
  34 +// String date = DateUtils.getTimeWithSec();
  35 +// DbManager instance = DbManager.getInstance(AppLike.getInstance().getApplication());
  36 +// CrashExceptionEntity entity = new CrashExceptionEntity();
  37 +// entity.setIphoneModel(AppUtil.getMaker());
  38 +// entity.setOccurDate(date);
  39 +// entity.setUploadFlag(false);
  40 +// String title = throwable.toString();
  41 +// if (title.length() > 70) {
  42 +// title = title.substring(0, 70);
  43 +// }
  44 +// entity.setModel(title);
  45 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
  46 + try {
  47 + throwable.printStackTrace(new PrintStream(baos));
  48 + String errorMessage = baos.toString();
  49 +// entity.setMd5Summary(EncryptUtil.MD5Encode(errorMessage, AppConfig.ENCODING));
  50 +// entity.setErrorMsg(errorMessage);
  51 +// instance.insertOrUpdateData(entity);
  52 + LogUtil.e(TAG, errorMessage);
  53 + baos.close();
  54 + } catch (IOException e) {
  55 + e.printStackTrace();
  56 + LogUtil.e(TAG, "insert error ex");
  57 + } finally {
  58 + //杀死我们进程
  59 + AppUtil.shutDownApp();
  60 + }
  61 + }
  62 +}
  1 +package com.xdy.commonlibrary.core;
  2 +
  3 +import android.os.Bundle;
  4 +import android.support.annotation.LayoutRes;
  5 +import android.view.LayoutInflater;
  6 +import android.view.View;
  7 +import android.view.ViewGroup;
  8 +import android.widget.FrameLayout;
  9 +
  10 +import com.xdy.commonlibrary.R;
  11 +import com.xdy.ui.viewgroup.MultipleStatusView;
  12 +import com.xdy.ui.viewgroup.TitleHeaderBar;
  13 +
  14 +import me.yokeyword.fragmentation.SupportFragment;
  15 +
  16 +
  17 +/**
  18 + * @author Administrator
  19 + * @version 1.0
  20 + * @file TitleBaseActivity.java
  21 + * @brief 带头的ACTIVITY
  22 + * @date 2017/6/7
  23 + * Copyright (c) 2017
  24 + * All rights reserved.
  25 + */
  26 +public abstract class TitleBaseActivity<P extends com.xdy.commonlibrary.mvp.BasePresenter> extends com.xdy.commonlibrary.core.AppBaseActivity<P> {
  27 +
  28 + protected TitleHeaderBar mTitleHeaderBar;
  29 + protected FrameLayout mContentContainer;
  30 + MultipleStatusView mBaseMultiple;
  31 + private boolean layoutIsAdded;
  32 +
  33 + @Override
  34 + protected void onCreate(Bundle savedInstanceState) {
  35 + super.onCreate(savedInstanceState);
  36 + }
  37 +
  38 + public com.xdy.ui.viewgroup.TitleHeaderBar getTitleHeaderBar() {
  39 + return (TitleHeaderBar) findViewById(R.id.content_frame_title_header);
  40 + }
  41 +
  42 + protected FrameLayout getContentContainer() {
  43 + return (FrameLayout) findViewById(R.id.content_view);
  44 + }
  45 +
  46 + public com.xdy.ui.viewgroup.MultipleStatusView getMultipleStatusView() {
  47 + return (com.xdy.ui.viewgroup.MultipleStatusView) findViewById(R.id.base_multiplestatusview);
  48 + }
  49 +
  50 + @Override
  51 + protected void initBaseLayout() {
  52 + //用基类布局
  53 + super.setContentView(R.layout.ui_base_activity_with_title_header);
  54 + mTitleHeaderBar = getTitleHeaderBar();
  55 + mContentContainer = getContentContainer();
  56 + mBaseMultiple = getMultipleStatusView();
  57 + if (enableDefaultBack()) {
  58 + mTitleHeaderBar.setLeftOnClickListener(new View.OnClickListener() {
  59 +
  60 + @Override
  61 + public void onClick(View v) {
  62 + onBackPressedSupport();
  63 + }
  64 + });
  65 + } else {
  66 + mTitleHeaderBar.getLeftViewContainer().setVisibility(View.INVISIBLE);
  67 + }
  68 + if (getLayoutId() != 0 && !layoutIsAdded) {
  69 + setContentView(getLayoutId());
  70 + layoutIsAdded = true;
  71 + }
  72 +
  73 + mBaseMultiple.setOnRetryClickListener(new View.OnClickListener() {
  74 + @Override
  75 + public void onClick(View view) {
  76 + switch (mBaseMultiple.getViewStatus()) {
  77 + case com.xdy.ui.viewgroup.MultipleStatusView.STATUS_EMPTY:
  78 + case com.xdy.ui.viewgroup.MultipleStatusView.STATUS_ERROR:
  79 + case com.xdy.ui.viewgroup.MultipleStatusView.STATUS_NO_NETWORK:
  80 + retry();
  81 + break;
  82 + }
  83 + }
  84 + });
  85 + }
  86 +
  87 + protected boolean enableDefaultBack() {
  88 + return true;
  89 + }
  90 +
  91 + @Override
  92 + public void setContentView(@LayoutRes int layoutResID) {
  93 + View view = LayoutInflater.from(this).inflate(layoutResID, null);
  94 + view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
  95 + setContentView(view);
  96 + }
  97 +
  98 + @Override
  99 + public void setContentView(View view) {
  100 + mContentContainer.addView(view);
  101 + }
  102 +
  103 + public void setContentViewSupper(int layoutResID) {
  104 + super.setContentView(layoutResID);
  105 + }
  106 +
  107 + protected void setHeaderTitle(int id) {
  108 + mTitleHeaderBar.getTitleTextView().setText(id);
  109 + }
  110 +
  111 + protected void setHeaderTitle(String title) {
  112 + mTitleHeaderBar.setTitle(title);
  113 + }
  114 +
  115 + /**
  116 + * 加载fragment,具体更多方法参考fragmentation
  117 + * @param toFragment
  118 + */
  119 + public void loadRootFragment(SupportFragment toFragment) {
  120 + SupportFragment fragment = findFragment(toFragment.getClass());
  121 +
  122 + if (fragment == null)
  123 + super.loadRootFragment(getContentContainer().getId(), toFragment);
  124 + }
  125 +
  126 + public void loadMultipleRootFragment(int showPosition, SupportFragment... toFragments) {
  127 + super.loadMultipleRootFragment(getContentContainer().getId(), showPosition, toFragments);
  128 + }
  129 +
  130 + /**
  131 + * 展示空数据Activity
  132 + */
  133 + protected void showActEmpty() {
  134 + mBaseMultiple.showEmpty();
  135 + }
  136 +
  137 + /**
  138 + * 展示错误Activity界面
  139 + */
  140 + protected void showActError() {
  141 + mBaseMultiple.showError();
  142 + }
  143 +
  144 + /**
  145 + * 展示没有网络状态Activity
  146 + */
  147 + protected void showActNoNetwork() {
  148 + mBaseMultiple.showNoNetwork();
  149 + }
  150 +
  151 + /**
  152 + * 展示正常Activity的进度条
  153 + */
  154 + protected void showActLoading() {
  155 + mBaseMultiple.showLoading();
  156 + }
  157 +
  158 + /**
  159 + * 展示正常Activity的内容
  160 + */
  161 + protected void showActContent() {
  162 + mBaseMultiple.showContent();
  163 + }
  164 +
  165 + /**
  166 + * 出现错误的时候重试点击事件
  167 + */
  168 + protected void retry() {
  169 + showMessage("重试");
  170 + }
  171 +
  172 +}
  1 +package com.xdy.commonlibrary.core.di;
  2 +
  3 +import android.app.Application;
  4 +import android.os.Handler;
  5 +
  6 +import com.google.gson.Gson;
  7 +import com.xdy.network.CacheModule;
  8 +import com.xdy.network.ServiceModule;
  9 +import com.xdy.network.cache.CacheManager;
  10 +import com.xdy.network.service.ServiceManager;
  11 +import com.xdy.commonlibrary.core.AppManager;
  12 +import com.xdy.commonlibrary.imageloader.ImageLoader;
  13 +import com.xdy.commonlibrary.utils.cache.ICache;
  14 +
  15 +import javax.inject.Singleton;
  16 +
  17 +import dagger.Component;
  18 +import me.jessyan.rxerrorhandler.core.RxErrorHandler;
  19 +import okhttp3.OkHttpClient;
  20 +import retrofit2.Retrofit;
  21 +
  22 +/**
  23 + * Created by jess on 8/4/16.
  24 + */
  25 +@Singleton
  26 +@Component(modules = {AppModule.class, ClientModule.class, ServiceModule.class, ImageModule.class,
  27 + CacheModule.class, GlobeConfigModule.class})
  28 +public interface AppComponent {
  29 + Application application();
  30 +
  31 + //服务管理器,retrofitApi
  32 + ServiceManager serviceManager();
  33 +
  34 + //Retrofit
  35 + Retrofit retrofitManager();
  36 +
  37 + //缓存管理器
  38 + CacheManager cacheManager();
  39 +
  40 + //Rxjava错误处理管理类
  41 + RxErrorHandler rxErrorHandler();
  42 +
  43 + OkHttpClient okHttpClient();
  44 +
  45 + //图片管理器,用于加载图片的管理类,默认使用glide,使用策略模式,可替换框架
  46 + ImageLoader imageLoader();
  47 +
  48 + //gson
  49 + Gson gson();
  50 +
  51 + //用于管理所有activity
  52 + AppManager appManager();
  53 +
  54 + Handler getHandler();
  55 +
  56 + ICache getCacheUtil();
  57 +}
  1 +package com.xdy.commonlibrary.core.di;
  2 +
  3 +import android.app.Application;
  4 +import android.os.Handler;
  5 +
  6 +import com.google.gson.Gson;
  7 +import com.xdy.commonlibrary.utils.cache.ACache;
  8 +import com.xdy.commonlibrary.utils.cache.ICache;
  9 +
  10 +import javax.inject.Singleton;
  11 +
  12 +import dagger.Module;
  13 +import dagger.Provides;
  14 +
  15 +/**
  16 + * Created by jess on 8/4/16.
  17 + */
  18 +@Module
  19 +public class AppModule {
  20 + private Application mApplication;
  21 + private Handler handler;
  22 +
  23 + public AppModule(Application application) {
  24 + this.mApplication = application;
  25 + this.handler = new Handler();
  26 + }
  27 +
  28 + @Singleton
  29 + @Provides
  30 + public Application provideApplication() {
  31 + return mApplication;
  32 + }
  33 +
  34 + @Singleton
  35 + @Provides
  36 + public Gson provideGson() {
  37 + return new Gson();
  38 + }
  39 +
  40 + @Singleton
  41 + @Provides
  42 + public Handler provideHandler() {
  43 + return handler;
  44 + }
  45 +
  46 + @Singleton
  47 + @Provides
  48 + public ICache provideCache() {
  49 + return ACache.get(mApplication);
  50 + }
  51 +
  52 +}
  1 +package com.xdy.commonlibrary.core.di;
  2 +
  3 +
  4 +import com.xdy.commonlibrary.core.CommonAppLike;
  5 +
  6 +import javax.inject.Singleton;
  7 +
  8 +import dagger.Component;
  9 +
  10 +/**
  11 + * Created by jess on 14/12/2017 13:58
  12 + * Contact with jess.yan.effort@gmail.com
  13 + */
  14 +@Singleton
  15 +@Component(modules={AppModule.class})
  16 +public interface BaseComponent {
  17 + void inject(CommonAppLike application);
  18 +}
  1 +package com.xdy.commonlibrary.core.di;
  2 +
  3 +import android.app.Application;
  4 +
  5 +import com.xdy.network.MyCacheSpeak;
  6 +import com.xdy.network.WrapGsonDeserializerInfo;
  7 +import com.xdy.commonlibrary.api.ShopinGsonConverterFactory;
  8 +import com.xdy.commonlibrary.api.interceptor.RequestIntercept;
  9 +import com.xdy.commonlibrary.core.AppManager;
  10 +import com.xdy.commonlibrary.entity.UserEntity;
  11 +import com.xdy.commonlibrary.entity.UserMayBeEmptyStringDeserializer;
  12 +
  13 +import java.io.File;
  14 +import java.util.ArrayList;
  15 +import java.util.List;
  16 +import java.util.concurrent.TimeUnit;
  17 +
  18 +import javax.inject.Singleton;
  19 +
  20 +import dagger.Module;
  21 +import dagger.Provides;
  22 +import io.rx_cache.internal.RxCache;
  23 +import me.jessyan.rxerrorhandler.core.RxErrorHandler;
  24 +import me.jessyan.rxerrorhandler.handler.listener.ResponseErroListener;
  25 +import okhttp3.Cache;
  26 +import okhttp3.HttpUrl;
  27 +import okhttp3.Interceptor;
  28 +import okhttp3.OkHttpClient;
  29 +import retrofit2.Retrofit;
  30 +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
  31 +
  32 +/**
  33 + * Created by jessyan on 2017/3/14.
  34 + */
  35 +@Module
  36 +public class ClientModule {
  37 + private static final int TIME_OUT = 10;
  38 + public static final int HTTP_RESPONSE_DISK_CACHE_MAX_SIZE = 10 * 1024 * 1024;//缓存文件最大值为10Mb
  39 + private AppManager mAppManager;
  40 +
  41 +
  42 + public ClientModule(AppManager appManager) {
  43 + this.mAppManager = appManager;
  44 + }
  45 +
  46 + /**
  47 + * @param builder
  48 + * @param client
  49 + * @param httpUrl
  50 + * @return
  51 + * @author: jess
  52 + * @date 8/30/16 1:15 PM
  53 + * @description:提供retrofit
  54 + */
  55 + @Singleton
  56 + @Provides
  57 + Retrofit provideRetrofit(Retrofit.Builder builder, OkHttpClient client, HttpUrl httpUrl) {
  58 +
  59 + //处理一些有可能反序列化错误的接口
  60 + List<WrapGsonDeserializerInfo> deserializerInfos = new ArrayList<>();
  61 + WrapGsonDeserializerInfo user = new WrapGsonDeserializerInfo();
  62 + user.setClazz(UserEntity.class);
  63 + user.setDeserializer(new UserMayBeEmptyStringDeserializer());
  64 + deserializerInfos.add(user);
  65 +
  66 + return builder
  67 + .baseUrl(httpUrl)//域名
  68 + .client(client)//设置okhttp
  69 + //使用rxjava
  70 + .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
  71 + //使用我们自定义的Gson
  72 + .addConverterFactory(ShopinGsonConverterFactory.create(deserializerInfos))
  73 + .build();
  74 + }
  75 +
  76 + /**
  77 + * 提供OkhttpClient
  78 + * @param okHttpClient
  79 + * @return
  80 + */
  81 + @Singleton
  82 + @Provides
  83 + OkHttpClient provideClient(OkHttpClient.Builder okHttpClient, Cache cache, Interceptor intercept
  84 + , List<Interceptor> interceptors) {
  85 + OkHttpClient.Builder builder = okHttpClient
  86 + .connectTimeout(TIME_OUT, TimeUnit.SECONDS)
  87 + .readTimeout(TIME_OUT, TimeUnit.SECONDS)
  88 + .cache(cache)//设置缓存
  89 + .addNetworkInterceptor(intercept);
  90 + if (interceptors != null && interceptors.size() > 0) {//如果外部提供了interceptor的数组则遍历添加
  91 + for (Interceptor interceptor : interceptors) {
  92 + builder.addInterceptor(interceptor);
  93 + }
  94 + }
  95 + return builder
  96 + .build();
  97 + }
  98 +
  99 +
  100 + @Singleton
  101 + @Provides
  102 + Retrofit.Builder provideRetrofitBuilder() {
  103 + return new Retrofit.Builder();
  104 + }
  105 +
  106 +
  107 + @Singleton
  108 + @Provides
  109 + OkHttpClient.Builder provideClientBuilder() {
  110 + return new OkHttpClient.Builder();
  111 + }
  112 +
  113 +
  114 + @Singleton
  115 + @Provides
  116 + Cache provideCache(File cacheFile) {
  117 + return new Cache(cacheFile, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE);//设置缓存路径和大小
  118 + }
  119 +
  120 +
  121 + @Singleton
  122 + @Provides
  123 + Interceptor provideIntercept(RequestIntercept intercept) {
  124 + return intercept;//打印请求信息的拦截器
  125 + }
  126 +
  127 +
  128 + /**
  129 + * 提供RXCache客户端
  130 + * @param cacheDir 缓存路径
  131 + * @return
  132 + */
  133 + @Singleton
  134 + @Provides
  135 + RxCache provideRxCache(File cacheDir) {
  136 + return new RxCache
  137 + .Builder()
  138 + .persistence(cacheDir, new MyCacheSpeak());
  139 + }
  140 +
  141 +
  142 + /**
  143 + * 提供处理Rxjava错误的管理器
  144 + * @return
  145 + */
  146 + @Singleton
  147 + @Provides
  148 + RxErrorHandler proRxErrorHandler(Application application, ResponseErroListener listener) {
  149 + return RxErrorHandler
  150 + .builder()
  151 + .with(application)
  152 + .responseErroListener(listener)
  153 + .build();
  154 + }
  155 +//
  156 +// /**
  157 +// * 提供权限管理类,用于请求权限,适配6.0的权限管理
  158 +// *
  159 +// * @param application
  160 +// * @return
  161 +// */
  162 +// @Singleton
  163 +// @Provides
  164 +// RxPermissions provideRxPermissions(Application application) {
  165 +// return RxPermissions.getInstance(application);
  166 +// }
  167 +
  168 +
  169 + /**
  170 + * 提供管理所有activity的管理类
  171 + * @return
  172 + */
  173 + @Singleton
  174 + @Provides
  175 + AppManager provideAppManager() {
  176 + return mAppManager;
  177 + }
  178 +
  179 +
  180 +// .addNetworkInterceptor(new Interceptor() {
  181 +// @Override
  182 +// public Response intercept(Interceptor.Chain chain) throws IOException {
  183 +// Request request = chain.request();
  184 +// if(!DeviceUtils.netIsConnected(UiUtils.getContext())){
  185 +// request = request.newBuilder()
  186 +// .cacheControl(CacheControl.FORCE_CACHE)
  187 +// .build();
  188 +// LogUtils.warnInfo("http","no network");
  189 +// }
  190 +// Response originalResponse = chain.proceed(request);
  191 +// if(DeviceUtils.netIsConnected(UiUtils.getContext())){
  192 +// //有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置
  193 +// String cacheControl = request.cacheControl().toString();
  194 +// return originalResponse.newBuilder()
  195 +// .header("Cache-Control", cacheControl)
  196 +// .removeHeader("Pragma")
  197 +// .build();
  198 +// }else{
  199 +// return originalResponse.newBuilder()
  200 +// .header("Cache-Control", "public, only-if-cached, max-stale=2419200")
  201 +// .removeHeader("Pragma")
  202 +// .build();
  203 +// }
  204 +// }
  205 +// })
  206 +
  207 +}
  1 +package com.xdy.commonlibrary.core.di;
  2 +
  3 +import android.app.Application;
  4 +import android.text.TextUtils;
  5 +
  6 +import com.xdy.network.http.GlobeHttpHandler;
  7 +import com.xdy.util.DataHelper;
  8 +import com.xdy.util.Preconditions;
  9 +
  10 +import java.io.File;
  11 +import java.util.ArrayList;
  12 +import java.util.List;
  13 +
  14 +import javax.inject.Singleton;
  15 +
  16 +import dagger.Module;
  17 +import dagger.Provides;
  18 +import me.jessyan.rxerrorhandler.handler.listener.ResponseErroListener;
  19 +import okhttp3.HttpUrl;
  20 +import okhttp3.Interceptor;
  21 +
  22 +
  23 +/**
  24 + * Created by jessyan on 2017/3/14.
  25 + */
  26 +@Module
  27 +public class GlobeConfigModule {
  28 + private HttpUrl mApiUrl;
  29 + private GlobeHttpHandler mHandler;
  30 + private List<Interceptor> mInterceptors;
  31 + private ResponseErroListener mErroListener;
  32 + private File mCacheFile;
  33 +
  34 + public void setUrl(HttpUrl mApiUrl) {
  35 + this.mApiUrl = mApiUrl;
  36 + }
  37 +
  38 + /**
  39 + * @author: jess
  40 + * @date 8/5/16 11:03 AM
  41 + * @description: 设置baseurl
  42 + */
  43 + private GlobeConfigModule(Buidler buidler) {
  44 + this.mApiUrl = buidler.apiUrl;
  45 + this.mHandler = buidler.handler;
  46 + this.mInterceptors = buidler.interceptors;
  47 + this.mErroListener = buidler.responseErroListener;
  48 + this.mCacheFile = buidler.cacheFile;
  49 + }
  50 +
  51 + public static Buidler buidler() {
  52 + return new Buidler();
  53 + }
  54 +
  55 +
  56 + @Singleton
  57 + @Provides
  58 + List<Interceptor> provideInterceptors() {
  59 + return mInterceptors;
  60 + }
  61 +
  62 +
  63 + @Singleton
  64 + @Provides
  65 + HttpUrl provideBaseUrl() {
  66 + return mApiUrl;
  67 + }
  68 +
  69 +
  70 + @Singleton
  71 + @Provides
  72 + GlobeHttpHandler provideGlobeHttpHandler() {
  73 + return mHandler == null ? GlobeHttpHandler.EMPTY : mHandler;//打印请求信息
  74 + }
  75 +
  76 +
  77 + /**
  78 + * 提供缓存地址
  79 + */
  80 +
  81 + @Singleton
  82 + @Provides
  83 + File provideCacheFile(Application application) {
  84 + return mCacheFile == null ? DataHelper.getCacheFile(application) : mCacheFile;
  85 + }
  86 +
  87 +
  88 + /**
  89 + * 提供处理Rxjava错误的管理器的回调
  90 + * @return
  91 + */
  92 + @Singleton
  93 + @Provides
  94 + ResponseErroListener provideResponseErroListener() {
  95 + return mErroListener == null ? ResponseErroListener.EMPTY : mErroListener;
  96 + }
  97 +
  98 +
  99 + public static final class Buidler {
  100 + private HttpUrl apiUrl = HttpUrl.parse("https://api.github.com/");
  101 + private GlobeHttpHandler handler;
  102 + private List<Interceptor> interceptors = new ArrayList<>();
  103 + private ResponseErroListener responseErroListener;
  104 + private File cacheFile;
  105 +
  106 + private Buidler() {
  107 + }
  108 +
  109 + public Buidler baseurl(String baseurl) {//基础url
  110 + if (TextUtils.isEmpty(baseurl)) {
  111 + throw new IllegalArgumentException("baseurl can not be empty");
  112 + }
  113 + this.apiUrl = HttpUrl.parse(baseurl);
  114 + return this;
  115 + }
  116 +
  117 + public Buidler globeHttpHandler(GlobeHttpHandler handler) {//用来处理http响应结果
  118 + this.handler = handler;
  119 + return this;
  120 + }
  121 +
  122 + public Buidler addInterceptor(Interceptor interceptor) {//动态添加任意个interceptor
  123 + this.interceptors.add(interceptor);
  124 + return this;
  125 + }
  126 +
  127 +
  128 + public Buidler responseErroListener(ResponseErroListener listener) {//处理所有Rxjava的onError逻辑
  129 + this.responseErroListener = listener;
  130 + return this;
  131 + }
  132 +
  133 +
  134 + public Buidler cacheFile(File cacheFile) {
  135 + this.cacheFile = cacheFile;
  136 + return this;
  137 + }
  138 +
  139 +
  140 + public GlobeConfigModule build() {
  141 + Preconditions.checkNotNull(apiUrl, "baseurl is required");
  142 + return new GlobeConfigModule(this);
  143 + }
  144 + }
  145 +}
  1 +package com.xdy.commonlibrary.core.di;
  2 +
  3 +
  4 +import com.xdy.commonlibrary.imageloader.BaseImageLoaderStrategy;
  5 +import com.xdy.commonlibrary.imageloader.glide.GlideImageLoaderStrategy;
  6 +
  7 +import javax.inject.Singleton;
  8 +
  9 +import dagger.Module;
  10 +import dagger.Provides;
  11 +
  12 +/**
  13 + * Created by jess on 8/5/16 16:10
  14 + * contact with jess.yan.effort@gmail.com
  15 + */
  16 +@Module
  17 +public class ImageModule {
  18 +
  19 + @Singleton
  20 + @Provides
  21 + public BaseImageLoaderStrategy provideImageLoaderStrategy(GlideImageLoaderStrategy glideImageLoaderStrategy) {
  22 + return glideImageLoaderStrategy;
  23 + }
  24 +
  25 +}
  1 +/**
  2 + * Copyright (C) 2017 Fernando Cejas Open Source Project
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package com.xdy.commonlibrary.di.scope;
  17 +
  18 +import java.lang.annotation.Retention;
  19 +
  20 +import javax.inject.Scope;
  21 +
  22 +import static java.lang.annotation.RetentionPolicy.RUNTIME;
  23 +
  24 +/**
  25 + * A scoping annotation to permit objects whose lifetime should
  26 + * conform to the life of the activity to be memorized in the
  27 + * correct component.
  28 + */
  29 +@Scope
  30 +@Retention(RUNTIME)
  31 +public @interface ActivityScope {}
  1 +/**
  2 + * Copyright (C) 2017 Fernando Cejas Open Source Project
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package com.xdy.commonlibrary.di.scope;
  17 +
  18 +import java.lang.annotation.Retention;
  19 +
  20 +import javax.inject.Scope;
  21 +
  22 +import static java.lang.annotation.RetentionPolicy.RUNTIME;
  23 +
  24 +/**
  25 + * A scoping annotation to permit objects whose lifetime should
  26 + * conform to the life of the activity to be memorized in the
  27 + * correct component.
  28 + */
  29 +@Scope
  30 +@Retention(RUNTIME)
  31 +public @interface FragmentScope {}
  1 +package com.xdy.commonlibrary.entity;
  2 +
  3 +
  4 +/**
  5 + * @author 蒋洪波
  6 + * @file BaseBean.java
  7 + * @brief 新接口实体封装对象的基类
  8 + * @date 2017/1/8
  9 + * Copyright (c) 2017
  10 + * All rights reserved.
  11 + */
  12 +public class BaseEntity<T> {
  13 +
  14 + //结果是否正常
  15 + public boolean success;
  16 + //返回码
  17 + public String code;
  18 + //返回信息
  19 + public String errorMessage;
  20 + //具体数据类型
  21 + public T data;
  22 +
  23 + //强制更新标记
  24 + public static String FORCE_UPGRADE = "128";
  25 + //! 不合法token 标记
  26 + public static String INVALID_TOKENID = "004";
  27 + //! 停机维护时间
  28 + public static String FIX_TIME = "006";
  29 + //! 服务器返回 JSON结果正确标记
  30 + public static boolean RESULT_OK = true;
  31 + public static String CODE_RESULT_OK = "A00000";
  32 + //! JSON结果不正确标记
  33 + public static boolean RESULT_ERROR = false;
  34 + //! 缺少必要参数
  35 + public static String LACK_PARAMS = "003";
  36 + //! 服务器返回错误信息字段
  37 + public static String ERROR_MESSAGE = "errorMessage";
  38 + //! 服务器返回的code字段
  39 + public static String CODE = "code";
  40 + //网络请求的TOKEN KEY
  41 + public static String TOKEN = "tokenId";
  42 +
  43 +
  44 +
  45 +
  46 +}
  1 +package com.xdy.commonlibrary.entity;
  2 +
  3 +
  4 +/**
  5 + * @author jianghongbo
  6 + * @version 1.0
  7 + * @file CrashExceptionEntity.java
  8 + * @brief 崩溃异常的实体
  9 + * @date 2017/12/19
  10 + * Copyright (c) 2017
  11 + * All rights reserved.
  12 + */
  13 +//@Entity(
  14 +// // Whether getters and setters for properties should be generated if missing.
  15 +// generateGettersSetters = true)
  16 +public class CrashExceptionEntity {
  17 +
  18 + //主键
  19 +// @NotNull
  20 +// @Unique
  21 +// @Id
  22 +// private String md5Summary;
  23 +// @NotNull
  24 +// private String iphoneModel;
  25 +// @NotNull
  26 +// private String model;
  27 +// @NotNull
  28 +// private String errorMsg;
  29 +// private String occurDate;
  30 +// private Boolean uploadFlag;
  31 +// private String ReservedField1;
  32 +// private String ReservedField2;
  33 +// private String ReservedField3;
  34 +//
  35 +//
  36 +// @Generated(hash = 1266713787)
  37 +// public CrashExceptionEntity(@NotNull String md5Summary, @NotNull String iphoneModel,
  38 +// @NotNull String model, @NotNull String errorMsg, String occurDate,
  39 +// Boolean uploadFlag, String ReservedField1, String ReservedField2,
  40 +// String ReservedField3) {
  41 +// this.md5Summary = md5Summary;
  42 +// this.iphoneModel = iphoneModel;
  43 +// this.model = model;
  44 +// this.errorMsg = errorMsg;
  45 +// this.occurDate = occurDate;
  46 +// this.uploadFlag = uploadFlag;
  47 +// this.ReservedField1 = ReservedField1;
  48 +// this.ReservedField2 = ReservedField2;
  49 +// this.ReservedField3 = ReservedField3;
  50 +// }
  51 +//
  52 +// @Generated(hash = 1937612897)
  53 +// public CrashExceptionEntity() {
  54 +// }
  55 +//
  56 +//
  57 +// public String getMd5Summary() {
  58 +// return md5Summary;
  59 +// }
  60 +//
  61 +// public void setMd5Summary(String md5Summary) {
  62 +// this.md5Summary = md5Summary;
  63 +// }
  64 +//
  65 +// public String getIphoneModel() {
  66 +// return iphoneModel;
  67 +// }
  68 +//
  69 +// public void setIphoneModel(String iphoneModel) {
  70 +// this.iphoneModel = iphoneModel;
  71 +// }
  72 +//
  73 +// public String getModel() {
  74 +// return model;
  75 +// }
  76 +//
  77 +// public void setModel(String model) {
  78 +// this.model = model;
  79 +// }
  80 +//
  81 +// public String getErrorMsg() {
  82 +// return errorMsg;
  83 +// }
  84 +//
  85 +// public void setErrorMsg(String errorMsg) {
  86 +// this.errorMsg = errorMsg;
  87 +// }
  88 +//
  89 +// public String getOccurDate() {
  90 +// return occurDate;
  91 +// }
  92 +//
  93 +// public void setOccurDate(String occurDate) {
  94 +// this.occurDate = occurDate;
  95 +// }
  96 +//
  97 +// public Boolean getUploadFlag() {
  98 +// return uploadFlag;
  99 +// }
  100 +//
  101 +// public void setUploadFlag(Boolean uploadFlag) {
  102 +// this.uploadFlag = uploadFlag;
  103 +// }
  104 +//
  105 +// public String getReservedField1() {
  106 +// return ReservedField1;
  107 +// }
  108 +//
  109 +// public void setReservedField1(String reservedField1) {
  110 +// ReservedField1 = reservedField1;
  111 +// }
  112 +//
  113 +// public String getReservedField2() {
  114 +// return ReservedField2;
  115 +// }
  116 +//
  117 +// public void setReservedField2(String reservedField2) {
  118 +// ReservedField2 = reservedField2;
  119 +// }
  120 +//
  121 +// public String getReservedField3() {
  122 +// return ReservedField3;
  123 +// }
  124 +//
  125 +// public void setReservedField3(String reservedField3) {
  126 +// ReservedField3 = reservedField3;
  127 +// }
  128 +}
  1 +package com.xdy.commonlibrary.entity;
  2 +
  3 +
  4 +/**
  5 + * @author 蒋洪波
  6 + * @file ResultEntity.java
  7 + * @brief 检查数据是否正常
  8 + * @date 2017/1/8
  9 + * Copyright (c) 2017
  10 + * All rights reserved.
  11 + */
  12 +public class ResultEntity{
  13 +
  14 + //返回码
  15 + public String code;
  16 + //返回信息
  17 + public String errorMessage;
  18 + //是否解析成功标识
  19 + public boolean isSuccess;
  20 +
  21 +
  22 +}
  1 +package com.xdy.commonlibrary.entity;
  2 +
  3 +/**
  4 + * @author Administrator
  5 + * @version 1.0
  6 + * @file UserEntity.java
  7 + * @brief 用户实体类
  8 + * @date 2017/1/8
  9 + * Copyright (c) 2017
  10 + * All rights reserved.
  11 + */
  12 +public class UserEntity implements Cloneable {
  13 +
  14 + @Override
  15 + public Object clone() {
  16 + Object obj = null;
  17 + try {
  18 + obj = super.clone();
  19 + } catch (CloneNotSupportedException e) {
  20 + e.printStackTrace();
  21 + }
  22 + return obj;
  23 + }
  24 +
  25 + //用户头像,暂时没有
  26 + public String userPic; // //暂时没有返回
  27 +
  28 + //用户会员等级 1:v1会员,2:v2会员,3:v3会员
  29 + public String mType;
  30 + //用户积分
  31 + public long nowPoint;
  32 +
  33 + public String memberSid;//用户id
  34 +
  35 + public String answer;
  36 + public String nickName;
  37 + public String question;
  38 + public String realName;
  39 + public String registFrom;
  40 + public String registTime;
  41 + public String sid;
  42 + public String idCard;
  43 + public String profession;
  44 + public String memberAddress;
  45 + public String completeDate;
  46 + public String income;
  47 + public String birthdate;
  48 + public String gender;
  49 + public String optUid;
  50 + public String ipAddress;
  51 + public String mobile;
  52 +
  53 +
  54 +
  55 +
  56 + public String getMemberSid() {
  57 + return memberSid;
  58 + }
  59 +
  60 + public void setMemberSid(String memberSid) {
  61 + this.memberSid = memberSid;
  62 + }
  63 +
  64 + public String getUserPic() {
  65 + return userPic;
  66 + }
  67 +
  68 + public void setUserPic(String userPic) {
  69 + this.userPic = userPic;
  70 + }
  71 +
  72 +
  73 + public String getmType() {
  74 + return mType;
  75 + }
  76 +
  77 + public void setmType(String mType) {
  78 + this.mType = mType;
  79 + }
  80 +
  81 + public long getNowPoint() {
  82 + return nowPoint;
  83 + }
  84 +
  85 + public void setNowPoint(long nowPoint) {
  86 + this.nowPoint = nowPoint;
  87 + }
  88 +
  89 + public String getAnswer() {
  90 + return answer;
  91 + }
  92 +
  93 + public void setAnswer(String answer) {
  94 + this.answer = answer;
  95 + }
  96 +
  97 + public String getNickName() {
  98 + return nickName;
  99 + }
  100 +
  101 + public void setNickName(String nickName) {
  102 + this.nickName = nickName;
  103 + }
  104 +
  105 + public String getQuestion() {
  106 + return question;
  107 + }
  108 +
  109 + public void setQuestion(String question) {
  110 + this.question = question;
  111 + }
  112 +
  113 + public String getRealName() {
  114 + return realName;
  115 + }
  116 +
  117 + public void setRealName(String realName) {
  118 + this.realName = realName;
  119 + }
  120 +
  121 + public String getRegistFrom() {
  122 + return registFrom;
  123 + }
  124 +
  125 + public void setRegistFrom(String registFrom) {
  126 + this.registFrom = registFrom;
  127 + }
  128 +
  129 + public String getRegistTime() {
  130 + return registTime;
  131 + }
  132 +
  133 + public void setRegistTime(String registTime) {
  134 + this.registTime = registTime;
  135 + }
  136 +
  137 + public String getSid() {
  138 + return sid;
  139 + }
  140 +
  141 + public void setSid(String sid) {
  142 + this.sid = sid;
  143 + }
  144 +
  145 + public String getIdCard() {
  146 + return idCard;
  147 + }
  148 +
  149 + public void setIdCard(String idCard) {
  150 + this.idCard = idCard;
  151 + }
  152 +
  153 + public String getProfession() {
  154 + return profession;
  155 + }
  156 +
  157 + public void setProfession(String profession) {
  158 + this.profession = profession;
  159 + }
  160 +
  161 + public String getMemberAddress() {
  162 + return memberAddress;
  163 + }
  164 +
  165 + public void setMemberAddress(String memberAddress) {
  166 + this.memberAddress = memberAddress;
  167 + }
  168 +
  169 + public String getCompleteDate() {
  170 + return completeDate;
  171 + }
  172 +
  173 + public void setCompleteDate(String completeDate) {
  174 + this.completeDate = completeDate;
  175 + }
  176 +
  177 + public String getIncome() {
  178 + return income;
  179 + }
  180 +
  181 + public void setIncome(String income) {
  182 + this.income = income;
  183 + }
  184 +
  185 + public String getBirthdate() {
  186 + return birthdate;
  187 + }
  188 +
  189 + public void setBirthdate(String birthdate) {
  190 + this.birthdate = birthdate;
  191 + }
  192 +
  193 + public String getGender() {
  194 + return gender;
  195 + }
  196 +
  197 + public void setGender(String gender) {
  198 + this.gender = gender;
  199 + }
  200 +
  201 + public String getOptUid() {
  202 + return optUid;
  203 + }
  204 +
  205 + public void setOptUid(String optUid) {
  206 + this.optUid = optUid;
  207 + }
  208 +
  209 + public String getIpAddress() {
  210 + return ipAddress;
  211 + }
  212 +
  213 + public void setIpAddress(String ipAddress) {
  214 + this.ipAddress = ipAddress;
  215 + }
  216 +
  217 + public String getMobile() {
  218 + return mobile;
  219 + }
  220 +
  221 + public void setMobile(String mobile) {
  222 + this.mobile = mobile;
  223 + }
  224 +}
  1 +package com.xdy.commonlibrary.entity;
  2 +
  3 +import com.google.gson.JsonDeserializationContext;
  4 +import com.google.gson.JsonDeserializer;
  5 +import com.google.gson.JsonElement;
  6 +import com.google.gson.JsonObject;
  7 +
  8 +import java.lang.reflect.Type;
  9 +
  10 +/**
  11 + * @author 蒋洪波
  12 + * @version 2.0
  13 + * @file ReplenishDeserializer.java
  14 + * @brief 补货商品反序列化对象,样板对象有可能为空
  15 + * @date 2017/1/8
  16 + * Copyright (c) 2017, 商品折扣
  17 + * All rights reserved.
  18 + */
  19 +public class UserMayBeEmptyStringDeserializer implements JsonDeserializer<UserEntity> {
  20 +
  21 + @Override
  22 + public UserEntity deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
  23 + UserEntity defValue = null;
  24 + try {
  25 + if (json.isJsonObject()) {
  26 +
  27 + JsonObject jsonObject = json.getAsJsonObject();
  28 +
  29 + JsonElement memberSid = jsonObject.get("memberSid");
  30 + JsonElement answer = jsonObject.get("answer");
  31 + JsonElement nickName = jsonObject.get("nickName");
  32 + JsonElement question = jsonObject.get("question");
  33 + JsonElement realName = jsonObject.get("realName");
  34 + JsonElement registFrom = jsonObject.get("registFrom");
  35 + JsonElement registTime = jsonObject.get("registTime");
  36 +
  37 + JsonElement sid = jsonObject.get("sid");
  38 + JsonElement idCard = jsonObject.get("idCard");
  39 + JsonElement profession = jsonObject.get("profession");
  40 + JsonElement memberAddress = jsonObject.get("memberAddress");
  41 + JsonElement completeDate = jsonObject.get("completeDate");
  42 + JsonElement income = jsonObject.get("income");
  43 + JsonElement birthdate = jsonObject.get("birthdate");
  44 + JsonElement gender = jsonObject.get("gender");
  45 + JsonElement optUid = jsonObject.get("optUid");
  46 + JsonElement ipAddress = jsonObject.get("ipAddress");
  47 + JsonElement mobile = jsonObject.get("mobile");
  48 +
  49 + JsonElement userPic = jsonObject.get("userPic");
  50 + JsonElement mType = jsonObject.get("mType");
  51 + long nowPoint = jsonObject.get("nowPoints").getAsLong();
  52 +
  53 +
  54 + defValue = new UserEntity();
  55 +
  56 + if (userPic != null && !userPic.isJsonNull()) {
  57 + defValue.userPic = userPic.getAsString();
  58 + }
  59 + if (mType != null && !mType.isJsonNull()) {
  60 + defValue.mType = mType.getAsString();
  61 + }
  62 + if (String.valueOf(nowPoint) != null ) {
  63 + defValue.setNowPoint(nowPoint);
  64 + }
  65 + if (memberSid != null&& !memberSid.isJsonNull()) {
  66 + defValue.setMemberSid(memberSid.getAsString());
  67 + }
  68 + if (answer != null && !answer.isJsonNull()) {
  69 + defValue.answer = answer.getAsString();
  70 + }
  71 + if (nickName != null && !nickName.isJsonNull()) {
  72 + defValue.nickName = nickName.getAsString();
  73 + }
  74 + if (question != null&& !question.isJsonNull()) {
  75 + defValue.question = question.getAsString();
  76 + }
  77 +
  78 + if (realName != null && !realName.isJsonNull()) {
  79 + defValue.realName = realName.getAsString();
  80 + }
  81 + if (registFrom != null && !registFrom.isJsonNull()) {
  82 + defValue.registFrom = registFrom.getAsString();
  83 + }
  84 + if (registTime != null && !registTime.isJsonNull()) {
  85 + defValue.registTime = registTime.getAsString();
  86 + }
  87 + if (sid != null && !sid.isJsonNull()) {
  88 + defValue.sid = sid.getAsString();
  89 + }
  90 + if (idCard != null && !idCard.isJsonNull()) {
  91 + defValue.idCard = idCard.getAsString();
  92 + }
  93 + if (profession != null && !profession.isJsonNull()) {
  94 + defValue.profession = profession.getAsString();
  95 + }
  96 + if (memberAddress != null && !memberAddress.isJsonNull()) {
  97 + defValue.memberAddress = memberAddress.getAsString();
  98 + }
  99 + if (completeDate != null && !completeDate.isJsonNull()) {
  100 + defValue.completeDate = completeDate.getAsString();
  101 + }
  102 + if (income != null && !income.isJsonNull()) {
  103 + defValue.income = income.getAsString();
  104 + }
  105 + if (birthdate != null && !birthdate.isJsonNull()) {
  106 + defValue.birthdate = birthdate.getAsString();
  107 + }
  108 + if (gender != null && !gender.isJsonNull()) {
  109 + defValue.gender = gender.getAsString();
  110 + }
  111 + if (optUid != null && !optUid.isJsonNull()) {
  112 + defValue.optUid = optUid.getAsString();
  113 + }
  114 + if (ipAddress != null && !ipAddress.isJsonNull()) {
  115 + defValue.ipAddress = ipAddress.getAsString();
  116 + }
  117 + if (mobile != null && !mobile.isJsonNull()) {
  118 + defValue.mobile = mobile.getAsString();
  119 + }
  120 + }
  121 + } catch (Exception e) {
  122 + e.printStackTrace();
  123 + }
  124 +
  125 + return defValue;
  126 + }
  127 +}
  1 +package com.xdy.commonlibrary.event;
  2 +
  3 +
  4 +/**
  5 + * @author 蒋洪波
  6 + * @version 3.0
  7 + * @file CheckUpgradeEvent.java
  8 + * @brief 检查更新事件
  9 + * @date 2017/3/19
  10 + * Copyright (c) 2017, 上品折扣[]
  11 + * All rights reserved.
  12 + */
  13 +public class CheckUpgradeEvent {
  14 +
  15 + public CheckUpgradeEvent() {
  16 + }
  17 +}
  1 +package com.xdy.commonlibrary.exception;
  2 +
  3 +/**
  4 + * @author jianghongbo
  5 + * @version 1.0
  6 + * @file ResultException.java
  7 + * @brief 服务器返回结果异常
  8 + * @date 2017/12/21
  9 + * Copyright (c) 2017, 上品折扣[]
  10 + * All rights reserved.
  11 + */
  12 +public class ResultException extends RuntimeException {
  13 +
  14 + private String resultCode;
  15 + private String errorMessage;
  16 +
  17 + public ResultException(String message) {
  18 + super(message);
  19 + }
  20 +
  21 + public String getResultCode() {
  22 + return resultCode;
  23 + }
  24 +
  25 + public void setResultCode(String resultCode) {
  26 + this.resultCode = resultCode;
  27 + }
  28 +
  29 + public String getErrorMessage() {
  30 + return errorMessage;
  31 + }
  32 +
  33 + public void setErrorMessage(String errorMessage) {
  34 + this.errorMessage = errorMessage;
  35 + }
  36 +}
  1 +package com.xdy.commonlibrary.imageloader;
  2 +
  3 +import android.content.Context;
  4 +
  5 +/**
  6 + * Created by jess on 8/5/16 15:50
  7 + * contact with jess.yan.effort@gmail.com
  8 + */
  9 +public interface BaseImageLoaderStrategy<T extends ImageConfig> {
  10 + void loadImage(Context ctx, T config);
  11 +}
  1 +package com.xdy.commonlibrary.imageloader;
  2 +
  3 +import android.widget.ImageView;
  4 +
  5 +/**
  6 + * Created by jess on 8/5/16 15:19
  7 + * contact with jess.yan.effort@gmail.com
  8 + * 这里是图片加载配置信息的基类,可以定义一些所有图片加载框架都可以用的通用参数
  9 + */
  10 +public class ImageConfig {
  11 + protected String url;
  12 + protected ImageView imageView;
  13 + protected int placeholder;
  14 + protected int errorPic;
  15 +
  16 +
  17 + public String getUrl() {
  18 + return url;
  19 + }
  20 +
  21 + public ImageView getImageView() {
  22 + return imageView;
  23 + }
  24 +
  25 + public int getPlaceholder() {
  26 + return placeholder;
  27 + }
  28 +
  29 + public int getErrorPic() {
  30 + return errorPic;
  31 + }
  32 +}
  1 +package com.xdy.commonlibrary.imageloader;
  2 +
  3 +import android.content.Context;
  4 +
  5 +import javax.inject.Inject;
  6 +import javax.inject.Singleton;
  7 +
  8 +/**
  9 + * Created by jess on 8/5/16 15:57
  10 + * contact with jess.yan.effort@gmail.com
  11 + */
  12 +@Singleton
  13 +public class ImageLoader {
  14 + private BaseImageLoaderStrategy mStrategy;
  15 +
  16 + @Inject
  17 + public ImageLoader(BaseImageLoaderStrategy strategy) {
  18 + setLoadImgStrategy(strategy);
  19 + }
  20 +
  21 +
  22 + public <T extends ImageConfig> void loadImage(Context context, T config) {
  23 + this.mStrategy.loadImage(context, config);
  24 + }
  25 +
  26 +
  27 + public void setLoadImgStrategy(BaseImageLoaderStrategy strategy) {
  28 + this.mStrategy = strategy;
  29 + }
  30 +
  31 +}
  1 +package com.xdy.commonlibrary.imageloader.glide;
  2 +
  3 +import android.content.Context;
  4 +
  5 +import com.bumptech.glide.Glide;
  6 +import com.bumptech.glide.GlideBuilder;
  7 +import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool;
  8 +import com.bumptech.glide.load.engine.cache.DiskCache;
  9 +import com.bumptech.glide.load.engine.cache.DiskLruCacheWrapper;
  10 +import com.bumptech.glide.load.engine.cache.LruResourceCache;
  11 +import com.bumptech.glide.load.engine.cache.MemorySizeCalculator;
  12 +import com.bumptech.glide.module.GlideModule;
  13 +import com.xdy.util.DataHelper;
  14 +import com.xdy.commonlibrary.core.CommonAppLike;
  15 +
  16 +/**
  17 + * Created by jess on 16/4/15.
  18 + */
  19 +public class GlideConfiguration implements GlideModule {
  20 + public static final int IMAGE_DISK_CACHE_MAX_SIZE = 100 * 1024 * 1024;//图片缓存文件最大值为100Mb
  21 +
  22 + @Override
  23 + public void applyOptions(Context context, GlideBuilder builder) {
  24 + builder.setDiskCache(new DiskCache.Factory() {
  25 + @Override
  26 + public DiskCache build() {
  27 + // Careful: the external cache directory doesn't enforce permissions
  28 + return DiskLruCacheWrapper.get(DataHelper.getCacheFile(CommonAppLike.getContext()), IMAGE_DISK_CACHE_MAX_SIZE);
  29 + }
  30 + });
  31 +
  32 + MemorySizeCalculator calculator = new MemorySizeCalculator(context);
  33 + int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
  34 + int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
  35 +
  36 + int customMemoryCacheSize = (int) (1.2 * defaultMemoryCacheSize);
  37 + int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize);
  38 +
  39 + builder.setMemoryCache(new LruResourceCache(customMemoryCacheSize));
  40 + builder.setBitmapPool(new LruBitmapPool(customBitmapPoolSize));
  41 +
  42 + }
  43 +
  44 + @Override
  45 + public void registerComponents(Context context, Glide glide) {
  46 +
  47 + }
  48 +}
  1 +package com.xdy.commonlibrary.imageloader.glide;
  2 +
  3 +import android.widget.ImageView;
  4 +
  5 +import com.bumptech.glide.load.Transformation;
  6 +import com.xdy.commonlibrary.imageloader.ImageConfig;
  7 +
  8 +/**
  9 + * Created by jess on 8/5/16 15:19
  10 + * contact with jess.yan.effort@gmail.com
  11 + * 这里放Glide专属的配置信息,可以一直扩展字段,如果外部调用时想让图片加载框架
  12 + * 做一些操作,比如清除或则切换缓存策略,则可以定义一个int类型的变量,内部根据int做不同过的操作
  13 + * 其他操作同理
  14 + */
  15 +public class GlideImageConfig extends ImageConfig {
  16 + private int cacheStrategy;//0对应DiskCacheStrategy.all,1对应DiskCacheStrategy.NONE,2对应DiskCacheStrategy.SOURCE,3对应DiskCacheStrategy.RESULT
  17 + private Transformation transformation;//glide用它来改变图形的形状
  18 +
  19 + private GlideImageConfig(Buidler builder) {
  20 + this.url = builder.url;
  21 + this.imageView = builder.imageView;
  22 + this.placeholder = builder.placeholder;
  23 + this.errorPic = builder.errorPic;
  24 + this.cacheStrategy = builder.cacheStrategy;
  25 + this.transformation = builder.transformation;
  26 + }
  27 +
  28 + public int getCacheStrategy() {
  29 + return cacheStrategy;
  30 + }
  31 +
  32 + public Transformation getTransformation() {
  33 + return transformation;
  34 + }
  35 +
  36 + public static Buidler builder() {
  37 + return new Buidler();
  38 + }
  39 +
  40 +
  41 + public static final class Buidler {
  42 + private String url;
  43 + private ImageView imageView;
  44 + private int placeholder;
  45 + private int errorPic;
  46 + private int cacheStrategy;//0对应DiskCacheStrategy.all,1对应DiskCacheStrategy.NONE,2对应DiskCacheStrategy.SOURCE,3对应DiskCacheStrategy.RESULT
  47 + private Transformation transformation;//glide用它来改变图形的形状
  48 +
  49 + private Buidler() {
  50 + }
  51 +
  52 + public Buidler url(String url) {
  53 + this.url = url;
  54 + return this;
  55 + }
  56 +
  57 + public Buidler placeholder(int placeholder) {
  58 + this.placeholder = placeholder;
  59 + return this;
  60 + }
  61 +
  62 + public Buidler errorPic(int errorPic){
  63 + this.errorPic = errorPic;
  64 + return this;
  65 + }
  66 +
  67 + public Buidler imagerView(ImageView imageView) {
  68 + this.imageView = imageView;
  69 + return this;
  70 + }
  71 +
  72 + public Buidler cacheStrategy(int cacheStrategy) {
  73 + this.cacheStrategy = cacheStrategy;
  74 + return this;
  75 + }
  76 +
  77 + public Buidler transformation(Transformation transformation) {
  78 + this.transformation = transformation;
  79 + return this;
  80 + }
  81 +
  82 +
  83 + public GlideImageConfig build() {
  84 + if (url == null) throw new IllegalStateException("url is required");
  85 + if (imageView == null) throw new IllegalStateException("imageview is required");
  86 + return new GlideImageConfig(this);
  87 + }
  88 + }
  89 +}
  1 +package com.xdy.commonlibrary.imageloader.glide;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.Context;
  5 +
  6 +import com.bumptech.glide.DrawableRequestBuilder;
  7 +import com.bumptech.glide.Glide;
  8 +import com.bumptech.glide.RequestManager;
  9 +import com.bumptech.glide.load.engine.DiskCacheStrategy;
  10 +import com.xdy.commonlibrary.imageloader.BaseImageLoaderStrategy;
  11 +
  12 +import javax.inject.Inject;
  13 +import javax.inject.Singleton;
  14 +
  15 +/**
  16 + * Created by jess on 8/5/16 16:28
  17 + * contact with jess.yan.effort@gmail.com
  18 + */
  19 +@Singleton
  20 +public class GlideImageLoaderStrategy implements BaseImageLoaderStrategy<GlideImageConfig> {
  21 +
  22 + @Inject
  23 + public GlideImageLoaderStrategy() {
  24 + }
  25 +
  26 + @Override
  27 + public void loadImage(Context ctx, GlideImageConfig config) {
  28 + RequestManager manager;
  29 + if (ctx instanceof Activity)//如果是activity则可以使用Activity的生命周期
  30 + manager = Glide.with((Activity) ctx);
  31 + else
  32 + manager = Glide.with(ctx);
  33 +
  34 + DrawableRequestBuilder<String> requestBuilder = manager.load(config.getUrl())
  35 + .crossFade()
  36 + .centerCrop();
  37 +
  38 + switch (config.getCacheStrategy()) {//缓存策略
  39 + case 0:
  40 + requestBuilder.diskCacheStrategy(DiskCacheStrategy.ALL);
  41 + break;
  42 + case 1:
  43 + requestBuilder.diskCacheStrategy(DiskCacheStrategy.NONE);
  44 + break;
  45 + case 2:
  46 + requestBuilder.diskCacheStrategy(DiskCacheStrategy.SOURCE);
  47 + break;
  48 + case 3:
  49 + requestBuilder.diskCacheStrategy(DiskCacheStrategy.RESULT);
  50 + break;
  51 + }
  52 +
  53 + if (config.getTransformation() != null) {//glide用它来改变图形的形状
  54 + requestBuilder.transform(config.getTransformation());
  55 + }
  56 +
  57 +
  58 + if (config.getPlaceholder() != 0)//设置占位符
  59 + requestBuilder.placeholder(config.getPlaceholder());
  60 +
  61 + if (config.getErrorPic() != 0)//设置错误的图片
  62 + requestBuilder.error(config.getErrorPic());
  63 +
  64 + requestBuilder
  65 + .into(config.getImageView());
  66 + }
  67 +}
  1 +package com.xdy.commonlibrary.mvp;
  2 +
  3 +
  4 +import com.xdy.network.http.BaseCacheManager;
  5 +import com.xdy.network.http.BaseServiceManager;
  6 +
  7 +/**
  8 + * Created by jess on 8/5/16 12:55
  9 + * contact with jess.yan.effort@gmail.com
  10 + */
  11 +public class BaseModel<S extends BaseServiceManager, C extends BaseCacheManager> implements IModel{
  12 + protected S mServiceManager;//服务管理类,用于网络请求
  13 + protected C mCacheManager;//缓存管理类,用于管理本地或者内存缓存
  14 +
  15 + public BaseModel(S serviceManager, C cacheManager) {
  16 + this.mServiceManager = serviceManager;
  17 + this.mCacheManager = cacheManager;
  18 + }
  19 +
  20 + @Override
  21 + public void onDestory() {
  22 + if (mServiceManager != null) {
  23 + mServiceManager = null;
  24 + }
  25 + if (mCacheManager != null) {
  26 + mCacheManager = null;
  27 + }
  28 + }
  29 +}