├── .gitignore ├── CoreModule ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── peng │ │ └── android │ │ └── coremodule │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── peng │ │ │ └── android │ │ │ └── coremodule │ │ │ ├── cache │ │ │ └── ACache.java │ │ │ ├── db │ │ │ └── GreenDBUpdateHelper.java │ │ │ ├── http │ │ │ ├── ApiClient.java │ │ │ ├── ApiClientInitProvider.java │ │ │ └── convert │ │ │ │ ├── FastJsonConverterFactory.java │ │ │ │ ├── FastJsonRequestBodyConverter.java │ │ │ │ └── FastJsonResponseBodyConvert.java │ │ │ ├── preference │ │ │ └── PreferenceHelper.java │ │ │ └── router │ │ │ ├── ProxyFragmentManager.java │ │ │ ├── ProxyFragmentTransaction.java │ │ │ ├── RouterActivity.java │ │ │ └── RouterHelper.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── peng │ └── android │ └── coremodule │ └── ExampleUnitTest.java ├── OpenSourceLibrary ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── res │ └── values │ └── strings.xml ├── README.md ├── UIModule ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── peng │ │ └── coremodule │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── peng │ │ │ └── library │ │ │ └── mantis │ │ │ ├── Mantis.java │ │ │ ├── delegate │ │ │ └── DefaultViewDelegate.java │ │ │ ├── expand │ │ │ ├── MantisBaseContract.java │ │ │ ├── MantisBaseFragment.java │ │ │ ├── MantisBasePresent.java │ │ │ ├── data │ │ │ │ ├── MantisDataContract.java │ │ │ │ ├── MantisDataFragment.java │ │ │ │ └── MantisDataPresent.java │ │ │ ├── list │ │ │ │ ├── MantisListContract.java │ │ │ │ ├── MantisListFragment.java │ │ │ │ ├── MantisListPresent.java │ │ │ │ └── link │ │ │ │ │ ├── ListConfig.java │ │ │ │ │ └── RecyclerViewDivider.java │ │ │ └── refresh │ │ │ │ ├── MantisRefreshContract.java │ │ │ │ ├── MantisRefreshFragment.java │ │ │ │ ├── MantisRefreshPresent.java │ │ │ │ └── link │ │ │ │ ├── MantisPtrHandler.java │ │ │ │ ├── OnCreateHeaderViewListener.java │ │ │ │ └── RefreshConfig.java │ │ │ ├── hint │ │ │ ├── HintConfig.java │ │ │ ├── HintLayout.java │ │ │ ├── HintManager.java │ │ │ ├── IHintView.java │ │ │ ├── OnRetryListener.java │ │ │ └── OnShowErrorViewListener.java │ │ │ ├── kit │ │ │ ├── Codec.java │ │ │ ├── Kits.java │ │ │ └── MLog.java │ │ │ ├── model │ │ │ ├── AbsModel.java │ │ │ ├── BackThread.java │ │ │ └── ModelManager.java │ │ │ └── mvp │ │ │ ├── AbsPresentManager.java │ │ │ ├── BindPresent.java │ │ │ ├── DefaultPresentManager.java │ │ │ ├── IPresent.java │ │ │ ├── IView.java │ │ │ ├── IViewDelegate.java │ │ │ ├── MantisFragment.java │ │ │ ├── MantisPresent.java │ │ │ ├── PresentEvent.java │ │ │ ├── RxLifePresent.java │ │ │ └── ViewHelper.java │ └── res │ │ └── values │ │ ├── ids.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── peng │ └── coremodule │ └── ExampleUnitTest.java ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── peng │ │ └── mantis │ │ ├── TestApplication.java │ │ ├── activity │ │ ├── MainActivity.java │ │ ├── TestActivity.java │ │ ├── TestDataActivity.java │ │ ├── TestHintActivity.java │ │ └── TestRefreshActivity.java │ │ ├── contract │ │ ├── TestDataContract.java │ │ ├── TestHintContract.java │ │ ├── TestHttpContract.java │ │ ├── TestListContract.java │ │ ├── TestRefreshContract.java │ │ └── TestRepositoryContract.java │ │ ├── model │ │ ├── db │ │ │ ├── MantisDBHelper.java │ │ │ ├── MantisDBManager.java │ │ │ ├── entity │ │ │ │ ├── TodayWeather.java │ │ │ │ └── adapter │ │ │ │ │ └── TodayWeatherAdapter.java │ │ │ └── greendao │ │ │ │ ├── DaoMaster.java │ │ │ │ ├── DaoSession.java │ │ │ │ └── TodayWeatherDao.java │ │ ├── http │ │ │ ├── ApiClient.java │ │ │ ├── ApiConstants.java │ │ │ ├── entity │ │ │ │ ├── BaiDuImage.java │ │ │ │ ├── HomeMessage.java │ │ │ │ └── Weather.java │ │ │ ├── interceptor │ │ │ │ └── BenguoUrlInterceptor.java │ │ │ └── service │ │ │ │ └── MantisNetApi.java │ │ └── repository │ │ │ ├── TodayWeatherRepository.java │ │ │ └── UserIdRepository.java │ │ ├── present │ │ ├── TestDataPresent.java │ │ ├── TestHintPresent.java │ │ ├── TestHttpPresent.java │ │ ├── TestListPresent.java │ │ ├── TestRefreshPresent.java │ │ └── TestRepositoryPresent.java │ │ └── view │ │ └── fragment │ │ ├── TestDataFragment.java │ │ ├── TestHintFragment.java │ │ ├── TestHttpFragment.java │ │ ├── TestListFragment.java │ │ ├── TestRefreshFragment.java │ │ └── TestRepositoryFragment.java │ └── res │ ├── layout │ ├── activity_main.xml │ ├── activity_test.xml │ ├── activity_test_data.xml │ ├── activity_test_hint.xml │ ├── activity_test_refresh.xml │ ├── fragment_test_data.xml │ ├── fragment_test_hint.xml │ ├── fragment_test_http.xml │ ├── fragment_test_refresh.xml │ ├── fragment_test_repository.xml │ ├── hint_empty.xml │ ├── hint_error.xml │ ├── hint_net_error.xml │ ├── hint_progress.xml │ └── item_list_test_list.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── dependencies.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | .idea 11 | -------------------------------------------------------------------------------- /CoreModule/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /CoreModule/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.android["minSdkVersion"] 9 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | compile fileTree(include: ['*.jar'], dir: 'libs') 26 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 27 | exclude group: 'com.android.support', module: 'support-annotations' 28 | }) 29 | compile project(':OpenSourceLibrary') 30 | compile 'com.android.support:appcompat-v7:25.3.1' 31 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 32 | testCompile 'junit:junit:4.12' 33 | } 34 | -------------------------------------------------------------------------------- /CoreModule/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Users\Administrator\AppData\Local\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 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /CoreModule/src/androidTest/java/com/peng/android/coremodule/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.peng.android.coremodule.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CoreModule/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CoreModule/src/main/java/com/peng/android/coremodule/http/ApiClient.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule.http; 2 | 3 | import android.os.Looper; 4 | 5 | import java.util.HashMap; 6 | 7 | import okhttp3.OkHttpClient; 8 | import retrofit2.Retrofit; 9 | 10 | /** 11 | * 所有的API调用都必须在主线程里面 12 | * 13 | * Created by pyt on 2017/7/6. 14 | */ 15 | 16 | public class ApiClient { 17 | 18 | //缓存Service的Map 19 | private HashMap serviceMap = new HashMap<>(); 20 | 21 | //OKHttp 22 | private OkHttpClient defaultClient; 23 | 24 | //Retrofit 25 | private Retrofit defaultRetrofit; 26 | 27 | /** 28 | * 获取单例 29 | * @return 30 | */ 31 | public static ApiClient getInstance(){ 32 | return ApiClientHolder.INSTANCE; 33 | } 34 | 35 | /** 36 | * 初始化这个Client 37 | * @param listener 38 | */ 39 | public void init(ApiClientInitProvider listener) { 40 | checkIsMainThread(); 41 | if (listener != null) { 42 | defaultClient = listener.provideOkHttpClient(); 43 | defaultRetrofit = listener.provideRetrofit(defaultClient); 44 | } 45 | if (defaultClient == null) { 46 | defaultClient = new OkHttpClient(); 47 | } 48 | 49 | if (defaultRetrofit == null) { 50 | defaultRetrofit = new Retrofit.Builder().build(); 51 | } 52 | } 53 | 54 | 55 | /** 56 | * 返回一个默认的OkHttpClient 57 | * 58 | * 一般情况下用不到,除非有自定义的OkHttpClient,而已还需要默认的配置的 59 | * 60 | * @return OkHttpClient 61 | */ 62 | public OkHttpClient getDefaultOkHttpClient(){ 63 | checkIsMainThread(); 64 | return defaultClient; 65 | } 66 | 67 | /** 68 | * 返回一个默认的Retrofit 69 | * 70 | * 情况下用不到,除非有自定义Retrofit,并且需要默认的配置 71 | * 72 | * @return Retrofit 73 | */ 74 | public Retrofit getDefaultRetrofit(){ 75 | checkIsMainThread(); 76 | return defaultRetrofit; 77 | } 78 | 79 | /** 80 | * 获取Retrofit对应的Service 81 | * @param retrofit 82 | * @param serviceClz 83 | * @param 84 | * @return 85 | */ 86 | public T obtainService(Retrofit retrofit, Class serviceClz) { 87 | checkIsMainThread(); 88 | if (serviceClz == null) { 89 | throw new AssertionError(); 90 | } 91 | Object o = serviceMap.get(serviceClz); 92 | if (o == null) { 93 | o = retrofit.create(serviceClz); 94 | serviceMap.put(serviceClz, o); 95 | } 96 | return (T) o; 97 | } 98 | 99 | /** 100 | * 获取Retrofit对应的Service 101 | * @param serviceClz 102 | * @param 103 | * @return 104 | */ 105 | public T obtainService(Class serviceClz) { 106 | return obtainService(defaultRetrofit, serviceClz); 107 | } 108 | 109 | /** 110 | * 校验是否为主线程 111 | * @return 112 | */ 113 | private void checkIsMainThread(){ 114 | if (Looper.myLooper() != Looper.getMainLooper()) { 115 | throw new AssertionError(); 116 | } 117 | } 118 | 119 | //single 120 | private static class ApiClientHolder{ 121 | public static final ApiClient INSTANCE = new ApiClient(); 122 | } 123 | 124 | 125 | } -------------------------------------------------------------------------------- /CoreModule/src/main/java/com/peng/android/coremodule/http/ApiClientInitProvider.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule.http; 2 | 3 | import okhttp3.OkHttpClient; 4 | import retrofit2.Retrofit; 5 | 6 | /** 7 | * 8 | * 初始化ApiClient内容提供器 9 | * 10 | * Created by pyt on 2017/7/6. 11 | */ 12 | 13 | public interface ApiClientInitProvider { 14 | 15 | OkHttpClient provideOkHttpClient(); 16 | 17 | Retrofit provideRetrofit(OkHttpClient okHttpClient); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /CoreModule/src/main/java/com/peng/android/coremodule/http/convert/FastJsonConverterFactory.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule.http.convert; 2 | 3 | import com.alibaba.fastjson.serializer.SerializeConfig; 4 | 5 | import java.lang.annotation.Annotation; 6 | import java.lang.reflect.Type; 7 | 8 | import okhttp3.RequestBody; 9 | import okhttp3.ResponseBody; 10 | import retrofit2.Converter; 11 | import retrofit2.Retrofit; 12 | 13 | /** 14 | * Created by pyt on 2017/7/7. 15 | */ 16 | 17 | public class FastJsonConverterFactory extends Converter.Factory { 18 | private final SerializeConfig serializeConfig; 19 | 20 | private FastJsonConverterFactory(SerializeConfig serializeConfig) { 21 | if(serializeConfig == null) { 22 | throw new NullPointerException("serializeConfig == null"); 23 | } else { 24 | this.serializeConfig = serializeConfig; 25 | } 26 | } 27 | 28 | public static FastJsonConverterFactory create() { 29 | return create(SerializeConfig.getGlobalInstance()); 30 | } 31 | 32 | public static FastJsonConverterFactory create(SerializeConfig serializeConfig) { 33 | return new FastJsonConverterFactory(serializeConfig); 34 | } 35 | 36 | public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { 37 | return new FastJsonRequestBodyConverter(this.serializeConfig); 38 | } 39 | 40 | public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { 41 | return new FastJsonResponseBodyConvert(type); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /CoreModule/src/main/java/com/peng/android/coremodule/http/convert/FastJsonRequestBodyConverter.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule.http.convert; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.serializer.SerializeConfig; 5 | import com.alibaba.fastjson.serializer.SerializerFeature; 6 | 7 | import java.io.IOException; 8 | 9 | import okhttp3.MediaType; 10 | import okhttp3.RequestBody; 11 | import retrofit2.Converter; 12 | 13 | /** 14 | * Created by pyt on 2017/7/7. 15 | */ 16 | 17 | final class FastJsonRequestBodyConverter implements Converter { 18 | private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8"); 19 | private SerializeConfig serializeConfig; 20 | 21 | public FastJsonRequestBodyConverter(SerializeConfig serializeConfig) { 22 | this.serializeConfig = serializeConfig; 23 | } 24 | 25 | public RequestBody convert(T value) throws IOException { 26 | return RequestBody.create(MEDIA_TYPE, JSON.toJSONBytes(value, this.serializeConfig, new SerializerFeature[0])); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /CoreModule/src/main/java/com/peng/android/coremodule/http/convert/FastJsonResponseBodyConvert.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule.http.convert; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.parser.Feature; 5 | 6 | import java.io.IOException; 7 | import java.lang.reflect.Type; 8 | 9 | import okhttp3.ResponseBody; 10 | import retrofit2.Converter; 11 | 12 | /** 13 | * Created by pyt on 2017/7/7. 14 | */ 15 | 16 | class FastJsonResponseBodyConvert implements Converter { 17 | private Type type; 18 | 19 | public FastJsonResponseBodyConvert(Type type) { 20 | this.type = type; 21 | } 22 | 23 | public T convert(ResponseBody value) throws IOException { 24 | if (type == String.class) { 25 | return (T) value.string(); 26 | } 27 | return JSON.parseObject(value.string(), this.type, new Feature[0]); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CoreModule/src/main/java/com/peng/android/coremodule/preference/PreferenceHelper.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule.preference; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.text.TextUtils; 6 | 7 | /** 8 | * Created by pyt on 2017/7/10. 9 | */ 10 | 11 | public class PreferenceHelper { 12 | 13 | public static final int DEFAULT_NUM_VALUE = -1; 14 | public static final boolean DEFAULT_BOL_VALUE = false; 15 | public static final String DEFAULT_STR_VALUE = ""; 16 | 17 | //缓存类 18 | private SharedPreferences sharedPreferences; 19 | 20 | private PreferenceHelper(Context context, String name) { 21 | sharedPreferences = context.getSharedPreferences(name, Context.MODE_PRIVATE); 22 | } 23 | 24 | /** 25 | * 创建一个辅助类 26 | * 27 | * @param context 28 | * @param preferenceName 29 | * @return 30 | */ 31 | public static PreferenceHelper create(Context context, String preferenceName) { 32 | if (context == null || TextUtils.isEmpty(preferenceName)) { 33 | throw new IllegalArgumentException("the Context is null ,or preferenceName is null."); 34 | } 35 | return new PreferenceHelper(context.getApplicationContext(), preferenceName); 36 | } 37 | 38 | /** 39 | * 存数据 40 | * 41 | * @param key 42 | * @param value 43 | */ 44 | public void put(String key, Object value) { 45 | if (TextUtils.isEmpty(key) || value == null) { 46 | return; 47 | } 48 | SharedPreferences.Editor edit = sharedPreferences.edit(); 49 | if (value instanceof Integer) { 50 | edit.putInt(key, (Integer) value); 51 | } else if (value instanceof Float) { 52 | edit.putFloat(key, (Float) value); 53 | } else if (value instanceof Long) { 54 | edit.putLong(key, (Long) value); 55 | } else if (value instanceof Boolean) { 56 | edit.putBoolean(key, (Boolean) value); 57 | } else if (value instanceof String) { 58 | edit.putString(key, (String) value); 59 | }else{ 60 | throw new IllegalArgumentException("not support "+value.getClass()+" type!"); 61 | } 62 | } 63 | 64 | /** 65 | * @param key 66 | * @return 67 | */ 68 | public int getInt(String key) { 69 | return getInt(key, DEFAULT_NUM_VALUE); 70 | } 71 | 72 | /** 73 | * 74 | * @param key 75 | * @param defValue 76 | * @return 77 | */ 78 | public int getInt(String key, int defValue) { 79 | return sharedPreferences.getInt(key, DEFAULT_NUM_VALUE); 80 | } 81 | 82 | /** 83 | * 84 | * @param key 85 | * @return 86 | */ 87 | public boolean getBoolean(String key) { 88 | return getBoolean(key, DEFAULT_BOL_VALUE); 89 | } 90 | 91 | public boolean getBoolean(String key, boolean defValue) { 92 | return sharedPreferences.getBoolean(key, defValue); 93 | } 94 | 95 | /** 96 | * 97 | * @param key 98 | * @return 99 | */ 100 | public float getFloat(String key) { 101 | return getFloat(key, DEFAULT_NUM_VALUE); 102 | } 103 | 104 | /** 105 | * 106 | * @param key 107 | * @param defValue 108 | * @return 109 | */ 110 | public float getFloat(String key, float defValue) { 111 | return sharedPreferences.getFloat(key, defValue); 112 | } 113 | 114 | /** 115 | * 116 | * @param key 117 | * @return 118 | */ 119 | public long getLong(String key) { 120 | return getLong(key, DEFAULT_NUM_VALUE); 121 | } 122 | 123 | /** 124 | * 125 | * @param key 126 | * @param defValue 127 | * @return 128 | */ 129 | public long getLong(String key, long defValue) { 130 | return sharedPreferences.getLong(key, defValue); 131 | } 132 | 133 | /** 134 | * 135 | * @param key 136 | * @return 137 | */ 138 | public String getString(String key) { 139 | return getString(key, DEFAULT_STR_VALUE); 140 | } 141 | 142 | /** 143 | * 144 | * @param key 145 | * @param defValue 146 | * @return 147 | */ 148 | public String getString(String key, String defValue) { 149 | return sharedPreferences.getString(key, defValue); 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /CoreModule/src/main/java/com/peng/android/coremodule/router/ProxyFragmentManager.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule.router; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.IdRes; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.app.FragmentManager; 8 | import android.support.v4.app.FragmentTransaction; 9 | 10 | import java.io.FileDescriptor; 11 | import java.io.PrintWriter; 12 | import java.util.List; 13 | 14 | /** 15 | * 静态代理的FragmentManager 16 | * Created by pyt on 2017/7/10. 17 | */ 18 | 19 | public class ProxyFragmentManager extends FragmentManager { 20 | 21 | /** 22 | * 创建这个Activity 23 | * 24 | * @param fragmentManager 25 | * @param intent 26 | * @return 代理的FragmentManager 27 | */ 28 | public static ProxyFragmentManager create(FragmentManager fragmentManager, Intent intent) { 29 | return new ProxyFragmentManager(fragmentManager, intent); 30 | } 31 | 32 | private FragmentManager fragmentManager; 33 | 34 | private Intent intent; 35 | 36 | private ProxyFragmentManager(FragmentManager fragmentManager, Intent intent) { 37 | this.fragmentManager = fragmentManager; 38 | this.intent = intent; 39 | } 40 | 41 | @Override 42 | public FragmentTransaction beginTransaction() { 43 | return ProxyFragmentTransaction.create(fragmentManager.beginTransaction(), intent); 44 | } 45 | 46 | @Override 47 | public boolean executePendingTransactions() { 48 | return this.fragmentManager.executePendingTransactions(); 49 | } 50 | 51 | @Override 52 | public Fragment findFragmentById(@IdRes int id) { 53 | return this.fragmentManager.findFragmentById(id); 54 | } 55 | 56 | @Override 57 | public Fragment findFragmentByTag(String tag) { 58 | return this.fragmentManager.findFragmentByTag(tag); 59 | } 60 | 61 | @Override 62 | public void popBackStack() { 63 | this.fragmentManager.popBackStack(); 64 | } 65 | 66 | @Override 67 | public boolean popBackStackImmediate() { 68 | return this.fragmentManager.popBackStackImmediate(); 69 | } 70 | 71 | @Override 72 | public void popBackStack(String name, int flags) { 73 | this.fragmentManager.popBackStack(name, flags); 74 | } 75 | 76 | @Override 77 | public boolean popBackStackImmediate(String name, int flags) { 78 | return this.fragmentManager.popBackStackImmediate(name, flags); 79 | } 80 | 81 | @Override 82 | public void popBackStack(int id, int flags) { 83 | this.fragmentManager.popBackStack(id, flags); 84 | } 85 | 86 | @Override 87 | public boolean popBackStackImmediate(int id, int flags) { 88 | return this.fragmentManager.popBackStackImmediate(id, flags); 89 | } 90 | 91 | @Override 92 | public int getBackStackEntryCount() { 93 | return this.fragmentManager.getBackStackEntryCount(); 94 | } 95 | 96 | @Override 97 | public BackStackEntry getBackStackEntryAt(int index) { 98 | return this.fragmentManager.getBackStackEntryAt(index); 99 | } 100 | 101 | @Override 102 | public void addOnBackStackChangedListener(OnBackStackChangedListener listener) { 103 | this.fragmentManager.addOnBackStackChangedListener(listener); 104 | } 105 | 106 | @Override 107 | public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) { 108 | this.fragmentManager.removeOnBackStackChangedListener(listener); 109 | } 110 | 111 | @Override 112 | public void putFragment(Bundle bundle, String key, Fragment fragment) { 113 | this.fragmentManager.putFragment(bundle, key, fragment); 114 | } 115 | 116 | @Override 117 | public Fragment getFragment(Bundle bundle, String key) { 118 | return this.fragmentManager.getFragment(bundle, key); 119 | } 120 | 121 | @Override 122 | public List getFragments() { 123 | return this.fragmentManager.getFragments(); 124 | } 125 | 126 | @Override 127 | public Fragment.SavedState saveFragmentInstanceState(Fragment f) { 128 | return this.fragmentManager.saveFragmentInstanceState(f); 129 | } 130 | 131 | @Override 132 | public boolean isDestroyed() { 133 | return this.fragmentManager.isDestroyed(); 134 | } 135 | 136 | @Override 137 | public void registerFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb, boolean recursive) { 138 | this.fragmentManager.registerFragmentLifecycleCallbacks(cb, recursive); 139 | } 140 | 141 | @Override 142 | public void unregisterFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb) { 143 | this.fragmentManager.unregisterFragmentLifecycleCallbacks(cb); 144 | } 145 | 146 | @Override 147 | public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 148 | this.fragmentManager.dump(prefix, fd, writer, args); 149 | } 150 | 151 | 152 | } 153 | -------------------------------------------------------------------------------- /CoreModule/src/main/java/com/peng/android/coremodule/router/RouterActivity.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule.router; 2 | 3 | import android.support.v4.app.FragmentManager; 4 | import android.support.v7.app.AppCompatActivity; 5 | 6 | /** 7 | * 路由Activity 8 | * Created by pyt on 2017/7/11. 9 | */ 10 | 11 | public class RouterActivity extends AppCompatActivity { 12 | 13 | @Override 14 | public FragmentManager getSupportFragmentManager() { 15 | return RouterHelper.create(super.getSupportFragmentManager(), this); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CoreModule/src/main/java/com/peng/android/coremodule/router/RouterHelper.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule.router; 2 | 3 | import android.app.Activity; 4 | import android.support.v4.app.FragmentManager; 5 | 6 | 7 | 8 | /** 9 | * 路由辅助类 10 | * Created by pyt on 2017/7/10. 11 | */ 12 | 13 | public class RouterHelper { 14 | 15 | /** 16 | * 获取支持路由的帮助类 17 | * @param fragmentManager 18 | * @param activity 19 | * @return 20 | */ 21 | public static FragmentManager create(FragmentManager fragmentManager, Activity activity) { 22 | return ProxyFragmentManager.create(fragmentManager, activity.getIntent()); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /CoreModule/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CoreModule 3 | 4 | -------------------------------------------------------------------------------- /CoreModule/src/test/java/com/peng/android/coremodule/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.peng.android.coremodule; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /OpenSourceLibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /OpenSourceLibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.android["minSdkVersion"] 9 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | testCompile rootProject.ext.dependencies["junit"] 28 | 29 | //ButterKnife 30 | compile rootProject.ext.dependencies["butterknife"] 31 | annotationProcessor rootProject.ext.dependencies["butterknife-compiler"] 32 | 33 | //RxJava 34 | compile rootProject.ext.dependencies["rxandroid"] 35 | compile rootProject.ext.dependencies["rxjava"] 36 | compile rootProject.ext.dependencies["rxlifecycle"] 37 | compile rootProject.ext.dependencies["rxlifecycle-components"] 38 | 39 | //图片 40 | compile rootProject.ext.dependencies["glide"] 41 | 42 | //UI相关 43 | compile rootProject.ext.dependencies["recyclerview-v7"] 44 | compile rootProject.ext.dependencies["appcompat-v7"] 45 | compile rootProject.ext.dependencies["constraint-layout"] 46 | compile rootProject.ext.dependencies["refresh-layout-lib"] 47 | compile rootProject.ext.dependencies["BRVAH"] 48 | 49 | //网络 50 | compile rootProject.ext.dependencies["retrofit"] 51 | compile rootProject.ext.dependencies["adapter-rxjava"] 52 | compile rootProject.ext.dependencies["okhttp3"] 53 | compile rootProject.ext.dependencies["okhttp3-logging-interceptor"] 54 | 55 | //调试 56 | compile rootProject.ext.dependencies["stetho"] 57 | compile rootProject.ext.dependencies["stetho-okhttp3"] 58 | 59 | //Json解析 60 | compile rootProject.ext.dependencies["fastjson"] 61 | 62 | //数据库 63 | compile rootProject.ext.dependencies["greendao"] 64 | 65 | //路由 66 | compile rootProject.ext.dependencies["arouter-api"] 67 | 68 | //卡片View 69 | compile rootProject.ext.dependencies["cardview-v7"] 70 | 71 | } 72 | -------------------------------------------------------------------------------- /OpenSourceLibrary/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/baron/develop/android/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 | #} 18 | -------------------------------------------------------------------------------- /OpenSourceLibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /OpenSourceLibrary/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Mantis概述([github地址](https://github.com/pengyuantao/Mantis)) 2 | ***** 3 | 1. 前言 4 | 2015年是MVP设计模式的爆发年,可以说是出现了百家争鸣的局面,例如:[TheMVP](https://github.com/kymjs/TheMVP)、[Beam](https://github.com/Jude95/Beam)等等MVP的框架,2017年Google推出了一个新的应用开发框架[指南](https://developer.android.com/topic/libraries/architecture/guide.html),看完之后如醍醐灌顶,这个的架构思想太好了。于是疯狂的在github上找类似的框架,发现这样的[MinimalistWeather](https://github.com/BaronZ88/MinimalistWeather)项目,经过研究,这就是我想要的mvp架构,只是作者提供了一个标准,和一些简单的实现,并不能提高开发的效率,于是我想基于这样的MVP结构,开发一款快速开发,又能在代码中直接规范开发者代码的框架——Mantis。 5 | 6 | ![framework_minimalist_weather.png](http://upload-images.jianshu.io/upload_images/1460021-d511001582e3d424.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 7 | 8 | 2. 架构的简要说明 9 | * Contract:View和Presenter进行数据交互的协议,协议中没有定义的方法,View和Presenter只能调用协议中定义的方法。 10 | * Activity: 负责管理View和Presenter的管理类 11 | * Responsitory:专门为Presenter提供各种的数据(Http/Db/SharePreference) 12 | 13 | 3. 细节决定是否好用 14 | 这样的框架是好了,关键我们开发的时候还是需要写很多的多的代码,针对一些通用的代码和功能,进行了总结。 15 | * 通用的提示页面(空页面、网络错误页面,运行错误页面)。 16 | * 通用的数据页面、列表页面、下拉刷新及上拉加载页面。 17 | * 统一以及规定接口,提高团队开发效率。 18 | * RxLifecycle对Presenter生命周期的管理。 19 | 4. 开源框架的整合 20 | * Rxjava 21 | * Retrofit 22 | * OkHttp 23 | * GreenDao 24 | * RetroLambda 25 | * android-Ultra-Pull-To-Refresh 26 | * BRVAH 27 | * ButterKnife 28 | ### Mantis的使用 29 | **** 30 | 1. Mantis的初始化 31 | ``` 32 | //建议在Application的中进行Mantis的初始化操作,各种Builder详见Demo中 33 | Mantis.getInstance().init(this); 34 | //设置显示EmptyView,ErrorView,NetErrorView的Builder 35 | Mantis.getInstance().setHintConfigBuilder(getDefaultHintConfigBuilder()); 36 | //设置页面刷新相关的配置 37 | Mantis.getInstance().setRefreshConfigBuilder(getDefaultRefreshBuilder()); 38 | //设置列表页面的相关的配置 39 | Mantis.getInstance().setListConfigBuilder(getDefaultListBuilder()); 40 | ``` 41 | 2. 根据需求定义协议 42 | 目前有3大内置协议,每一个协议都有MantisXXXFragment和MantisXXXPresent与之对应,使用该协议的Fragment或Present必须继承于对应的MantisXXXFragment或MantisXXXPresent。 43 | 44 | |协议名称|使用范围| 45 | |:---|:----| 46 | |MantisDataContract|适用于单一数据的界面,例如:商品详情,只是需要一个详情数据| 47 | |MantisRefreshContract|适合非列表页面的刷新协议| 48 | |MantisListContract|集成于MantisRefreshContract协议,自带就有刷新的功能| 49 | |MantisBaseContract|如果不需要刷新或者列表的功能,那么你完全可以集成这个协议,自己进行定义| 50 | ```` 51 | /** 52 | * 53 | *加入使用的是MantisDataContract协议 54 | */ 55 | public interface TestDataContract{ 56 | interface View extends MantisDataContract.View{ 57 | void toast (String msg); 58 | } 59 | interface Present extends MantisDataContract.Present{ 60 | void login (String account, String password); 61 | void logout (); 62 | } 63 | } 64 | 65 | /** 66 | * Fragment (View)的定义,继承TestDataContract.View接口,传入对应的泛型 67 | * 使用BindPresent注解指定这个Fragment需要进行引用的Present具体的实现类 68 | */ 69 | @BindPresent(value = TestDataPresent.class) 70 | public class TestDataFragment extends MantisDataFragment implements TestDataContract.View{} 71 | 72 | /** 73 | * Present的定义,继承TestDataContract.Present接口,传入对应的泛型 74 | * 75 | */ 76 | public class TestDataPresent extends MantisDataPresent implements TestDataContract.Present {} 77 | 78 | //在View中可以通过getPresent()方法获取Present实例,从而调用Present在协议中提供的api,在Present中通过getView()方法获取View的实例,从而调用View在协议中提供的api。 79 | ```` 80 | 3. Present绑定生命周期防止内存的泄露 81 | 我是将RxLifecycle绑定生命周期的方法移植到Present里面,用法和RxLifecycle一样。 82 | ``` 83 | Observable.create(subscriber -> subscriber.onNext("登录成功 账号:" + account + " 密码:" + password)) 84 | .delay(2, TimeUnit.SECONDS) 85 | .subscribeOn(Schedulers.io()) 86 | //如果是Rxjava通过下面的用法进行绑定 87 | .compose(bindUntilEvent(PresentEvent.DESTROY)) 88 | .observeOn(AndroidSchedulers.mainThread()) 89 | .subscribe(s -> { 90 | publishData(s); 91 | Log.i(TAG, "login: 执行onNext"); 92 | } 93 | , throwable -> { 94 | publishError(throwable); 95 | Log.i(TAG, "login: 执行onError"); 96 | } 97 | , () -> { 98 | Log.i(TAG, "login: 执行onComplete"); 99 | }); 100 | ``` 101 | 4. Present中空指提示View的显示和隐藏 102 | 通过getViewDeletegate()方法获取提示view的代理对象 103 | ``` 104 | @Override 105 | public void reload() { 106 | reloadIndex++; 107 | Log.i(TAG, "reload: index [ " + reloadIndex + " ]"); 108 | if ( reloadIndex == 1) { 109 | createCommonObservable("", 1).subscribe(s -> getViewDelegate().showNetworkErrorView()); 110 | Log.i(TAG, "reload:显示网络异常View"); 111 | } else if ( reloadIndex == 2) { 112 | createCommonObservable("", 1) .subscribe(s -> getViewDelegate().showErrorView("十分的抱歉", "由于攻城狮GG的失误,导致程序的奔溃,截此图奖励9999999元")); 113 | Log.i(TAG, "reload: 显示程序错误View"); 114 | }else { 115 | createCommonObservable("恭喜恭喜,终于显示ContentView了,来自不易啊!", 1).subscribe(s -> publishData(s), throwable -> publishError(throwable)); 116 | Log.i(TAG, "reload: 显示内容View"); 117 | reloadIndex = 0; 118 | } 119 | } 120 | ``` 121 | 5. 个性化定义刷新和列表 122 | 还记得咱们再Application中定义的各种Builder嘛,这个时候总算用到了,哈哈,很多时候我们的刷新和提示不见的所有的页面都是一样的,那么就可以通过你重新MantisXXXFragment的onCreateView方法,进行个性化的设置。 123 | ``` 124 | @Override 125 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState, HintConfig.Builder hintBuilder, RefreshConfig.Builder refreshBuilder) { 126 | refreshBuilder.autoRefresh(false); 127 | return inflater.inflate(R.layout.fragment_test_refresh, container, false); 128 | } 129 | ``` 130 | -------------------------------------------------------------------------------- /UIModule/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /UIModule/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'me.tatarka.retrolambda' 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 15 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | 22 | compileOptions { 23 | sourceCompatibility JavaVersion.VERSION_1_8 24 | targetCompatibility JavaVersion.VERSION_1_8 25 | } 26 | 27 | } 28 | 29 | 30 | dependencies { 31 | compile fileTree(include: ['*.jar'], dir: 'libs') 32 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 33 | exclude group: 'com.android.support', module: 'support-annotations' 34 | }) 35 | compile 'com.android.support:appcompat-v7:25.3.1' 36 | testCompile 'junit:junit:4.12' 37 | compile project(':OpenSourceLibrary') 38 | } 39 | -------------------------------------------------------------------------------- /UIModule/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Users\Administrator\AppData\Local\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 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /UIModule/src/androidTest/java/com/peng/coremodule/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.peng.coremodule; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.peng.coremodule.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /UIModule/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/Mantis.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis; 2 | 3 | import android.app.Application; 4 | 5 | import com.peng.library.mantis.expand.list.link.ListConfig; 6 | import com.peng.library.mantis.hint.HintConfig; 7 | import com.peng.library.mantis.model.ModelManager; 8 | import com.peng.library.mantis.expand.refresh.link.RefreshConfig; 9 | 10 | /** 11 | * 超级大螳螂,目前为主要的管理类 12 | *

13 | * 主要功能: 14 | * 1.对全部的HintView进行初始化 15 | *

16 | * Created by pyt on 2017/6/19. 17 | */ 18 | public class Mantis { 19 | 20 | private static Mantis instance = new Mantis(); 21 | 22 | private HintConfig.Builder hintConfigBuilder; 23 | 24 | private RefreshConfig.Builder refreshConfigBuilder; 25 | 26 | private ListConfig.Builder listConfigBuilder; 27 | 28 | public static Mantis getInstance() { 29 | return instance; 30 | } 31 | 32 | /** 33 | * @param application 34 | */ 35 | public void init(Application application) { 36 | ModelManager.init(application); 37 | } 38 | 39 | /** 40 | * 设置提示View的配置Builder 41 | * 42 | * @param builder 43 | */ 44 | public void setHintConfigBuilder(HintConfig.Builder builder) { 45 | this.hintConfigBuilder = builder; 46 | } 47 | 48 | /** 49 | * 设置刷新View的配置Builder 50 | * 51 | * @param refreshConfigBuilder 52 | */ 53 | public void setRefreshConfigBuilder(RefreshConfig.Builder refreshConfigBuilder) { 54 | this.refreshConfigBuilder = refreshConfigBuilder; 55 | } 56 | 57 | public void setListConfigBuilder(ListConfig.Builder listConfigBuilder) { 58 | this.listConfigBuilder = listConfigBuilder; 59 | } 60 | 61 | public HintConfig.Builder getHintConfigBuilder() { 62 | return hintConfigBuilder == null ? null : hintConfigBuilder.clone(); 63 | } 64 | 65 | public RefreshConfig.Builder getRefreshConfigBuilder() { 66 | return refreshConfigBuilder == null ? null : refreshConfigBuilder.clone(); 67 | } 68 | 69 | public ListConfig.Builder getListConfigBuilder() { 70 | return listConfigBuilder == null ? null : listConfigBuilder.clone(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/delegate/DefaultViewDelegate.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.delegate; 2 | 3 | 4 | import com.peng.library.mantis.hint.HintManager; 5 | import com.peng.library.mantis.kit.MLog; 6 | import com.peng.library.mantis.mvp.IViewDelegate; 7 | 8 | /** 9 | * Created by pyt on 2017/6/21. 10 | */ 11 | 12 | public class DefaultViewDelegate implements IViewDelegate { 13 | 14 | private static final String TAG = "DefaultViewDelegate"; 15 | 16 | private HintManager hintManager; 17 | 18 | public DefaultViewDelegate(HintManager hintManager) { 19 | this.hintManager = hintManager; 20 | if (hintManager == null) {//不正确 21 | MLog.i( "DefaultViewDelegate: HintConfig.Builder of config is incorrect, the viewDelegate is useLess!"); 22 | } 23 | } 24 | 25 | public DefaultViewDelegate setHintManager(HintManager hintManager) { 26 | this.hintManager = hintManager; 27 | return this; 28 | } 29 | 30 | @Override 31 | public void showErrorView(String title, String content) { 32 | if (hintManager != null) { 33 | hintManager.showErrorView(title, content); 34 | } else { 35 | MLog.i( "showErrorView: null"); 36 | } 37 | } 38 | 39 | @Override 40 | public void showNetworkErrorView() { 41 | if (hintManager != null) { 42 | hintManager.showNetworkErrorView(); 43 | }else { 44 | MLog.i( "showNetworkErrorView: null"); 45 | } 46 | } 47 | 48 | @Override 49 | public void showEmptyView() { 50 | if (hintManager != null) { 51 | hintManager.showEmptyView(); 52 | }else { 53 | MLog.i( "showEmptyView: null"); 54 | } 55 | } 56 | 57 | @Override 58 | public void showProgressView() { 59 | if (hintManager != null) { 60 | hintManager.showProgressView(); 61 | }else { 62 | MLog.i( "showProgressView: null"); 63 | } 64 | } 65 | 66 | @Override 67 | public void showContentView() { 68 | if (hintManager != null) { 69 | hintManager.showContentView(); 70 | }else { 71 | MLog.i( "showContentView: null"); 72 | } 73 | } 74 | 75 | @Override 76 | public void showErrorView(String title, String content, Object tag) { 77 | if (hintManager != null) { 78 | hintManager.showErrorView(title, content, tag); 79 | }else { 80 | MLog.i( "showErrorView: null"); 81 | } 82 | } 83 | 84 | @Override 85 | public void showNetworkErrorView(Object tag) { 86 | if (hintManager != null) { 87 | hintManager.showNetworkErrorView( tag); 88 | }else { 89 | MLog.i( "showNetworkErrorView: null"); 90 | } 91 | } 92 | 93 | @Override 94 | public void showEmptyView(Object tag) { 95 | if (hintManager != null) { 96 | hintManager.showEmptyView( tag); 97 | }else { 98 | MLog.i( "showEmptyView: null"); 99 | } 100 | } 101 | 102 | 103 | 104 | } 105 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/MantisBaseContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand; 2 | 3 | import com.peng.library.mantis.mvp.IPresent; 4 | import com.peng.library.mantis.mvp.IView; 5 | 6 | /** 7 | * Created by pyt on 2017/8/8. 8 | */ 9 | 10 | public interface MantisBaseContract { 11 | 12 | interface View extends IView { 13 | 14 | } 15 | 16 | interface Present extends IPresent{ 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/MantisBaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.peng.library.mantis.Mantis; 10 | import com.peng.library.mantis.delegate.DefaultViewDelegate; 11 | import com.peng.library.mantis.hint.HintConfig; 12 | import com.peng.library.mantis.hint.HintManager; 13 | import com.peng.library.mantis.hint.OnRetryListener; 14 | import com.peng.library.mantis.mvp.IPresent; 15 | import com.peng.library.mantis.mvp.IViewDelegate; 16 | import com.peng.library.mantis.mvp.MantisFragment; 17 | 18 | 19 | /** 20 | * 这个Fragment主要进行包装,如显示ErrorView,EmptyView,ProgressView,RetryView 21 | * Created by pyt on 2017/6/18. 22 | */ 23 | 24 | public abstract class MantisBaseFragment

extends MantisFragment

implements OnRetryListener { 25 | 26 | private static final String TAG = "MantisBaseFragment"; 27 | 28 | //提示管理类 29 | private HintManager hintManager; 30 | 31 | private DefaultViewDelegate defaultViewDelegate = new DefaultViewDelegate(hintManager); 32 | 33 | 34 | @Override 35 | public IViewDelegate getViewDelegate() { 36 | return defaultViewDelegate.setHintManager(hintManager); 37 | } 38 | 39 | @Nullable 40 | @Override 41 | public final View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 42 | HintConfig.Builder builder = Mantis.getInstance().getHintConfigBuilder(); 43 | View view = onCreateView(inflater, null, savedInstanceState,builder); 44 | HintConfig hintConfig = builder.build(); 45 | //校验是否支持提示 46 | if (!hintConfig.isHintEnable()) { 47 | return view; 48 | } 49 | //支持HintConfig 50 | if (view!=null&&builder != null){ 51 | builder.retryListener(this); 52 | hintManager = new HintManager(builder); 53 | return hintManager.bindFragment(view); 54 | } 55 | return view; 56 | } 57 | 58 | /** 59 | * 给子类复写的方法 60 | * @param inflater 61 | * @param container 62 | * @param savedInstanceState 63 | * @return 64 | */ 65 | public abstract View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState,HintConfig.Builder hintConfigBuilder); 66 | 67 | @Override 68 | public void onRetry(int type, Object tag) { 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/MantisBasePresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand; 2 | 3 | import android.app.Activity; 4 | import android.support.v4.app.Fragment; 5 | 6 | import com.peng.library.mantis.mvp.IView; 7 | import com.peng.library.mantis.mvp.IViewDelegate; 8 | import com.peng.library.mantis.mvp.MantisPresent; 9 | 10 | /** 11 | * 12 | * Created by pyt on 2017/6/18. 13 | */ 14 | 15 | public abstract class MantisBasePresent extends MantisPresent { 16 | 17 | /** 18 | * 提供Activity对象,用于startActivity和Dialog调用使用 19 | * @return 20 | */ 21 | protected Activity getActivity() { 22 | if (view instanceof Activity) { 23 | return (Activity) view; 24 | } else if (view instanceof Fragment) { 25 | return ((Fragment) view).getActivity(); 26 | } 27 | throw new RuntimeException("can't found class "+view==null?"null":view.getClass().getName()); 28 | } 29 | 30 | /** 31 | * 返回一个提示相关的代理类 32 | * @return 33 | */ 34 | protected IViewDelegate getViewDelegate(){ 35 | return getView().getViewDelegate(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/data/MantisDataContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.data; 2 | 3 | import com.peng.library.mantis.mvp.IPresent; 4 | import com.peng.library.mantis.mvp.IView; 5 | 6 | /** 7 | * 单一数据对应的协议(如果使用Data相关模块,必须使用这个协议) 8 | * Created by pyt on 2017/6/22. 9 | */ 10 | 11 | public interface MantisDataContract { 12 | 13 | interface View extends IView{ 14 | void onReceiveData (DATA data); 15 | 16 | void onReceiveError (Throwable error); 17 | } 18 | 19 | interface Present extends IPresent{ 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/data/MantisDataFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.data; 2 | 3 | import com.peng.library.mantis.expand.MantisBaseFragment; 4 | 5 | /** 6 | * 单一数据的Fragment 7 | * Created by pyt on 2017/6/22. 8 | */ 9 | 10 | public abstract class MantisDataFragment extends MantisBaseFragment implements MantisDataContract.View{ 11 | 12 | } 13 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/data/MantisDataPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.data; 2 | 3 | import com.peng.library.mantis.expand.MantisBasePresent; 4 | 5 | import rx.Subscriber; 6 | import rx.subjects.BehaviorSubject; 7 | 8 | /** 9 | * 单一数据的Present 10 | * Created by pyt on 2017/6/22. 11 | */ 12 | 13 | public abstract class MantisDataPresent extends MantisBasePresent implements MantisDataContract.Present{ 14 | 15 | //对初始化时候传入数据的处理 16 | private final BehaviorSubject behaviorSubject = BehaviorSubject.create(); 17 | 18 | //操作View的Subscriber,通过它操作当前View中的数据 19 | private final Subscriber viewSubscriber = new Subscriber() { 20 | @Override 21 | public void onCompleted() { 22 | 23 | } 24 | 25 | @Override 26 | public void onError(Throwable e) { 27 | view.onReceiveError(e); 28 | } 29 | 30 | @Override 31 | public void onNext(DATA data) { 32 | view.onReceiveData(data); 33 | } 34 | }; 35 | 36 | 37 | @Override 38 | public void onCreateView(VIEW view) { 39 | super.onCreateView(view); 40 | DATA dataFromIntent = getDataFromIntent(); 41 | if (dataFromIntent != null) { 42 | behaviorSubject.onNext(dataFromIntent); 43 | } 44 | //绑定当前的生命周期并且开始进行订阅(在onDestroyView的时候取消订阅) 45 | behaviorSubject.compose(bindToLifecycle()).subscribe(viewSubscriber); 46 | } 47 | 48 | /** 49 | * 向View层发送Data 50 | * @param data 51 | */ 52 | protected final void publishData(DATA data) { 53 | viewSubscriber.onNext(data); 54 | } 55 | 56 | /** 57 | * 向View层发送Error 58 | * @param error 59 | */ 60 | protected final void publishError(Throwable error) { 61 | viewSubscriber.onError(error); 62 | } 63 | 64 | /** 65 | * 如果从其他页面跳转过来的,那么可以重写这个方法 66 | * 只要数据不为null,那么就会自动发布了 67 | * @return 68 | */ 69 | protected DATA getDataFromIntent(){ 70 | return null; 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/list/MantisListContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.list; 2 | 3 | import android.support.annotation.LayoutRes; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import com.chad.library.adapter.base.BaseQuickAdapter; 7 | import com.chad.library.adapter.base.BaseViewHolder; 8 | import com.peng.library.mantis.expand.list.link.ListConfig; 9 | import com.peng.library.mantis.expand.refresh.MantisRefreshContract; 10 | import com.peng.library.mantis.mvp.IPresent; 11 | import com.peng.library.mantis.mvp.IView; 12 | 13 | /** 14 | * 列表对应的协议(这个协议,继承刷新的协议) 15 | * Created by pyt on 2017/6/29. 16 | */ 17 | public interface MantisListContract { 18 | 19 | interface View extends MantisRefreshContract.View { 20 | void onConvert (BaseViewHolder holder, DATA data, int position); 21 | 22 | void onReceiveError (Throwable throwable); 23 | } 24 | 25 | interface Present extends MantisRefreshContract.Present { 26 | BaseQuickAdapter getAdapter (); 27 | 28 | void bindRecyclerView (RecyclerView recyclerView, @LayoutRes int itemLayout, ListConfig listConfig); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/list/MantisListFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.list; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.LayoutRes; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import com.peng.library.mantis.Mantis; 12 | import com.peng.library.mantis.expand.list.link.ListConfig; 13 | import com.peng.library.mantis.expand.refresh.MantisRefreshFragment; 14 | import com.peng.library.mantis.expand.refresh.link.RefreshConfig; 15 | import com.peng.library.mantis.hint.HintConfig; 16 | 17 | /** 18 | * 列表类型的fragment 19 | * Created by pyt on 2017/6/29. 20 | */ 21 | 22 | public abstract class MantisListFragment extends MantisRefreshFragment implements MantisListContract.View { 23 | 24 | protected RecyclerView recyclerView; 25 | 26 | 27 | @Override 28 | public final View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState, HintConfig.Builder hintConfigBuilder, RefreshConfig.Builder refreshConfigBuilder) { 29 | ListConfig.Builder listConfigBuilder = getListConfigBuilder(); 30 | if (listConfigBuilder == null) { 31 | throw new IllegalArgumentException("The ListConfigBuilder must not null!"); 32 | } 33 | //获取子类返回的View 34 | View contentView = onCreateView(inflater, container, savedInstanceState,hintConfigBuilder, refreshConfigBuilder, listConfigBuilder); 35 | ListConfig listConfig = listConfigBuilder.build(); 36 | 37 | if (contentView != null) { 38 | //找到它对应的RecyclerView 39 | if (listConfig.getRecyclerView() != null) { 40 | recyclerView = listConfig.getRecyclerView(); 41 | } else if (listConfig.getRecyclerViewId() != ListConfig.RESOURCE_NULL) { 42 | recyclerView = (RecyclerView) contentView.findViewById(listConfig.getRecyclerViewId()); 43 | } else { 44 | throw new IllegalArgumentException("You must set the recyclerView or id of recyclerView in the ListConfig"); 45 | } 46 | setRecyclerViewConfig(recyclerView, listConfig); 47 | return contentView; 48 | } else { 49 | recyclerView = new RecyclerView(getContext()); 50 | ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 51 | recyclerView.setLayoutParams(params); 52 | setRecyclerViewConfig(recyclerView, listConfig); 53 | return recyclerView; 54 | } 55 | } 56 | 57 | /** 58 | * 配置这个RecycleView 59 | * 60 | * @param recyclerView 61 | * @param listConfig 62 | */ 63 | private void setRecyclerViewConfig(RecyclerView recyclerView, ListConfig listConfig) { 64 | //设置Recycle背景色 65 | if (listConfig.getBackgroundColor() != ListConfig.RESOURCE_NULL) { 66 | recyclerView.setBackgroundColor(listConfig.getBackgroundColor()); 67 | } 68 | getPresent().bindRecyclerView(recyclerView, getItemLayout(), listConfig); 69 | } 70 | 71 | @LayoutRes 72 | public abstract int getItemLayout(); 73 | 74 | /** 75 | * 给子类复写的onCreateView 76 | * 77 | * @param inflater 78 | * @param container 79 | * @param savedInstanceState 80 | * @param refreshConfigBuilder 可以自己配置相关刷新的属性 81 | * @param listConfigBuilder 配置加载更多,自定义界面必须指定RecyclerView 82 | * @return 83 | */ 84 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState,HintConfig.Builder hintConfigBuilder, RefreshConfig.Builder refreshConfigBuilder, ListConfig.Builder listConfigBuilder) { 85 | return null; 86 | } 87 | 88 | /** 89 | * 返回当前自定义的Builder 90 | * 91 | * @return 92 | */ 93 | public ListConfig.Builder getListConfigBuilder() { 94 | return Mantis.getInstance().getListConfigBuilder(); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/list/MantisListPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.list; 2 | 3 | import android.support.annotation.LayoutRes; 4 | import android.support.v7.widget.LinearLayoutManager; 5 | import android.support.v7.widget.RecyclerView; 6 | 7 | import com.chad.library.adapter.base.BaseQuickAdapter; 8 | import com.chad.library.adapter.base.BaseViewHolder; 9 | import com.peng.library.mantis.expand.list.link.ListConfig; 10 | import com.peng.library.mantis.expand.list.link.RecyclerViewDivider; 11 | import com.peng.library.mantis.expand.refresh.MantisRefreshPresent; 12 | import com.peng.library.mantis.kit.Kits; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Date; 16 | import java.util.List; 17 | 18 | import rx.Subscriber; 19 | 20 | /** 21 | * ListPresent 22 | * Created by pyt on 2017/6/29. 23 | */ 24 | 25 | public abstract class MantisListPresent 26 | extends MantisRefreshPresent 27 | implements MantisListContract.Present, BaseQuickAdapter.OnItemClickListener, BaseQuickAdapter.RequestLoadMoreListener, BaseQuickAdapter.OnItemLongClickListener { 28 | 29 | private BaseQuickAdapter adapter; 30 | 31 | protected final Subscriber> listSubscriber = new Subscriber>() { 32 | @Override 33 | public void onCompleted() { 34 | 35 | } 36 | 37 | @Override 38 | public void onError(Throwable e) { 39 | getView().onReceiveError(e); 40 | } 41 | 42 | @Override 43 | public void onNext(List datas) { 44 | getView().refreshComplete(); 45 | adapter.disableLoadMoreIfNotFullPage(); 46 | adapter.replaceData(datas); 47 | } 48 | }; 49 | 50 | 51 | @Override 52 | public BaseQuickAdapter getAdapter() { 53 | return adapter; 54 | } 55 | 56 | @Override 57 | public void bindRecyclerView(RecyclerView recyclerView, @LayoutRes int itemLayout, ListConfig listConfig) { 58 | adapter = new BaseQuickAdapter(itemLayout, new ArrayList()) { 59 | @Override 60 | protected void convert(BaseViewHolder helper, DATA item) { 61 | //noinspection unchecked 62 | getView().onConvert(helper, item, helper.getAdapterPosition()); 63 | } 64 | }; 65 | adapter.bindToRecyclerView(recyclerView); 66 | adapter.setOnItemClickListener(this); 67 | adapter.setOnItemLongClickListener(this); 68 | boolean canLoadMore = listConfig.isCanLoadMore(); 69 | if (canLoadMore) { 70 | if (listConfig.getLoadMoreView() == null) { 71 | throw new IllegalArgumentException("you must set you LoadMore View!"); 72 | } 73 | adapter.setOnLoadMoreListener(this, recyclerView); 74 | adapter.setLoadMoreView(listConfig.getLoadMoreView()); 75 | } 76 | adapter.setEnableLoadMore(canLoadMore); 77 | //设置动画 78 | adapter.openLoadAnimation(listConfig.getAnimationType()); 79 | if (listConfig.isHasDivider()) { 80 | if (listConfig.getCustomItemDecoration() != null) { 81 | //设置成用户自己指定的item 82 | recyclerView.addItemDecoration(listConfig.getCustomItemDecoration()); 83 | } else { 84 | //需要将传过来的dp转成px 85 | recyclerView.addItemDecoration(new RecyclerViewDivider(recyclerView.getContext() 86 | , LinearLayoutManager.HORIZONTAL, Kits.Dimens.dpToPxInt(recyclerView.getContext() , listConfig.getDividerHeightDp()), listConfig.getDividerColor())); 87 | } 88 | } 89 | recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext())); 90 | recyclerView.setAdapter(adapter); 91 | } 92 | 93 | /** 94 | * 发布List数据 95 | * 96 | * @param dataList 数据集合 97 | */ 98 | protected void publishListData(List dataList) { 99 | listSubscriber.onNext(dataList); 100 | } 101 | 102 | /** 103 | * 发布错误信息 104 | * 105 | * @param e 错误 106 | */ 107 | protected void pushlishError(Throwable e) { 108 | listSubscriber.onError(e); 109 | } 110 | 111 | /** 112 | * 替换当前Adapter里面的数据 113 | * 114 | * @param datas 数据集合 115 | */ 116 | protected void replaceData(List datas) { 117 | adapter.replaceData(datas); 118 | } 119 | 120 | /** 121 | * 完成loadMore的加载 122 | */ 123 | public void loadMoreComplete() { 124 | adapter.loadMoreComplete(); 125 | } 126 | 127 | /** 128 | * 完成所有loadMore 129 | * 130 | * @param isGone 是否去除LoadView 131 | */ 132 | public void loadMoreEnd(boolean isGone) { 133 | adapter.loadMoreEnd(isGone); 134 | } 135 | 136 | /** 137 | * 完成所有的LoadMore并且显示LoadMoreView 138 | */ 139 | public void loadMoreEnd() { 140 | loadMoreEnd(false); 141 | } 142 | 143 | /** 144 | * 如果调用了loadMoreEnd,如果还想再次记性加载更多的话,必须再次调用这个方法 145 | */ 146 | public void restLoadMore(){ 147 | adapter.notifyLoadMoreToLoading(); 148 | } 149 | 150 | /** 151 | * 加载更多失败,点击之后进行重试 152 | */ 153 | public void loaMoreFail() { 154 | adapter.loadMoreFail(); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/list/link/RecyclerViewDivider.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.list.link; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.Drawable; 9 | import android.support.v4.content.ContextCompat; 10 | import android.support.v7.widget.LinearLayoutManager; 11 | import android.support.v7.widget.RecyclerView; 12 | import android.util.Log; 13 | import android.view.View; 14 | 15 | /** 16 | * Created by pyt on 2017/6/29. 17 | */ 18 | 19 | public class RecyclerViewDivider extends RecyclerView.ItemDecoration { 20 | 21 | private Paint mPaint; 22 | private Drawable mDivider; 23 | private int mDividerHeight = 1;//分割线高度,默认为1px 24 | private int mOrientation;//列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL 25 | private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; 26 | 27 | /** 28 | * 默认分割线:高度为2px,颜色为灰色 29 | * 30 | * @param context 31 | * @param orientation 列表方向 32 | */ 33 | public RecyclerViewDivider(Context context, int orientation) { 34 | if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) { 35 | throw new IllegalArgumentException("请输入正确的参数!"); 36 | } 37 | mOrientation = orientation; 38 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 39 | a.recycle(); 40 | } 41 | 42 | /** 43 | * 自定义分割线 44 | * 45 | * @param context 46 | * @param orientation 列表方向 47 | * @param drawableId 分割线图片 48 | */ 49 | public RecyclerViewDivider(Context context, int orientation, int drawableId) { 50 | this(context, orientation); 51 | mDivider = ContextCompat.getDrawable(context, drawableId); 52 | mDividerHeight = mDivider.getIntrinsicHeight(); 53 | } 54 | 55 | /** 56 | * 自定义分割线 57 | * 58 | * @param context 59 | * @param orientation 列表方向 60 | * @param dividerHeightPx 分割线高度 61 | * @param dividerColor 分割线颜色 62 | */ 63 | public RecyclerViewDivider(Context context, int orientation, int dividerHeightPx, int dividerColor) { 64 | this(context, orientation); 65 | mDividerHeight = dividerHeightPx; 66 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 67 | mPaint.setColor(dividerColor); 68 | mPaint.setStyle(Paint.Style.FILL); 69 | } 70 | 71 | 72 | //获取分割线尺寸 73 | @Override 74 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 75 | super.getItemOffsets(outRect, view, parent, state); 76 | outRect.set(0, 0, 0, mDividerHeight); 77 | } 78 | 79 | //绘制分割线 80 | @Override 81 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 82 | super.onDraw(c, parent, state); 83 | 84 | } 85 | 86 | @Override 87 | public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { 88 | super.onDrawOver(c, parent, state); 89 | if (mOrientation == LinearLayoutManager.VERTICAL) { 90 | drawVertical(c, parent); 91 | } else { 92 | drawHorizontal(c, parent); 93 | } 94 | } 95 | 96 | 97 | //绘制横向 item 分割线 98 | private void drawHorizontal(Canvas canvas, RecyclerView parent) { 99 | final int left = parent.getPaddingLeft(); 100 | final int right = parent.getMeasuredWidth() - parent.getPaddingRight(); 101 | final int childSize = parent.getChildCount(); 102 | //不进行绘制底部的分割线 103 | for (int i = 0; i < childSize; i++) { 104 | final View child = parent.getChildAt(i); 105 | RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams(); 106 | final int top = child.getBottom() + layoutParams.bottomMargin; 107 | final int bottom = top + mDividerHeight; 108 | if (mDivider != null) { 109 | mDivider.setBounds(left, top, right, bottom); 110 | mDivider.draw(canvas); 111 | } 112 | if (mPaint != null) { 113 | canvas.drawRect(left, top, right, bottom, mPaint); 114 | } 115 | } 116 | } 117 | 118 | //绘制纵向 item 分割线 119 | private void drawVertical(Canvas canvas, RecyclerView parent) { 120 | final int top = parent.getPaddingTop(); 121 | final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom(); 122 | final int childSize = parent.getChildCount(); 123 | for (int i = 0; i < childSize; i++) { 124 | final View child = parent.getChildAt(i); 125 | RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams(); 126 | final int left = child.getRight() + layoutParams.rightMargin; 127 | final int right = left + mDividerHeight; 128 | if (mDivider != null) { 129 | mDivider.setBounds(left, top, right, bottom); 130 | mDivider.draw(canvas); 131 | } 132 | if (mPaint != null) { 133 | canvas.drawRect(left, top, right, bottom, mPaint); 134 | } 135 | } 136 | } 137 | } -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/refresh/MantisRefreshContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.refresh; 2 | 3 | import com.peng.library.mantis.mvp.IPresent; 4 | import com.peng.library.mantis.mvp.IView; 5 | 6 | /** 7 | * 刷新数据的协议 8 | * Created by pyt on 2017/6/27. 9 | */ 10 | 11 | public interface MantisRefreshContract { 12 | 13 | interface View extends IView{ 14 | void autoRefresh (); 15 | void refreshComplete (); 16 | boolean isRefreshing (); 17 | } 18 | 19 | interface Present extends IPresent{ 20 | void onRefreshCall (); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/refresh/MantisRefreshPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.refresh; 2 | 3 | import com.peng.library.mantis.expand.MantisBasePresent; 4 | 5 | /** 6 | * 使用刷新的Present 7 | * Created by pyt on 2017/6/27. 8 | */ 9 | 10 | public abstract class MantisRefreshPresent extends MantisBasePresent implements MantisRefreshContract.Present { 11 | 12 | /** 13 | * 将属性完成的方法代理过来 14 | */ 15 | protected void refreshComplete(){ 16 | getView().refreshComplete(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/refresh/link/MantisPtrHandler.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.refresh.link; 2 | 3 | import com.peng.refresh.layout.PtrDefaultHandler; 4 | 5 | /** 6 | * 以后可以在这里进行拓展其他的下拉的状态 7 | * Created by pyt on 2017/6/28. 8 | */ 9 | 10 | public abstract class MantisPtrHandler extends PtrDefaultHandler { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/expand/refresh/link/OnCreateHeaderViewListener.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.expand.refresh.link; 2 | 3 | import android.view.View; 4 | 5 | import com.peng.refresh.layout.PtrFrameLayout; 6 | 7 | /** 8 | * 当创建HeaderView的时候进行调用 9 | * Created by pyt on 2017/6/28. 10 | */ 11 | 12 | public interface OnCreateHeaderViewListener { 13 | View onCreateHeaderView (PtrFrameLayout ptrFrameLayout); 14 | } 15 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/hint/HintConfig.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.hint; 2 | 3 | import android.support.annotation.LayoutRes; 4 | import android.view.View; 5 | 6 | /** 7 | * Created by pyt on 2017/6/18. 8 | */ 9 | 10 | public class HintConfig { 11 | 12 | public static final int NO_LAYOUT_ID = -1; 13 | 14 | private int layoutEmptyId = NO_LAYOUT_ID; 15 | 16 | private int layoutProgressId = NO_LAYOUT_ID; 17 | 18 | private int layoutErrorId = NO_LAYOUT_ID; 19 | 20 | private int layoutNetworkErrorId = NO_LAYOUT_ID; 21 | 22 | private View contentView; 23 | 24 | private OnRetryListener onRetryListener; 25 | 26 | private OnShowErrorViewListener onShowErrorViewListener; 27 | 28 | private boolean hintEnable; 29 | 30 | public int getLayoutEmptyId() { 31 | return layoutEmptyId; 32 | } 33 | 34 | public int getLayoutProgressId() { 35 | return layoutProgressId; 36 | } 37 | 38 | public int getLayoutErrorId() { 39 | return layoutErrorId; 40 | } 41 | 42 | public int getLayoutNetworkErrorId() { 43 | return layoutNetworkErrorId; 44 | } 45 | 46 | public View getContentView() { 47 | return contentView; 48 | } 49 | 50 | public OnRetryListener getOnRetryListener() { 51 | return onRetryListener; 52 | } 53 | 54 | public OnShowErrorViewListener getOnShowErrorViewListener() { 55 | return onShowErrorViewListener; 56 | } 57 | 58 | public boolean isHintEnable() { 59 | return hintEnable; 60 | } 61 | 62 | /** 63 | * HontConfig构建器 64 | */ 65 | public static class Builder implements Cloneable{ 66 | 67 | private int layoutEmptyId = NO_LAYOUT_ID; 68 | 69 | private int layoutProgressId = NO_LAYOUT_ID; 70 | 71 | private int layoutErrorId = NO_LAYOUT_ID; 72 | 73 | private int layoutNetworkErrorId = NO_LAYOUT_ID; 74 | 75 | private View contentView; 76 | 77 | private OnRetryListener onRetryListener; 78 | 79 | private OnShowErrorViewListener onShowErrorViewListener; 80 | 81 | private boolean hintEnable = true; 82 | 83 | public Builder layoutEmptyId(@LayoutRes int layoutId) { 84 | this.layoutEmptyId = layoutId; 85 | return this; 86 | } 87 | 88 | public Builder layoutProgressId(@LayoutRes int layoutId) { 89 | this.layoutProgressId = layoutId; 90 | return this; 91 | } 92 | 93 | public Builder layoutErrorId(@LayoutRes int layoutId) { 94 | this.layoutErrorId = layoutId; 95 | return this; 96 | } 97 | 98 | public Builder layoutNetworkErrorId(@LayoutRes int layoutId) { 99 | this.layoutNetworkErrorId = layoutId; 100 | return this; 101 | } 102 | 103 | public Builder contentView(View view) { 104 | this.contentView = view; 105 | return this; 106 | } 107 | 108 | public Builder retryListener(OnRetryListener retryListener) { 109 | this.onRetryListener = retryListener; 110 | return this; 111 | } 112 | 113 | public Builder showErrorViewListener(OnShowErrorViewListener showErrorViewListener) { 114 | this.onShowErrorViewListener = showErrorViewListener; 115 | return this; 116 | } 117 | 118 | public Builder hintEnable(boolean hintEnable) { 119 | this.hintEnable = hintEnable; 120 | return this; 121 | } 122 | 123 | public HintConfig build() { 124 | HintConfig hintConfig = new HintConfig(); 125 | hintConfig.layoutNetworkErrorId = layoutNetworkErrorId; 126 | hintConfig.layoutEmptyId = layoutEmptyId; 127 | hintConfig.layoutErrorId = layoutErrorId; 128 | hintConfig.layoutProgressId = layoutProgressId; 129 | hintConfig.onRetryListener = onRetryListener; 130 | hintConfig.onShowErrorViewListener = onShowErrorViewListener; 131 | hintConfig.contentView = contentView; 132 | hintConfig.hintEnable = hintEnable; 133 | return hintConfig; 134 | } 135 | 136 | @Override 137 | public Builder clone() { 138 | try { 139 | Builder cloneBuilder = (Builder) super.clone(); 140 | //去除contentView和onRetryListener引用 141 | cloneBuilder.contentView = null; 142 | cloneBuilder.onRetryListener = null; 143 | return cloneBuilder; 144 | } catch (CloneNotSupportedException e) { 145 | e.printStackTrace(); 146 | } 147 | 148 | //如果克隆失败,那么就自己创建 149 | return new Builder() 150 | .layoutProgressId(layoutProgressId) 151 | .layoutNetworkErrorId(layoutNetworkErrorId) 152 | .layoutErrorId(layoutErrorId) 153 | .layoutEmptyId(layoutEmptyId) 154 | .showErrorViewListener(onShowErrorViewListener) 155 | .hintEnable(hintEnable); 156 | } 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/hint/HintManager.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.hint; 2 | 3 | 4 | import android.app.Activity; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | /** 9 | * 相关提示View的管理类 10 | * Created by pyt on 2017/6/18. 11 | */ 12 | 13 | public class HintManager implements IHintView { 14 | 15 | private static final String TAG = "HintManager"; 16 | 17 | private HintConfig.Builder builder; 18 | private HintLayout hintLayout; 19 | 20 | public HintManager(HintConfig.Builder builder) { 21 | this.builder = builder; 22 | if (builder == null) { 23 | throw new IllegalArgumentException("the hintConfig must not null!"); 24 | } 25 | } 26 | 27 | /** 28 | * 绑定Fragment 29 | * 30 | * @param fragmentView 31 | */ 32 | public View bindFragment(View fragmentView) { 33 | //fix:Fragment无法remove(由于替换掉了onCreateView导致) 34 | ViewGroup parent = ((ViewGroup) fragmentView.getParent()); 35 | if (parent != null) { 36 | parent.removeView(fragmentView); 37 | } 38 | hintLayout = new HintLayout(fragmentView.getContext()); 39 | ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 40 | hintLayout.setLayoutParams(params); 41 | this.builder.contentView(fragmentView); 42 | hintLayout.init(this.builder.build()); 43 | return hintLayout; 44 | } 45 | 46 | /** 47 | * 绑定Activity 48 | * 49 | * @param activity 50 | */ 51 | public void bindActivity(Activity activity) { 52 | bindView(activity.findViewById(android.R.id.content)); 53 | } 54 | 55 | /** 56 | * 绑定View 57 | * 58 | * @param contentView 59 | */ 60 | public void bindView(View contentView) { 61 | //找到这个View的父View 62 | ViewGroup parentView = (ViewGroup) contentView.getParent(); 63 | if (parentView == null) { 64 | throw new IllegalArgumentException("bindView: the content's parent view is null,binding failure!"); 65 | } 66 | //获取当前View在ParentView中的位置 67 | int childCount = parentView.getChildCount(); 68 | int contentViewIndex = 0; 69 | for (int i = 0; i < childCount; i++) { 70 | if (parentView.getChildAt(i) == contentView) { 71 | contentViewIndex = i; 72 | } 73 | } 74 | //获取contentView的LayoutParams,并且进行替换 75 | hintLayout = new HintLayout(contentView.getContext()); 76 | ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams(); 77 | parentView.removeView(contentView); 78 | this.builder.contentView(contentView); 79 | hintLayout.init(this.builder.build()); 80 | parentView.addView(hintLayout, contentViewIndex, layoutParams); 81 | } 82 | 83 | @Override 84 | public void showErrorView(String title, String content) { 85 | hintLayout.showErrorView(title, content); 86 | } 87 | 88 | @Override 89 | public void showNetworkErrorView() { 90 | hintLayout.showNetworkErrorView(); 91 | } 92 | 93 | 94 | @Override 95 | public void showEmptyView() { 96 | hintLayout.showEmptyView(); 97 | } 98 | 99 | @Override 100 | public void showProgressView() { 101 | hintLayout.showProgressView(); 102 | } 103 | 104 | @Override 105 | public void showContentView() { 106 | hintLayout.showContentView(); 107 | } 108 | 109 | @Override 110 | public void showErrorView(String title, String content, Object tag) { 111 | hintLayout.showErrorView(title, content, tag); 112 | } 113 | 114 | @Override 115 | public void showNetworkErrorView(Object tag) { 116 | showNetworkErrorView(tag); 117 | } 118 | 119 | @Override 120 | public void showEmptyView(Object tag) { 121 | showEmptyView(tag); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/hint/IHintView.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.hint; 2 | 3 | /** 4 | * 对所支持显示View的抽象,将IViewDeleget的抽象拿过来,这个将来可以单独作为一个SDK 5 | * Created by pyt on 2017/6/18. 6 | */ 7 | 8 | public interface IHintView { 9 | 10 | /** 11 | * 显示错误的界面(可重试) 12 | * @param title 13 | * @param content 14 | */ 15 | void showErrorView (String title, String content); 16 | 17 | /** 18 | * 显示网络错误的界面(可重试) 19 | */ 20 | void showNetworkErrorView (); 21 | 22 | /** 23 | * 显示空的界面(可重试) 24 | */ 25 | void showEmptyView (); 26 | 27 | /** 28 | * 显示进度界面 29 | */ 30 | void showProgressView (); 31 | 32 | /** 33 | * 显示当前的内容View 34 | */ 35 | void showContentView (); 36 | 37 | /** 38 | * 显示错误的界面(可重试) 39 | * @param title 40 | * @param content 41 | */ 42 | void showErrorView (String title, String content, Object tag); 43 | 44 | /** 45 | * 显示网络错误的界面(可重试) 46 | */ 47 | void showNetworkErrorView (Object tag); 48 | 49 | /** 50 | * 显示空的界面(可重试) 51 | */ 52 | void showEmptyView (Object tag); 53 | } 54 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/hint/OnRetryListener.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.hint; 2 | 3 | /** 4 | * Created by pyt on 2017/6/18. 5 | */ 6 | 7 | public interface OnRetryListener { 8 | 9 | /** 10 | * 进行重试的方法 11 | * @param type 12 | * @param tag 13 | */ 14 | void onRetry (int type, Object tag); 15 | } 16 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/hint/OnShowErrorViewListener.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.hint; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * Created by pyt on 2017/6/18. 7 | */ 8 | 9 | public interface OnShowErrorViewListener { 10 | 11 | void onShow (View errorView, String title, String content); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/model/AbsModel.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.model; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by zhuchenxi on 15/6/7. 7 | */ 8 | public abstract class AbsModel { 9 | public static final T getInstance(Class clazz){ 10 | return ModelManager.getInstance(clazz); 11 | } 12 | protected void onAppCreate(Context ctx){} 13 | protected void onAppCreateOnBackThread(Context ctx){} 14 | protected final void runOnBackThread(Runnable runnable){ 15 | ModelManager.runOnBackThread(runnable); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/model/BackThread.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.model; 2 | 3 | import android.os.Handler; 4 | import android.os.HandlerThread; 5 | 6 | /** 7 | * 使用Handler的机制,使用一个指定的子线程执行耗时操作 8 | * Created by Mr.Jude on 2015/7/26. 9 | */ 10 | class BackThread extends HandlerThread { 11 | 12 | private Handler handler; 13 | 14 | public BackThread(String name) { 15 | super(name); 16 | } 17 | 18 | @Override 19 | public synchronized void start() { 20 | super.start(); 21 | if (handler == null) { 22 | handler = new Handler(getLooper()); 23 | } 24 | } 25 | 26 | public void execute(Runnable runnable) { 27 | handler.post(runnable); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/model/ModelManager.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.model; 2 | 3 | import android.content.Context; 4 | import android.content.pm.ApplicationInfo; 5 | import android.content.pm.PackageManager; 6 | import android.support.annotation.NonNull; 7 | import android.util.Log; 8 | 9 | import java.util.HashMap; 10 | 11 | /** 12 | * Created by Mr.Jude on 2015/7/26. 13 | */ 14 | public class ModelManager { 15 | 16 | private final static HashMap,AbsModel> mModelMap = new HashMap<>(); 17 | private final static BackThread mBackThread = new BackThread("Mantis_Model_Manager"); 18 | private static Context mApplication; 19 | 20 | public static void init(final Context ctx){ 21 | mBackThread.start(); 22 | mApplication = ctx; 23 | Class[] models = null; 24 | try { 25 | ApplicationInfo appInfo = ctx.getPackageManager() 26 | .getApplicationInfo(ctx.getPackageName(), 27 | PackageManager.GET_META_DATA); 28 | if (appInfo.metaData == null||appInfo.metaData.getString("MODEL") == null||appInfo.metaData.getString("MODEL").isEmpty()){ 29 | Log.e("Beam","MODEL No Found!Have you declare MODEL in the manifests?"); 30 | return; 31 | } 32 | String modelStr = appInfo.metaData.getString("MODEL").trim(); 33 | String[] modelStrs = modelStr.split(","); 34 | models = new Class[modelStrs.length]; 35 | for (int i = 0; i < modelStrs.length; i++) { 36 | try{ 37 | models[i] = Class.forName(modelStrs[i].trim()); 38 | }catch (ClassNotFoundException e){ 39 | Log.e("Beam",modelStrs[i].trim()+" Class No Found!"); 40 | } 41 | } 42 | } catch (PackageManager.NameNotFoundException e) { 43 | return ; 44 | } 45 | 46 | for (Class m:models) { 47 | createModel(m); 48 | } 49 | for (AbsModel absModel : mModelMap.values()) { 50 | launchModel(absModel); 51 | } 52 | } 53 | 54 | private static T createModel(Class clazz){ 55 | if (clazz!=null && AbsModel.class.isAssignableFrom(clazz)){ 56 | try { 57 | AbsModel instance = clazz.newInstance(); 58 | mModelMap.put(clazz, instance); 59 | return (T) instance; 60 | } catch (InstantiationException e) { 61 | e.printStackTrace(); 62 | } catch (IllegalAccessException e) { 63 | e.printStackTrace(); 64 | } 65 | }else{ 66 | throw new IllegalArgumentException("your model must extends AbsModel"); 67 | } 68 | throw new IllegalArgumentException("your model must extends AbsModel"); 69 | } 70 | 71 | private static void launchModel(@NonNull final AbsModel model){ 72 | model.onAppCreate(mApplication); 73 | //后台调用 74 | mBackThread.execute(new Runnable() { 75 | @Override 76 | public void run() { 77 | model.onAppCreateOnBackThread(mApplication); 78 | } 79 | }); 80 | } 81 | 82 | public static T getInstance(Class clazz) { 83 | if (mModelMap.get(clazz) == null){ 84 | synchronized (clazz){ 85 | launchModel(createModel(clazz)); 86 | } 87 | } 88 | return (T) mModelMap.get(clazz); 89 | } 90 | 91 | static void runOnBackThread(Runnable runnable){ 92 | mBackThread.execute(runnable); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/AbsPresentManager.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | /** 4 | * Created by pyt on 2017/6/17. 5 | */ 6 | 7 | public abstract class AbsPresentManager { 8 | 9 | private static AbsPresentManager instance = new DefaultPresentManager(); 10 | 11 | 12 | public static AbsPresentManager getInstance(){ 13 | return instance; 14 | } 15 | 16 | /** 17 | * 创建Present和生成id的方法 18 | * @param idAndPresent 19 | * @param view 20 | */ 21 | public abstract void create(Object[] idAndPresent,Object view); 22 | 23 | /** 24 | * 根据id获取present 25 | * @param id 26 | * @param

27 | * @return 28 | */ 29 | public abstract

P get(String id); 30 | 31 | /** 32 | * 根据id销毁present 33 | * @param id 34 | */ 35 | public abstract void destroy(String id); 36 | } 37 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/BindPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by pyt on 2017/6/17. 10 | */ 11 | @Retention(value = RetentionPolicy.RUNTIME) 12 | @Target(value = ElementType.TYPE) 13 | public @interface BindPresent { 14 | Class value (); 15 | } 16 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/DefaultPresentManager.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | import android.support.annotation.Size; 4 | 5 | import java.util.HashMap; 6 | 7 | /** 8 | * Created by pyt on 2017/6/17. 9 | */ 10 | 11 | public class DefaultPresentManager extends AbsPresentManager { 12 | 13 | public static final String DIVISION_PRESENT_ID = "_"; 14 | 15 | //缓存Present地方 16 | private HashMap cachePresent = new HashMap(); 17 | 18 | private int nextIndex; 19 | 20 | private StringBuilder idBuilder = new StringBuilder(); 21 | 22 | 23 | @Override 24 | public void create(@Size(2) Object[] idAndPresent, Object view) { 25 | String id = generatePresentId(); 26 | try { 27 | BindPresent bindPresentAnnotation = view.getClass().getAnnotation(BindPresent.class); 28 | Class value = bindPresentAnnotation.value(); 29 | if (value == null) { 30 | throw new IllegalArgumentException("you "+view.getClass().getName()+" must use @BindPresent at the TYPE"); 31 | } 32 | IPresent iPresent = value.newInstance(); 33 | cachePresent.put(id, iPresent); 34 | idAndPresent[0] = id; 35 | idAndPresent[1] = iPresent; 36 | } catch (InstantiationException e) { 37 | e.printStackTrace(); 38 | } catch (IllegalAccessException e) { 39 | e.printStackTrace(); 40 | } 41 | 42 | } 43 | 44 | private String generatePresentId() { 45 | idBuilder.append(nextIndex) 46 | .append(DIVISION_PRESENT_ID) 47 | .append(System.nanoTime()) 48 | .append(DIVISION_PRESENT_ID) 49 | .append(((int) (Math.random() * 1000))); 50 | String generateId = idBuilder.toString(); 51 | idBuilder.setLength(0); 52 | return generateId; 53 | } 54 | 55 | @Override 56 | public

P get(String id) { 57 | return (P) cachePresent.get(id); 58 | } 59 | 60 | @Override 61 | public void destroy(String id) { 62 | cachePresent.remove(id); 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/IPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | 6 | /** 7 | * MVP模式里面所有Present的顶层接口 8 | * Created by pyt on 2017/6/16. 9 | */ 10 | 11 | public interface IPresent { 12 | 13 | /** 14 | * 这个方法在创建这个Present时候调用,但是View没有完全初始化完毕 15 | * @param data 16 | */ 17 | void onCreate (VIEW view, Bundle data); 18 | 19 | /** 20 | * 当Present被从缓存中移除了 21 | */ 22 | void onDestroy (); 23 | 24 | /** 25 | * 当View被创建并且被初始化完毕 26 | * @param view 27 | */ 28 | void onCreateView (VIEW view); 29 | 30 | /** 31 | * 当View被销毁 32 | */ 33 | void onDestroyView (); 34 | 35 | 36 | //所有的生命周期方法 37 | void onStart (); 38 | 39 | void onStop (); 40 | 41 | void onResume (); 42 | 43 | void onPause (); 44 | 45 | void onSave (Bundle data); 46 | 47 | //调用startActivityResult 48 | void onResult (int requestCode, int resultCode, Intent data); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/IView.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | /** 4 | * MVP模式里面所有View的顶层接口 5 | * Created by pyt on 2017/6/16. 6 | */ 7 | 8 | public interface IView { 9 | 10 | PRESENT getPresent (); 11 | 12 | IViewDelegate getViewDelegate (); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/IViewDelegate.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | import com.peng.library.mantis.hint.HintLayout; 4 | import com.peng.library.mantis.hint.IHintView; 5 | 6 | /** 7 | * View的代理类,这个类主要用于View的辅助显示 8 | *

9 | * 相关辅助weidget 10 | * 1.errorView 11 | * 2.emptyView 12 | * 3.progressView 13 | *

14 | * Created by pyt on 2017/6/16. 15 | */ 16 | 17 | public interface IViewDelegate extends IHintView { 18 | 19 | int INDEX_CONTENT = HintLayout.INDEX_CONTENT; 20 | 21 | int INDEX_EMPTY = HintLayout.INDEX_EMPTY; 22 | 23 | int INDEX_PROGRESS = HintLayout.INDEX_PROGRESS; 24 | 25 | int INDEX_ERROR = HintLayout.INDEX_ERROR; 26 | 27 | int INDEX_NETWORK_ERROR = HintLayout.INDEX_NETWORK_ERROR; 28 | } 29 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/MantisFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | 8 | /** 9 | * Fragment作为View层,Activity作为环境层,activity主要用来操作View和Present 10 | * Created by pyt on 2017/6/17. 11 | */ 12 | 13 | public abstract class MantisFragment

extends Fragment implements IView

{ 14 | 15 | private ViewHelper

viewHelper = new ViewHelper<>(); 16 | 17 | @Override 18 | public P getPresent() { 19 | return viewHelper.getPresent(); 20 | } 21 | 22 | 23 | @Override 24 | public void onCreate(@Nullable Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | viewHelper.onCreate(this,savedInstanceState); 27 | } 28 | 29 | @Override 30 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 31 | super.onActivityCreated(savedInstanceState); 32 | viewHelper.onCreateView(this); 33 | } 34 | 35 | @Override 36 | public void onStart() { 37 | super.onStart(); 38 | viewHelper.onStart(); 39 | } 40 | 41 | @Override 42 | public void onStop() { 43 | viewHelper.onStop(); 44 | super.onStop(); 45 | 46 | } 47 | 48 | @Override 49 | public void onResume() { 50 | super.onResume(); 51 | viewHelper.onResume(); 52 | } 53 | 54 | @Override 55 | public void onPause() { 56 | viewHelper.onPause(); 57 | super.onPause(); 58 | } 59 | 60 | @Override 61 | public void onDestroyView() { 62 | viewHelper.onDestroyView(); 63 | super.onDestroyView(); 64 | } 65 | 66 | @Override 67 | public void onDestroy() { 68 | viewHelper.onDestroy(); 69 | super.onDestroy(); 70 | } 71 | 72 | @Override 73 | public void onSaveInstanceState(Bundle outState) { 74 | super.onSaveInstanceState(outState); 75 | viewHelper.onSave(outState); 76 | } 77 | 78 | @Override 79 | public void onActivityResult(int requestCode, int resultCode, Intent data) { 80 | super.onActivityResult(requestCode, resultCode, data); 81 | viewHelper.onResult(requestCode,resultCode,data); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/MantisPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.CheckResult; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.trello.rxlifecycle.LifecycleProvider; 9 | import com.trello.rxlifecycle.LifecycleTransformer; 10 | import com.trello.rxlifecycle.RxLifecycle; 11 | 12 | import rx.Observable; 13 | import rx.subjects.BehaviorSubject; 14 | 15 | 16 | /** 17 | 18 | * Created by pyt on 2017/6/17. 19 | */ 20 | public abstract class MantisPresent implements IPresent, LifecycleProvider { 21 | 22 | protected V view; 23 | 24 | private final BehaviorSubject lifecycleSubject = BehaviorSubject.create(); 25 | 26 | /** 27 | * Rxjava的调用绑定Present的生命周期 28 | * 说明: 如果你调用bindToLifecycle()出于onCreate状态,那么在onDestroy状态 29 | * 就会完成这种绑定状态,自动调用onComplete()方法完成解绑的动作 30 | * 31 | * @param 32 | * @return 33 | */ 34 | @NonNull 35 | @Override 36 | @CheckResult 37 | public LifecycleTransformer bindToLifecycle() { 38 | return RxLifePresent.bindPresent(lifecycleSubject); 39 | } 40 | 41 | @NonNull 42 | @Override 43 | public Observable lifecycle() { 44 | return lifecycleSubject.asObservable(); 45 | } 46 | 47 | /** 48 | * 指定生命周期进行解绑(如果到了绑定生命周期方法的执行,那么如果还没有取消绑定,那么这里会自动完成,然后取消绑定) 49 | * @param event 50 | * @param 51 | * @return 52 | */ 53 | @NonNull 54 | @Override 55 | public LifecycleTransformer bindUntilEvent(@NonNull PresentEvent event) { 56 | return RxLifecycle.bindUntilEvent(lifecycleSubject, event); 57 | } 58 | 59 | @Override 60 | public void onCreate(V view,Bundle data) { 61 | lifecycleSubject.onNext(PresentEvent.CREATE); 62 | } 63 | 64 | @Override 65 | public void onDestroy() { 66 | lifecycleSubject.onNext(PresentEvent.DESTROY); 67 | } 68 | 69 | @Override 70 | public void onCreateView(V view) { 71 | this.view = view; 72 | lifecycleSubject.onNext(PresentEvent.CREATE_VIEW); 73 | } 74 | 75 | protected V getView(){ 76 | return view; 77 | } 78 | 79 | @Override 80 | public void onDestroyView() { 81 | lifecycleSubject.onNext(PresentEvent.DESTROY_VIEW); 82 | } 83 | 84 | @Override 85 | public void onStart() { 86 | lifecycleSubject.onNext(PresentEvent.START); 87 | } 88 | 89 | @Override 90 | public void onStop() { 91 | lifecycleSubject.onNext(PresentEvent.STOP); 92 | } 93 | 94 | @Override 95 | public void onResume() { 96 | lifecycleSubject.onNext(PresentEvent.RESUME); 97 | } 98 | 99 | @Override 100 | public void onPause() { 101 | lifecycleSubject.onNext(PresentEvent.PAUSE); 102 | } 103 | 104 | @Override 105 | public void onSave(Bundle data) { 106 | 107 | } 108 | 109 | @Override 110 | public void onResult(int requestCode, int resultCode, Intent data) { 111 | 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/PresentEvent.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | /** 4 | * Created by pyt on 2017/6/17. 5 | */ 6 | 7 | public enum PresentEvent { 8 | CREATE, 9 | START, 10 | RESUME, 11 | PAUSE, 12 | STOP, 13 | DESTROY, 14 | CREATE_VIEW, 15 | DESTROY_VIEW 16 | } 17 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/RxLifePresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | import android.support.annotation.CheckResult; 4 | import android.support.annotation.NonNull; 5 | import android.util.Log; 6 | 7 | import com.trello.rxlifecycle.LifecycleTransformer; 8 | import com.trello.rxlifecycle.OutsideLifecycleException; 9 | import com.trello.rxlifecycle.RxLifecycle; 10 | 11 | import rx.Observable; 12 | import rx.functions.Func1; 13 | 14 | 15 | /** 16 | * 用于对Present的生命周期的管理,防止在使用Rxjava的时候内存泄露 17 | * Created by pyt on 2017/6/17. 18 | */ 19 | 20 | public class RxLifePresent { 21 | 22 | private static final String TAG = "RxLifePresent"; 23 | 24 | // Figures out which corresponding next lifecycle event in which to unsubscribe, for Present 25 | private static final Func1 PRESENT_LIFECYCLE = 26 | new Func1() { 27 | @Override 28 | public PresentEvent call(PresentEvent lastEvent) { 29 | Log.i(TAG, "RxLifePresent-->" + lastEvent); 30 | switch (lastEvent) { 31 | case CREATE: 32 | return PresentEvent.DESTROY; 33 | case CREATE_VIEW: 34 | return PresentEvent.DESTROY_VIEW; 35 | case START: 36 | return PresentEvent.STOP; 37 | case RESUME: 38 | return PresentEvent.PAUSE; 39 | case PAUSE: 40 | return PresentEvent.STOP; 41 | case STOP: 42 | return PresentEvent.DESTROY; 43 | case DESTROY_VIEW: 44 | return PresentEvent.DESTROY; 45 | case DESTROY: 46 | throw new OutsideLifecycleException("Cannot bind to Activity lifecycle when outside of it."); 47 | default: 48 | throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented"); 49 | } 50 | } 51 | }; 52 | 53 | 54 | @NonNull 55 | @CheckResult 56 | public static LifecycleTransformer bindPresent(@NonNull final Observable lifecycle) { 57 | return RxLifecycle.bind(lifecycle, PRESENT_LIFECYCLE); 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /UIModule/src/main/java/com/peng/library/mantis/mvp/ViewHelper.java: -------------------------------------------------------------------------------- 1 | package com.peng.library.mantis.mvp; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.text.TextUtils; 6 | 7 | /** 8 | * 将View中的生命周期方法全部代理到Present 9 | * Created by pyt on 2017/6/17. 10 | */ 11 | 12 | public class ViewHelper

{ 13 | 14 | //标记位 15 | public static final String KEY_PRESENT_ID = "KEY_PRESENT_ID"; 16 | 17 | private P present; 18 | 19 | private String presentId; 20 | 21 | public void onCreate(V view, Bundle data) { 22 | if (data == null || TextUtils.isEmpty(data.getString(KEY_PRESENT_ID))) { 23 | createPresent(view,data); 24 | } else { 25 | presentId = data.getString(KEY_PRESENT_ID); 26 | IPresent iPresent = AbsPresentManager.getInstance().get(presentId); 27 | if (iPresent == null) { 28 | createPresent(view,data); 29 | } 30 | } 31 | } 32 | 33 | public P getPresent(){ 34 | return present; 35 | } 36 | 37 | public void onDestroy() { 38 | if (checkPresentIsNotNull()) { 39 | present.onDestroy(); 40 | AbsPresentManager.getInstance().destroy(presentId); 41 | } 42 | } 43 | 44 | public void onCreateView(IView view) { 45 | if (checkPresentIsNotNull()) { 46 | present.onCreateView(view); 47 | } 48 | } 49 | 50 | public void onDestroyView() { 51 | if (checkPresentIsNotNull()) { 52 | present.onDestroyView(); 53 | } 54 | } 55 | 56 | public void onStart() { 57 | if (checkPresentIsNotNull()) { 58 | present.onStart(); 59 | } 60 | } 61 | 62 | public void onStop() { 63 | if (checkPresentIsNotNull()) { 64 | present.onStop(); 65 | } 66 | } 67 | 68 | public void onResume() { 69 | if (checkPresentIsNotNull()) { 70 | present.onResume(); 71 | } 72 | } 73 | 74 | public void onPause() { 75 | if (checkPresentIsNotNull()) { 76 | present.onPause(); 77 | } 78 | } 79 | 80 | public void onSave(Bundle data) { 81 | if (checkPresentIsNotNull()) { 82 | data.putString(KEY_PRESENT_ID, presentId); 83 | present.onSave(data); 84 | } 85 | } 86 | 87 | public void onResult(int requestCode, int resultCode, Intent data) { 88 | present.onResult(requestCode,resultCode,data); 89 | } 90 | 91 | private boolean checkPresentIsNotNull(){ 92 | return present != null; 93 | } 94 | 95 | private void createPresent(V view, Bundle data) { 96 | Object[] idAndPresent = new Object[2]; 97 | AbsPresentManager.getInstance().create(idAndPresent, view); 98 | if (!TextUtils.isEmpty((String) idAndPresent[0]) && idAndPresent[1] != null) { 99 | presentId = (String) idAndPresent[0]; 100 | present = (P) idAndPresent[1]; 101 | present.onCreate(view,data); 102 | } 103 | } 104 | 105 | 106 | } 107 | -------------------------------------------------------------------------------- /UIModule/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /UIModule/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CoreModule 3 | 4 | -------------------------------------------------------------------------------- /UIModule/src/test/java/com/peng/coremodule/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.peng.coremodule; 2 | 3 | import com.peng.library.mantis.hint.HintConfig; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | // @Test 14 | // public void addition_isCorrect() throws Exception { 15 | // assertEquals(4, 2 + 2); 16 | // } 17 | // 18 | 19 | @Test 20 | public void test_HintConfigBuilder() throws Exception { 21 | HintConfig.Builder builder = new HintConfig.Builder().layoutEmptyId(1).layoutErrorId(2).layoutNetworkErrorId(3).layoutProgressId(4); 22 | HintConfig.Builder clone = builder.clone(); 23 | System.out.println("Builder old -> " + Integer.toHexString(builder.hashCode()) + " new -> " + Integer.toHexString(clone.hashCode())); 24 | System.out.println("HintConfig old -> " + Integer.toHexString(builder.build().hashCode()) + " new -> " + Integer.toHexString(clone.build().hashCode())); 25 | } 26 | 27 | 28 | } -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'me.tatarka.retrolambda' 3 | apply plugin: 'org.greenrobot.greendao' // apply plugin 4 | 5 | android { 6 | compileSdkVersion 25 7 | buildToolsVersion "25.0.2" 8 | defaultConfig { 9 | applicationId "com.peng.mantis" 10 | minSdkVersion rootProject.ext.android["minSdkVersion"] 11 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 12 | versionCode 1 13 | versionName "1.0" 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | javaCompileOptions { 16 | annotationProcessorOptions { 17 | arguments = [ moduleName : project.getName() ] 18 | } 19 | } 20 | } 21 | 22 | greendao { 23 | schemaVersion 1 24 | targetGenDir "src/main/java" 25 | daoPackage "com.peng.mantis.model.db.greendao" 26 | generateTests false 27 | } 28 | 29 | //天气 30 | buildTypes { 31 | release { 32 | minifyEnabled false 33 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 34 | } 35 | } 36 | 37 | //去除Warning:Conflict with dependency 'com.google.code.findbugs:jsr305 38 | 39 | configurations.all { 40 | resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9' 41 | } 42 | 43 | compileOptions { 44 | sourceCompatibility JavaVersion.VERSION_1_8 45 | targetCompatibility JavaVersion.VERSION_1_8 46 | } 47 | 48 | 49 | } 50 | 51 | dependencies { 52 | compile fileTree(include: ['*.jar'], dir: 'libs') 53 | testCompile 'junit:junit:4.12' 54 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 55 | exclude group: 'com.android.support', module: 'support-annotations' 56 | }) 57 | compile project(':UIModule') 58 | //apt生成类,必须在工程里面再次加一遍 59 | compile rootProject.ext.dependencies["butterknife"] 60 | annotationProcessor rootProject.ext.dependencies["butterknife-compiler"] 61 | annotationProcessor rootProject.ext.dependencies["arouter-compiler"] 62 | debugCompile rootProject.ext.dependencies["leakCanary-debug"] 63 | releaseCompile rootProject.ext.dependencies["leakCanary-release"] 64 | testCompile rootProject.ext.dependencies["leakCanary-test"] 65 | testCompile rootProject.ext.dependencies["appcompat-v7"] 66 | testCompile rootProject.ext.dependencies["constraint-layout"] 67 | compile project(':OpenSourceLibrary') 68 | compile project(':CoreModule') 69 | } 70 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\Android\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 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/TestApplication.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.graphics.Color; 6 | import android.widget.TextView; 7 | 8 | import com.alibaba.android.arouter.launcher.ARouter; 9 | import com.chad.library.adapter.base.loadmore.SimpleLoadMoreView; 10 | import com.facebook.stetho.Stetho; 11 | import com.peng.library.mantis.Mantis; 12 | import com.peng.library.mantis.expand.list.link.ListConfig; 13 | import com.peng.library.mantis.expand.refresh.link.RefreshConfig; 14 | import com.peng.library.mantis.hint.HintConfig; 15 | import com.peng.library.mantis.kit.Kits; 16 | import com.peng.mantis.model.db.MantisDBManager; 17 | import com.peng.mantis.model.http.ApiClient; 18 | import com.peng.mantis.model.http.ApiConstants; 19 | import com.peng.mantis.model.http.service.MantisNetApi; 20 | import com.peng.refresh.layout.PtrFrameLayout; 21 | import com.peng.refresh.layout.header.StoreHouseHeader; 22 | import com.squareup.leakcanary.LeakCanary; 23 | 24 | /** 25 | * Created by pyt on 2017/6/17. 26 | */ 27 | 28 | public class TestApplication extends Application { 29 | 30 | private static TestApplication instance; 31 | 32 | private MantisNetApi mantisNetApi; 33 | 34 | @Override 35 | protected void attachBaseContext(Context base) { 36 | super.attachBaseContext(base); 37 | ARouter.init(this); 38 | } 39 | 40 | @Override 41 | public void onCreate() { 42 | super.onCreate(); 43 | instance = this; 44 | PtrFrameLayout.DEBUG = false; 45 | if (LeakCanary.isInAnalyzerProcess(this)) { 46 | return; 47 | } 48 | LeakCanary.install(this); 49 | Mantis.getInstance().init(this); 50 | //设置提示的Builder 51 | Mantis.getInstance().setHintConfigBuilder(getDefaultHintConfigBuilder()); 52 | Mantis.getInstance().setRefreshConfigBuilder(getDefaultRefreshBuilder()); 53 | Mantis.getInstance().setListConfigBuilder(getDefaultListBuilder()); 54 | Stetho.initializeWithDefaults(this); 55 | MantisDBManager.getInstance().init(this); 56 | } 57 | 58 | /** 59 | * 获取默认的列表配置Builder 60 | * @return 61 | */ 62 | public ListConfig.Builder getDefaultListBuilder(){ 63 | ListConfig.Builder builder = new ListConfig.Builder(); 64 | builder.canLoadMore(false).loadMoreView(new SimpleLoadMoreView()); 65 | return builder; 66 | } 67 | 68 | /** 69 | * 获取默认的刷新配置的Builder 70 | * @return 71 | */ 72 | public RefreshConfig.Builder getDefaultRefreshBuilder(){ 73 | RefreshConfig.Builder builder = new RefreshConfig.Builder(); 74 | builder.onCreateHeaderViewListener(ptrFrameLayout -> { 75 | StoreHouseHeader header = new StoreHouseHeader(this); 76 | int padding = ((int) Kits.Dimens.dpToPx(this, 20)); 77 | header.setPadding(0,padding , 0,padding); 78 | header.initWithString("PENG YUAN TAO"); 79 | return header; 80 | }).headerBackgroundColor(Color.BLACK); 81 | return builder; 82 | } 83 | 84 | /** 85 | * 获取默认的提示配置的Builder 86 | * @return 87 | */ 88 | private HintConfig.Builder getDefaultHintConfigBuilder () { 89 | HintConfig.Builder builder = new HintConfig.Builder(); 90 | builder.layoutEmptyId(R.layout.hint_empty) 91 | .layoutProgressId(R.layout.hint_progress) 92 | .layoutErrorId(R.layout.hint_error) 93 | .showErrorViewListener((errorView, title, content) -> { 94 | ((TextView) errorView.findViewById(R.id.tv_error_title)).setText(title); 95 | ((TextView) errorView.findViewById(R.id.tv_error_content)).setText(content); 96 | }) 97 | .layoutNetworkErrorId(R.layout.hint_net_error); 98 | return builder; 99 | } 100 | 101 | public static TestApplication getApplication(){ 102 | return instance; 103 | } 104 | 105 | public MantisNetApi getMantisNetApi (){ 106 | if (mantisNetApi == null) { 107 | mantisNetApi = ApiClient.createApiService(ApiConstants.API_BENGUO_NET_URL, MantisNetApi.class); 108 | } 109 | return mantisNetApi; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.activity; 2 | 3 | import android.Manifest; 4 | import android.os.Bundle; 5 | import android.support.v4.app.ActivityCompat; 6 | import android.support.v7.app.AppCompatActivity; 7 | 8 | import com.peng.mantis.R; 9 | import com.peng.mantis.view.fragment.TestDataFragment; 10 | import com.peng.mantis.view.fragment.TestHintFragment; 11 | import com.peng.mantis.view.fragment.TestHttpFragment; 12 | import com.peng.mantis.view.fragment.TestListFragment; 13 | import com.peng.mantis.view.fragment.TestRefreshFragment; 14 | import com.peng.mantis.view.fragment.TestRepositoryFragment; 15 | 16 | import butterknife.ButterKnife; 17 | import butterknife.OnClick; 18 | 19 | public class MainActivity extends AppCompatActivity { 20 | 21 | private static final String TAG = "MainActivity"; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_main); 27 | ButterKnife.bind(this); 28 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 11); 29 | } 30 | 31 | @OnClick(R.id.btn_skip_data_test) 32 | public void onDataTest() { 33 | TestActivity.start(this, TestDataFragment.class); 34 | } 35 | 36 | @OnClick(R.id.btn_skip_hint_test) 37 | public void onHintTest() { 38 | TestActivity.start(this, TestHintFragment.class); 39 | } 40 | 41 | @OnClick(R.id.btn_skip_refresh_test) 42 | public void onRefreshTest() { 43 | TestActivity.start(this, TestRefreshFragment.class); 44 | } 45 | 46 | @OnClick(R.id.btn_skip_list_test) 47 | public void onListTest() { 48 | TestActivity.start(this, TestListFragment.class); 49 | } 50 | 51 | 52 | @OnClick(R.id.btn_skip_http_test) 53 | public void onClick() { 54 | TestActivity.start(this, TestHttpFragment.class); 55 | } 56 | 57 | @OnClick(R.id.btn_skip_repository_test) 58 | public void onRepository() { 59 | TestActivity.start(this, TestRepositoryFragment.class); 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/activity/TestActivity.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.activity; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.app.FragmentManager; 8 | import android.support.v7.app.AppCompatActivity; 9 | 10 | import com.peng.mantis.R; 11 | 12 | /** 13 | * 如果一个Activity里面只有一个Fragment,那么只要通过这个包装的Activity进行启动就行。 14 | */ 15 | public class TestActivity extends AppCompatActivity { 16 | 17 | public static final String FLAG_ACTIVITY = "FLAG_ACTIVITY"; 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_test); 23 | addFragmentToContainer(); 24 | } 25 | 26 | private void addFragmentToContainer() { 27 | FragmentManager supportFragmentManager = getSupportFragmentManager(); 28 | try { 29 | supportFragmentManager.beginTransaction().replace(R.id.fragment_container, (Fragment) getFragmentClz().newInstance(), FLAG_ACTIVITY).commitNow(); 30 | } catch (InstantiationException e) { 31 | e.printStackTrace(); 32 | } catch (IllegalAccessException e) { 33 | e.printStackTrace(); 34 | } 35 | 36 | } 37 | 38 | public Class getFragmentClz(){ 39 | return (Class) getIntent().getSerializableExtra(FLAG_ACTIVITY); 40 | } 41 | 42 | public static void start(Context context, Class fragmentClz) { 43 | Intent intent = new Intent(context, TestActivity.class); 44 | intent.putExtra(FLAG_ACTIVITY, fragmentClz); 45 | context.startActivity(intent); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/activity/TestDataActivity.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.activity; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | import com.peng.mantis.R; 7 | 8 | public class TestDataActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_test_data); 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/activity/TestHintActivity.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.activity; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | import com.peng.mantis.R; 7 | 8 | public class TestHintActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_test_hint); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/activity/TestRefreshActivity.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.activity; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | import com.peng.mantis.R; 7 | 8 | public class TestRefreshActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_test_refresh); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/contract/TestDataContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.contract; 2 | 3 | import com.peng.library.mantis.expand.data.MantisDataContract; 4 | 5 | /** 6 | * 7 | * Created by pyt on 2017/6/23. 8 | */ 9 | public interface TestDataContract{ 10 | 11 | interface View extends MantisDataContract.View{ 12 | void toast (String msg); 13 | } 14 | 15 | interface Present extends MantisDataContract.Present{ 16 | 17 | void login (String account, String password); 18 | 19 | void logout (); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/contract/TestHintContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.contract; 2 | 3 | import com.peng.library.mantis.expand.data.MantisDataContract; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 测试提示框架的协议 9 | * Created by pyt on 2017/6/26. 10 | */ 11 | 12 | public interface TestHintContract { 13 | 14 | 15 | interface View extends MantisDataContract.View{ 16 | } 17 | 18 | interface Present extends MantisDataContract.Present{ 19 | 20 | void reload (); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/contract/TestHttpContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.contract; 2 | 3 | import com.peng.library.mantis.expand.data.MantisDataContract; 4 | 5 | /** 6 | * 测试网络的协议 7 | * Created by pyt on 2017/7/5. 8 | */ 9 | 10 | public interface TestHttpContract { 11 | 12 | 13 | interface View extends MantisDataContract.View{ 14 | 15 | } 16 | 17 | interface Present extends MantisDataContract.Present{ 18 | void startGetRequest (); 19 | 20 | void startPostRequest (); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/contract/TestListContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.contract; 2 | 3 | import com.peng.library.mantis.expand.list.MantisListContract; 4 | 5 | /** 6 | * Created by pyt on 2017/6/29. 7 | */ 8 | 9 | public interface TestListContract { 10 | 11 | interface View extends MantisListContract.View{ 12 | 13 | } 14 | 15 | interface Present extends MantisListContract.Present { 16 | 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/contract/TestRefreshContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.contract; 2 | 3 | import com.peng.library.mantis.expand.refresh.MantisRefreshContract; 4 | 5 | /** 6 | * Created by pyt on 2017/6/28. 7 | */ 8 | 9 | public interface TestRefreshContract { 10 | 11 | 12 | interface View extends MantisRefreshContract.View{ 13 | void onReceiveData (String data); 14 | 15 | void onReceiveError (Throwable error); 16 | } 17 | 18 | interface Present extends MantisRefreshContract.Present{ 19 | void giveMeData (); 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/contract/TestRepositoryContract.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.contract; 2 | 3 | import com.peng.library.mantis.expand.data.MantisDataContract; 4 | import com.peng.library.mantis.expand.refresh.MantisRefreshContract; 5 | import com.peng.mantis.model.db.entity.TodayWeather; 6 | 7 | /** 8 | * 测试将Repository对象协议 9 | * Created by pyt on 2017/7/11. 10 | */ 11 | 12 | public interface TestRepositoryContract { 13 | 14 | interface View extends MantisRefreshContract.View{ 15 | void setTodayWeather (TodayWeather todayWeather); 16 | } 17 | 18 | interface Present extends MantisRefreshContract.Present { 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/db/MantisDBHelper.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.db; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | 6 | import com.peng.android.coremodule.db.GreenDBUpdateHelper; 7 | import com.peng.mantis.model.db.greendao.DaoMaster; 8 | import com.peng.mantis.model.db.greendao.TodayWeatherDao; 9 | 10 | 11 | /** 12 | * 数据库升级主要类 13 | * Created by pyt on 2017/7/11. 14 | */ 15 | 16 | class MantisDBHelper extends DaoMaster.OpenHelper { 17 | 18 | 19 | public MantisDBHelper(Context context, String name) { 20 | super(context, name); 21 | } 22 | 23 | public MantisDBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) { 24 | super(context, name, factory); 25 | } 26 | 27 | @Override 28 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 29 | //自动升级 30 | GreenDBUpdateHelper.migrate(db, TodayWeatherDao.class); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/db/MantisDBManager.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.db; 2 | 3 | import android.content.Context; 4 | 5 | import com.peng.mantis.model.db.greendao.DaoMaster; 6 | import com.peng.mantis.model.db.greendao.DaoSession; 7 | import com.peng.refresh.layout.header.MaterialHeader; 8 | 9 | 10 | /** 11 | * 数据库初始化管理类 12 | * Created by pyt on 2017/7/11. 13 | */ 14 | 15 | public class MantisDBManager { 16 | 17 | public static final String DB_WEATHER_NAME = "today_weather"; 18 | 19 | private static MantisDBManager instance = new MantisDBManager(); 20 | 21 | private DaoSession weatherDaoSeeeion; 22 | 23 | private MantisDBManager() { 24 | 25 | } 26 | 27 | public static MantisDBManager getInstance() { 28 | return instance; 29 | } 30 | 31 | /** 32 | * 初始化所有的数据库 33 | * 34 | * @param context 35 | */ 36 | public void init(Context context) { 37 | MantisDBHelper mantisDBHelper = new MantisDBHelper(context.getApplicationContext(), DB_WEATHER_NAME); 38 | DaoMaster daoMaster = new DaoMaster(mantisDBHelper.getWritableDb()); 39 | weatherDaoSeeeion = daoMaster.newSession(); 40 | } 41 | 42 | public DaoSession getTodayDaoSession() { 43 | return weatherDaoSeeeion; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/db/entity/TodayWeather.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.db.entity; 2 | 3 | 4 | import org.greenrobot.greendao.annotation.Entity; 5 | import org.greenrobot.greendao.annotation.Unique; 6 | 7 | import java.util.Date; 8 | import org.greenrobot.greendao.annotation.Generated; 9 | 10 | /** 11 | * 今天天气 12 | * Created by pyt on 2017/7/11. 13 | */ 14 | @Entity 15 | public class TodayWeather { 16 | 17 | /** 18 | * date : 11日星期二 19 | * high : 高温 35℃ 20 | * fengli : 微风级 21 | * low : 低温 28℃ 22 | * fengxiang : 南风 23 | * type : 多云 24 | */ 25 | @Unique 26 | private String city; 27 | private String todayDate; 28 | private String date; 29 | private String high; 30 | private String fengli; 31 | private String low; 32 | private String fengxiang; 33 | private String type; 34 | private long cacheTime; 35 | @Generated(hash = 871522415) 36 | public TodayWeather(String city, String todayDate, String date, String high, 37 | String fengli, String low, String fengxiang, String type, 38 | long cacheTime) { 39 | this.city = city; 40 | this.todayDate = todayDate; 41 | this.date = date; 42 | this.high = high; 43 | this.fengli = fengli; 44 | this.low = low; 45 | this.fengxiang = fengxiang; 46 | this.type = type; 47 | this.cacheTime = cacheTime; 48 | } 49 | @Generated(hash = 940679256) 50 | public TodayWeather() { 51 | } 52 | public String getCity() { 53 | return this.city; 54 | } 55 | public void setCity(String city) { 56 | this.city = city; 57 | } 58 | public String getTodayDate() { 59 | return this.todayDate; 60 | } 61 | public void setTodayDate(String todayDate) { 62 | this.todayDate = todayDate; 63 | } 64 | public String getDate() { 65 | return this.date; 66 | } 67 | public void setDate(String date) { 68 | this.date = date; 69 | } 70 | public String getHigh() { 71 | return this.high; 72 | } 73 | public void setHigh(String high) { 74 | this.high = high; 75 | } 76 | public String getFengli() { 77 | return this.fengli; 78 | } 79 | public void setFengli(String fengli) { 80 | this.fengli = fengli; 81 | } 82 | public String getLow() { 83 | return this.low; 84 | } 85 | public void setLow(String low) { 86 | this.low = low; 87 | } 88 | public String getFengxiang() { 89 | return this.fengxiang; 90 | } 91 | public void setFengxiang(String fengxiang) { 92 | this.fengxiang = fengxiang; 93 | } 94 | public String getType() { 95 | return this.type; 96 | } 97 | public void setType(String type) { 98 | this.type = type; 99 | } 100 | public long getCacheTime() { 101 | return this.cacheTime; 102 | } 103 | public void setCacheTime(long cacheTime) { 104 | this.cacheTime = cacheTime; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/db/entity/adapter/TodayWeatherAdapter.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.db.entity.adapter; 2 | 3 | import com.peng.library.mantis.kit.Kits; 4 | import com.peng.mantis.model.db.entity.TodayWeather; 5 | import com.peng.mantis.model.http.entity.Weather; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by pyt on 2017/7/11. 11 | */ 12 | 13 | public class TodayWeatherAdapter { 14 | 15 | private Weather weather; 16 | 17 | public TodayWeatherAdapter(Weather weather) { 18 | this.weather = weather; 19 | } 20 | 21 | public TodayWeather getTodayWeather(String city) { 22 | List forecast = weather.getData().getForecast(); 23 | if (forecast != null && !forecast.isEmpty() && forecast.size() != 0) { 24 | Weather.DataBean.ForecastBean forecastBean = forecast.get(0); 25 | TodayWeather todayWeather = new TodayWeather(); 26 | todayWeather.setCacheTime(System.currentTimeMillis()); 27 | todayWeather.setCity(weather.getDesc()); 28 | todayWeather.setDate(Kits.Date.getYmd(System.currentTimeMillis())); 29 | todayWeather.setFengli(forecastBean.getFengli()); 30 | todayWeather.setFengxiang(forecastBean.getFengxiang()); 31 | todayWeather.setHigh(forecastBean.getHigh()); 32 | todayWeather.setLow(forecastBean.getLow()); 33 | todayWeather.setCity(city); 34 | todayWeather.setType(forecastBean.getType()); 35 | return todayWeather; 36 | } 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/db/greendao/DaoMaster.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.db.greendao; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteDatabase.CursorFactory; 6 | import android.util.Log; 7 | 8 | import org.greenrobot.greendao.AbstractDaoMaster; 9 | import org.greenrobot.greendao.database.StandardDatabase; 10 | import org.greenrobot.greendao.database.Database; 11 | import org.greenrobot.greendao.database.DatabaseOpenHelper; 12 | import org.greenrobot.greendao.identityscope.IdentityScopeType; 13 | 14 | 15 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. 16 | /** 17 | * Master of DAO (schema version 1): knows all DAOs. 18 | */ 19 | public class DaoMaster extends AbstractDaoMaster { 20 | public static final int SCHEMA_VERSION = 1; 21 | 22 | /** Creates underlying database table using DAOs. */ 23 | public static void createAllTables(Database db, boolean ifNotExists) { 24 | TodayWeatherDao.createTable(db, ifNotExists); 25 | } 26 | 27 | /** Drops underlying database table using DAOs. */ 28 | public static void dropAllTables(Database db, boolean ifExists) { 29 | TodayWeatherDao.dropTable(db, ifExists); 30 | } 31 | 32 | /** 33 | * WARNING: Drops all table on Upgrade! Use only during development. 34 | * Convenience method using a {@link DevOpenHelper}. 35 | */ 36 | public static DaoSession newDevSession(Context context, String name) { 37 | Database db = new DevOpenHelper(context, name).getWritableDb(); 38 | DaoMaster daoMaster = new DaoMaster(db); 39 | return daoMaster.newSession(); 40 | } 41 | 42 | public DaoMaster(SQLiteDatabase db) { 43 | this(new StandardDatabase(db)); 44 | } 45 | 46 | public DaoMaster(Database db) { 47 | super(db, SCHEMA_VERSION); 48 | registerDaoClass(TodayWeatherDao.class); 49 | } 50 | 51 | public DaoSession newSession() { 52 | return new DaoSession(db, IdentityScopeType.Session, daoConfigMap); 53 | } 54 | 55 | public DaoSession newSession(IdentityScopeType type) { 56 | return new DaoSession(db, type, daoConfigMap); 57 | } 58 | 59 | /** 60 | * Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} - 61 | */ 62 | public static abstract class OpenHelper extends DatabaseOpenHelper { 63 | public OpenHelper(Context context, String name) { 64 | super(context, name, SCHEMA_VERSION); 65 | } 66 | 67 | public OpenHelper(Context context, String name, CursorFactory factory) { 68 | super(context, name, factory, SCHEMA_VERSION); 69 | } 70 | 71 | @Override 72 | public void onCreate(Database db) { 73 | Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION); 74 | createAllTables(db, false); 75 | } 76 | } 77 | 78 | /** WARNING: Drops all table on Upgrade! Use only during development. */ 79 | public static class DevOpenHelper extends OpenHelper { 80 | public DevOpenHelper(Context context, String name) { 81 | super(context, name); 82 | } 83 | 84 | public DevOpenHelper(Context context, String name, CursorFactory factory) { 85 | super(context, name, factory); 86 | } 87 | 88 | @Override 89 | public void onUpgrade(Database db, int oldVersion, int newVersion) { 90 | Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables"); 91 | dropAllTables(db, true); 92 | onCreate(db); 93 | } 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/db/greendao/DaoSession.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.db.greendao; 2 | 3 | import java.util.Map; 4 | 5 | import org.greenrobot.greendao.AbstractDao; 6 | import org.greenrobot.greendao.AbstractDaoSession; 7 | import org.greenrobot.greendao.database.Database; 8 | import org.greenrobot.greendao.identityscope.IdentityScopeType; 9 | import org.greenrobot.greendao.internal.DaoConfig; 10 | 11 | import com.peng.mantis.model.db.entity.TodayWeather; 12 | 13 | import com.peng.mantis.model.db.greendao.TodayWeatherDao; 14 | 15 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. 16 | 17 | /** 18 | * {@inheritDoc} 19 | * 20 | * @see org.greenrobot.greendao.AbstractDaoSession 21 | */ 22 | public class DaoSession extends AbstractDaoSession { 23 | 24 | private final DaoConfig todayWeatherDaoConfig; 25 | 26 | private final TodayWeatherDao todayWeatherDao; 27 | 28 | public DaoSession(Database db, IdentityScopeType type, Map>, DaoConfig> 29 | daoConfigMap) { 30 | super(db); 31 | 32 | todayWeatherDaoConfig = daoConfigMap.get(TodayWeatherDao.class).clone(); 33 | todayWeatherDaoConfig.initIdentityScope(type); 34 | 35 | todayWeatherDao = new TodayWeatherDao(todayWeatherDaoConfig, this); 36 | 37 | registerDao(TodayWeather.class, todayWeatherDao); 38 | } 39 | 40 | public void clear() { 41 | todayWeatherDaoConfig.clearIdentityScope(); 42 | } 43 | 44 | public TodayWeatherDao getTodayWeatherDao() { 45 | return todayWeatherDao; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/http/ApiClient.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.http; 2 | 3 | import com.facebook.stetho.okhttp3.StethoInterceptor; 4 | import com.peng.android.coremodule.http.convert.FastJsonConverterFactory; 5 | import com.peng.mantis.BuildConfig; 6 | import com.peng.mantis.model.http.interceptor.BenguoUrlInterceptor; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | import okhttp3.OkHttpClient; 11 | import okhttp3.logging.HttpLoggingInterceptor; 12 | import retrofit2.Retrofit; 13 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; 14 | 15 | /** 16 | * 网络请求客户端 17 | * Created by pyt on 2017/7/5. 18 | */ 19 | 20 | public class ApiClient { 21 | 22 | /** 23 | * 根据不同的URL和Service clz对象,创建指定的Service 24 | * 25 | * @param baseUrl 26 | * @param serviceClz 27 | * @param 28 | * @return 29 | */ 30 | public static T createApiService(String baseUrl, Class serviceClz) { 31 | //创建和初始化OkHttp 32 | OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder(); 33 | //debug状态添加Log拦截器 34 | if (BuildConfig.DEBUG) { 35 | //这里必须设置成Body模式,默认为null,则不会进行打log 36 | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); 37 | httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 38 | okHttpBuilder.addInterceptor(httpLoggingInterceptor); 39 | } 40 | okHttpBuilder.connectTimeout(20, TimeUnit.SECONDS); 41 | okHttpBuilder.readTimeout(10, TimeUnit.SECONDS); 42 | okHttpBuilder.writeTimeout(10, TimeUnit.SECONDS); 43 | //添加url拦截器 44 | okHttpBuilder.addInterceptor(BenguoUrlInterceptor.create()); 45 | okHttpBuilder.addNetworkInterceptor(new StethoInterceptor()); 46 | //构建OKHttpClient 47 | OkHttpClient okHttpClient = okHttpBuilder.build(); 48 | //初始化Retrofit 49 | Retrofit.Builder retrofitBuilder = new Retrofit.Builder(); 50 | //添加Soap请求的转换器 51 | Retrofit retrofit = retrofitBuilder 52 | .addConverterFactory(FastJsonConverterFactory.create()) 53 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 54 | .client(okHttpClient) 55 | .baseUrl(baseUrl) 56 | .build(); 57 | return retrofit.create(serviceClz); 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/http/ApiConstants.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.http; 2 | 3 | /** 4 | * api网络请求用到的常量 5 | * Created by pyt on 2017/7/5. 6 | */ 7 | 8 | public class ApiConstants { 9 | 10 | //本果网络请求地址(必须以/结尾) 11 | public static final String API_BENGUO_NET_URL = "https://ba.benguo.cn/zhba/"; 12 | 13 | //其他网络请求地址 14 | public static final String API_OTHER_NET_URL = ""; 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/http/interceptor/BenguoUrlInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.http.interceptor; 2 | 3 | import com.peng.mantis.model.http.ApiConstants; 4 | import com.peng.mantis.model.repository.UserIdRepository; 5 | 6 | import java.io.IOException; 7 | 8 | import okhttp3.HttpUrl; 9 | import okhttp3.Interceptor; 10 | import okhttp3.Request; 11 | import okhttp3.Response; 12 | 13 | /** 14 | * 本果网络拦截器,拦截url 15 | * _userid=2782&_httpstate=UDP 16 | * 添加参数_userid和_state 17 | * Created by pyt on 2017/7/5. 18 | */ 19 | 20 | public class BenguoUrlInterceptor implements Interceptor { 21 | 22 | public static final String KEY_USERID = "_userid"; 23 | public static final String KEY_HTTP_STATE = "_httpstate"; 24 | public static final String VALUE_UDP = "UDP"; 25 | 26 | @Override 27 | public Response intercept(Chain chain) throws IOException { 28 | Request oldRequest = chain.request(); 29 | if (ApiConstants.API_BENGUO_NET_URL.contains(oldRequest.url().host())) { 30 | HttpUrl url = oldRequest.url(); 31 | //添加附加的参数 32 | HttpUrl.Builder urlBuilder = url.newBuilder(); 33 | urlBuilder.addQueryParameter(KEY_USERID, UserIdRepository.getUserId()); 34 | urlBuilder.addQueryParameter(KEY_HTTP_STATE, VALUE_UDP); 35 | Request newRequest = oldRequest.newBuilder().url(urlBuilder.build()).build(); 36 | return chain.proceed(newRequest); 37 | } else { 38 | Request newRequest = oldRequest.newBuilder().addHeader("Accept-Encoding","identity").url(oldRequest.url()).build(); 39 | return chain.proceed(newRequest); 40 | } 41 | } 42 | 43 | public static BenguoUrlInterceptor create(){ 44 | return new BenguoUrlInterceptor(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/http/service/MantisNetApi.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.http.service; 2 | 3 | import com.peng.mantis.model.http.entity.Weather; 4 | 5 | import retrofit2.http.Field; 6 | import retrofit2.http.FormUrlEncoded; 7 | import retrofit2.http.GET; 8 | import retrofit2.http.POST; 9 | import retrofit2.http.Query; 10 | import rx.Observable; 11 | 12 | /** 13 | * 本果网络请求的api 14 | * Created by pyt on 2017/7/5. 15 | */ 16 | 17 | public interface MantisNetApi { 18 | 19 | @GET("http://image.baidu.com/channel/listjson?pn=30&rn=30&tag2=全部&ftags=&sorttype=0&ie=utf8&oe=utf-8&fr=channel&app=img.browse.channel.star") 20 | Observable getBaiduImage (@Query("tag1") String type); 21 | 22 | //http://image.baidu.com/channel/listjson?pn=0&rn=30&tag1=%E7%BE%8E%E5%A5%B3&tag2=%E5%85%A8%E9%83%A8&sorttype=0&ie=utf8&oe=utf-8 23 | @FormUrlEncoded 24 | @POST("http://image.baidu.com/channel/listjson") 25 | Observable getBaiduImagePost (@Field("pn") int pn, @Field("rn") int rn, @Field("tag1") String tag1, @Field("tag2") String tag2, @Field("sorttype") int sortType, @Field("ie") String ie, @Field("oe") String oe); 26 | 27 | //查询天气 28 | @GET("http://wthrcdn.etouch.cn/weather_mini") 29 | Observable getWeatherInfo (@Query(value = "city", encoded = true) String city); 30 | 31 | @GET("https://bkzjapi.21move.net/api.aspx?action=bk_buy_order_list_get&did=a5e530da36c053f494f006d8e03e40c6&token=e36cefaf8b494684b4771b8d4f67416e&format=json&v=3&terminal=H5&lang=CN&sign_method=md5&appkey=21ee4afb24d149beb430ff16258bf974&appid=d3254130218942f5af7bbbf94cbfbcd8&limit=6&start=0&statue=&fstatue=×tamp=2017-07-12+13%3A54%3A59&sign=7cccddfcc72f6622f02351e681e94a41&_1499838899798=") 32 | Observable getOrderList (); 33 | 34 | @GET("https://kyfw.12306.cn/otn/regist/init") 35 | Observable get12306Request (); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/repository/TodayWeatherRepository.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.repository; 2 | 3 | import com.peng.library.mantis.kit.Kits; 4 | import com.peng.mantis.TestApplication; 5 | import com.peng.mantis.model.db.MantisDBManager; 6 | import com.peng.mantis.model.db.entity.TodayWeather; 7 | import com.peng.mantis.model.db.entity.adapter.TodayWeatherAdapter; 8 | import com.peng.mantis.model.db.greendao.TodayWeatherDao; 9 | 10 | import rx.Observable; 11 | import rx.schedulers.Schedulers; 12 | 13 | /** 14 | * 获取今天天气的Repository 15 | * Created by pyt on 2017/7/11. 16 | */ 17 | 18 | public class TodayWeatherRepository { 19 | 20 | /** 21 | * @param city 22 | * @return 23 | */ 24 | public static Observable getTodayWeather(String city){ 25 | //从数据库查询当前的天气 26 | Observable dbTodayWeatherObservable = MantisDBManager.getInstance().getTodayDaoSession() 27 | .queryBuilder(TodayWeather.class) 28 | .where(TodayWeatherDao.Properties.City.eq(city)) 29 | .rx() 30 | .unique(); 31 | 32 | //判断是否有网络 33 | if (Kits.NetWork.NETWORK_TYPE_DISCONNECT.equals(Kits.NetWork.getNetworkTypeName(TestApplication.getApplication()))) { 34 | return dbTodayWeatherObservable; 35 | } 36 | 37 | //请求网络 38 | Observable networkTodayWeatherObservable = TestApplication.getApplication().getMantisNetApi().getWeatherInfo(city) 39 | .map(weather -> new TodayWeatherAdapter(weather).getTodayWeather(city)) 40 | .doOnNext(todayWeather -> Schedulers.io().createWorker() 41 | .schedule(() -> MantisDBManager.getInstance().getTodayDaoSession().insertOrReplace(todayWeather))); 42 | 43 | //合并两个Observalbe 44 | return Observable.concat(dbTodayWeatherObservable, networkTodayWeatherObservable) 45 | .distinct() 46 | .filter(todayWeather -> todayWeather != null) 47 | .takeUntil(todayWeather -> System.currentTimeMillis() - todayWeather.getCacheTime() < 10000); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/model/repository/UserIdRepository.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.model.repository; 2 | 3 | /** 4 | * 用户id的 5 | * Created by pyt on 2017/7/5. 6 | */ 7 | 8 | public class UserIdRepository { 9 | 10 | /** 11 | *获取用户id 12 | * @return 13 | */ 14 | public static String getUserId(){ 15 | return "2782"; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/present/TestDataPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.present; 2 | 3 | import android.text.TextUtils; 4 | import android.util.Log; 5 | 6 | import com.peng.library.mantis.expand.data.MantisDataPresent; 7 | import com.peng.library.mantis.mvp.PresentEvent; 8 | import com.peng.mantis.contract.TestDataContract; 9 | 10 | import java.util.concurrent.TimeUnit; 11 | 12 | import rx.Observable; 13 | import rx.android.schedulers.AndroidSchedulers; 14 | import rx.schedulers.Schedulers; 15 | 16 | /** 17 | * 测试数据的Present 18 | * Created by pyt on 2017/6/23. 19 | */ 20 | 21 | public class TestDataPresent extends MantisDataPresent implements TestDataContract.Present { 22 | 23 | private static final String TAG = "TestDataPresent"; 24 | 25 | @Override 26 | public void login(String account, String password) { 27 | if (TextUtils.isEmpty(account)) { 28 | view.toast("账号为NULL"); 29 | return; 30 | } 31 | 32 | if (TextUtils.isEmpty(password)) { 33 | view.toast("密码为NULL"); 34 | return; 35 | } 36 | publishData("正在登录。。。。。"); 37 | Observable.create(subscriber -> subscriber.onNext("登录成功 账号:" + account + " 密码:" + password)) 38 | .delay(2, TimeUnit.SECONDS) 39 | .subscribeOn(Schedulers.io()) 40 | .compose(bindUntilEvent(PresentEvent.DESTROY)) 41 | .observeOn(AndroidSchedulers.mainThread()) 42 | .subscribe(s -> { 43 | publishData(s); 44 | Log.i(TAG, "login: 执行onNext"); 45 | } 46 | , throwable -> { 47 | publishError(throwable); 48 | Log.i(TAG, "login: 执行onError"); 49 | } 50 | , () -> { 51 | Log.i(TAG, "login: 执行onComplete"); 52 | }); 53 | } 54 | 55 | @Override 56 | public void logout() { 57 | clearData(); 58 | } 59 | 60 | private void clearData(){ 61 | getView().toast("Hello"); 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/present/TestHintPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.present; 2 | 3 | import android.os.Bundle; 4 | import android.util.Log; 5 | 6 | import com.peng.library.mantis.expand.data.MantisDataPresent; 7 | import com.peng.mantis.contract.TestHintContract; 8 | 9 | import java.util.concurrent.TimeUnit; 10 | 11 | import rx.Observable; 12 | import rx.android.schedulers.AndroidSchedulers; 13 | import rx.schedulers.Schedulers; 14 | 15 | import static android.content.ContentValues.TAG; 16 | 17 | /** 18 | * 测试提示框架的Present 19 | * Created by pyt on 2017/6/26. 20 | */ 21 | 22 | public class TestHintPresent extends MantisDataPresent implements TestHintContract.Present { 23 | 24 | private int reloadIndex = 0; 25 | 26 | @Override 27 | public void onCreate(TestHintContract.View view, Bundle data) { 28 | super.onCreate(view, data); 29 | } 30 | 31 | @Override 32 | public void onCreateView(TestHintContract.View view) { 33 | super.onCreateView(view); 34 | //由于其他网络请求或则是耗时操作,先显示ProgressView 35 | getViewDelegate().showProgressView(); 36 | //2s后显示emptyView 37 | createCommonObservable("", 1).subscribe(s -> getViewDelegate().showEmptyView()); 38 | } 39 | 40 | 41 | @Override 42 | public void reload() { 43 | reloadIndex++; 44 | Log.i(TAG, "reload: index [ " + reloadIndex + " ]"); 45 | if ( reloadIndex == 1) { 46 | createCommonObservable("", 1).subscribe(s -> getViewDelegate().showNetworkErrorView()); 47 | Log.i(TAG, "reload:显示网络异常View"); 48 | } else if ( reloadIndex == 2) { 49 | createCommonObservable("", 1) .subscribe(s -> getViewDelegate().showErrorView("十分的抱歉", "由于攻城狮GG的失误,导致程序的奔溃,截此图奖励9999999元")); 50 | Log.i(TAG, "reload: 显示程序错误View"); 51 | }else { 52 | createCommonObservable("恭喜恭喜,终于显示ContentView了,来自不易啊!", 1).subscribe(s -> publishData(s), throwable -> publishError(throwable)); 53 | Log.i(TAG, "reload: 显示内容View"); 54 | reloadIndex = 0; 55 | } 56 | } 57 | 58 | /** 59 | * @param text 60 | * @param delay 61 | * @return 62 | */ 63 | private Observable createCommonObservable(String text, int delay){ 64 | return Observable.create(subscriber -> subscriber.onNext(text)) 65 | .delay(delay, TimeUnit.SECONDS) 66 | .subscribeOn(Schedulers.io()) 67 | .observeOn(AndroidSchedulers.mainThread()); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/present/TestHttpPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.present; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.peng.library.mantis.expand.data.MantisDataPresent; 6 | import com.peng.library.mantis.mvp.PresentEvent; 7 | import com.peng.mantis.contract.TestHttpContract; 8 | import com.peng.mantis.model.http.ApiClient; 9 | import com.peng.mantis.model.http.ApiConstants; 10 | import com.peng.mantis.model.http.service.MantisNetApi; 11 | 12 | import rx.android.schedulers.AndroidSchedulers; 13 | import rx.schedulers.Schedulers; 14 | 15 | 16 | /** 17 | * Created by pyt on 201/7/5. 18 | */ 19 | 20 | public class TestHttpPresent extends MantisDataPresent implements TestHttpContract.Present { 21 | 22 | private static final String TAG = "TestHttpPresent"; 23 | 24 | private MantisNetApi mantisNetApi; 25 | 26 | @Override 27 | public void onCreate(TestHttpContract.View view, Bundle data) { 28 | super.onCreate(view, data); 29 | mantisNetApi = ApiClient.createApiService(ApiConstants.API_BENGUO_NET_URL, MantisNetApi.class); 30 | } 31 | 32 | @Override 33 | public void startGetRequest() { 34 | // mantisNetApi.getBaiduImage("明星") 35 | // .compose(bindUntilEvent(PresentEvent.DESTROY)) 36 | // .subscribeOn(Schedulers.io()) 37 | // .observeOn(AndroidSchedulers.mainThread()) 38 | // .subscribe(baiDuImage -> this.publishData(baiDuImage), throwable -> publishError(throwable)); 39 | 40 | ApiClient.createApiService(ApiConstants.API_BENGUO_NET_URL, MantisNetApi.class).getOrderList() 41 | .compose(bindUntilEvent(PresentEvent.DESTROY)) 42 | .subscribeOn(Schedulers.io()) 43 | .observeOn(AndroidSchedulers.mainThread()) 44 | .subscribe(string -> this.publishData(string), throwable -> publishError(throwable)); 45 | } 46 | 47 | @Override 48 | public void startPostRequest() { 49 | // mantisNetApi.getBaiduImagePost(0, 50, "美女", "全部", 0, "utf-8", "utf-8") 50 | // .compose(bindUntilEvent(PresentEvent.DESTROY)) 51 | // .subscribeOn(Schedulers.io()) 52 | // .observeOn(AndroidSchedulers.mainThread()) 53 | // .subscribe(baiDuImage -> publishData(baiDuImage), throwable -> publishError(throwable)); 54 | 55 | mantisNetApi.get12306Request() 56 | .compose(bindUntilEvent(PresentEvent.DESTROY)) 57 | .subscribeOn(Schedulers.io()) 58 | .observeOn(AndroidSchedulers.mainThread()) 59 | .subscribe(baiDuImage -> publishData(baiDuImage), throwable -> publishError(throwable)); 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/present/TestRefreshPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.present; 2 | 3 | import android.util.Log; 4 | 5 | import com.peng.library.mantis.expand.refresh.MantisRefreshPresent; 6 | import com.peng.library.mantis.kit.MLog; 7 | import com.peng.mantis.contract.TestRefreshContract; 8 | 9 | import java.util.concurrent.TimeUnit; 10 | 11 | import rx.Observable; 12 | import rx.Observer; 13 | import rx.Subscriber; 14 | import rx.android.schedulers.AndroidSchedulers; 15 | import rx.schedulers.Schedulers; 16 | 17 | /** 18 | * Created by pyt on 2017/6/28. 19 | */ 20 | 21 | public class TestRefreshPresent extends MantisRefreshPresent implements TestRefreshContract.Present { 22 | 23 | private static final String TAG = "TestRefreshPresent"; 24 | private Observer proxySubscriber = new Subscriber(){ 25 | 26 | @Override 27 | public void onCompleted() { 28 | 29 | } 30 | 31 | @Override 32 | public void onError(Throwable e) { 33 | getView().onReceiveError(e); 34 | } 35 | 36 | @Override 37 | public void onNext(String o) { 38 | getView().onReceiveData(o); 39 | } 40 | }; 41 | 42 | 43 | @Override 44 | public void onCreateView(TestRefreshContract.View view) { 45 | super.onCreateView(view); 46 | } 47 | 48 | @Override 49 | public void giveMeData() { 50 | 51 | } 52 | 53 | 54 | /** 55 | * 获取一个公共的观察者 56 | * 57 | * @param text 58 | * @param delay 59 | * @return 60 | */ 61 | private Observable createCommonObservable(String text, int delay) { 62 | return Observable.create(subscriber -> subscriber.onNext(text)) 63 | .delay(delay, TimeUnit.SECONDS) 64 | .subscribeOn(Schedulers.io()) 65 | .observeOn(AndroidSchedulers.mainThread()); 66 | } 67 | 68 | @Override 69 | public void onRefreshCall() { 70 | MLog.i("哈哈哈哈哈哈"); 71 | Log.d(TAG, "giveMeData() called"); 72 | createCommonObservable("终于拉出来了,一共拉了 " + ((int) (Math.random() * 1000)) + " 坨", 2) 73 | .subscribe(proxySubscriber); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/present/TestRepositoryPresent.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.present; 2 | 3 | import android.os.Bundle; 4 | import android.util.Log; 5 | 6 | import com.peng.library.mantis.expand.data.MantisDataPresent; 7 | import com.peng.library.mantis.expand.refresh.MantisRefreshPresent; 8 | import com.peng.mantis.contract.TestRepositoryContract; 9 | import com.peng.mantis.model.db.entity.TodayWeather; 10 | import com.peng.mantis.model.repository.TodayWeatherRepository; 11 | import com.trello.rxlifecycle.LifecycleTransformer; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | import rx.Subscriber; 16 | import rx.android.schedulers.AndroidSchedulers; 17 | import rx.schedulers.Schedulers; 18 | 19 | /** 20 | * Created by pyt on 2017/7/11. 21 | */ 22 | 23 | public class TestRepositoryPresent extends MantisRefreshPresent implements TestRepositoryContract.Present { 24 | 25 | 26 | private static final String TAG = "TestRepositoryPresent"; 27 | 28 | @Override 29 | public void onRefreshCall() { 30 | TodayWeatherRepository.getTodayWeather("北京") 31 | .subscribeOn(Schedulers.io()) 32 | .observeOn(AndroidSchedulers.mainThread()) 33 | .subscribe(new Subscriber() { 34 | @Override 35 | public void onCompleted() { 36 | getView().refreshComplete(); 37 | } 38 | 39 | @Override 40 | public void onError(Throwable e) { 41 | getView().refreshComplete(); 42 | e.printStackTrace(); 43 | getViewDelegate().showErrorView("恭喜发生错误了", "废话一堆!!!" + e.getMessage()); 44 | } 45 | 46 | @Override 47 | public void onNext(TodayWeather todayWeather) { 48 | if (todayWeather != null) { 49 | getViewDelegate().showContentView(); 50 | getView().setTodayWeather(todayWeather); 51 | } else { 52 | getViewDelegate().showErrorView("没有请求到数据", "重试吧!!"); 53 | } 54 | } 55 | }); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/view/fragment/TestDataFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.view.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.EditText; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import com.peng.library.mantis.expand.data.MantisDataFragment; 13 | import com.peng.library.mantis.hint.HintConfig; 14 | import com.peng.library.mantis.mvp.BindPresent; 15 | import com.peng.mantis.R; 16 | import com.peng.mantis.contract.TestDataContract; 17 | import com.peng.mantis.present.TestDataPresent; 18 | 19 | import butterknife.BindView; 20 | import butterknife.ButterKnife; 21 | import butterknife.OnClick; 22 | 23 | /** 24 | * Created by pyt on 2017/6/23. 25 | */ 26 | @BindPresent(value = TestDataPresent.class) 27 | public class TestDataFragment extends MantisDataFragment implements TestDataContract.View { 28 | 29 | @BindView(R.id.et_password) 30 | EditText etPassword; 31 | @BindView(R.id.et_account) 32 | EditText etAccount; 33 | @BindView(R.id.tv_result) 34 | TextView tvResult; 35 | 36 | @Override 37 | public void onCreate(@Nullable Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | } 40 | 41 | 42 | @Override 43 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState, HintConfig.Builder builder) { 44 | View contentView = inflater.inflate(R.layout.fragment_test_data, container, false); 45 | ButterKnife.bind(this, contentView); 46 | return contentView; 47 | } 48 | 49 | @Override 50 | public void onReceiveData(String s) { 51 | tvResult.setText(s); 52 | } 53 | 54 | @Override 55 | public void onReceiveError(Throwable error) { 56 | error.printStackTrace(); 57 | tvResult.setText("发生错误:" + error.getMessage()); 58 | } 59 | 60 | 61 | @Override 62 | public void toast(String msg) { 63 | Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show(); 64 | } 65 | 66 | @OnClick(R.id.btn_login) 67 | public void login() { 68 | getPresent().login(etAccount.getText().toString(), etPassword.getText().toString()); 69 | } 70 | 71 | 72 | public void onLogout(View view) { 73 | getPresent().logout(); 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/view/fragment/TestHintFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.view.fragment; 2 | 3 | import android.accounts.NetworkErrorException; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.util.Log; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.TextView; 11 | 12 | import com.peng.library.mantis.expand.data.MantisDataFragment; 13 | import com.peng.library.mantis.hint.HintConfig; 14 | import com.peng.library.mantis.mvp.BindPresent; 15 | import com.peng.mantis.R; 16 | import com.peng.mantis.contract.TestHintContract; 17 | import com.peng.mantis.present.TestHintPresent; 18 | 19 | import butterknife.BindView; 20 | import butterknife.ButterKnife; 21 | 22 | /** 23 | * 测试提示框架的Fragment 24 | * Created by pyt on 2017/6/26. 25 | */ 26 | @BindPresent(value = TestHintPresent.class) 27 | public class TestHintFragment extends MantisDataFragment implements TestHintContract.View { 28 | 29 | private static final String TAG = "TestHintFragment"; 30 | 31 | @BindView(R.id.tv_content) 32 | TextView tvContent; 33 | 34 | 35 | @Override 36 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState, HintConfig.Builder builder) { 37 | View contentView = inflater.inflate(R.layout.fragment_test_hint, container, false); 38 | Log.i(TAG, "onCreateView: "+contentView.getParent()); 39 | //必须指定Fragment和View 40 | ButterKnife.bind(this,contentView); 41 | return contentView; 42 | } 43 | 44 | @Override 45 | public void onReceiveData(String s) { 46 | getViewDelegate().showContentView(); 47 | tvContent.setText(s); 48 | } 49 | 50 | @Override 51 | public void onReceiveError(Throwable error) { 52 | if (error instanceof NetworkErrorException) { 53 | getViewDelegate().showNetworkErrorView(); 54 | }else { 55 | getViewDelegate().showErrorView("抱歉我们的程序发生错误", error.getMessage()); 56 | } 57 | } 58 | 59 | @Override 60 | public void onRetry(int type,Object tag) { 61 | getViewDelegate().showProgressView(); 62 | getPresent().reload(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/view/fragment/TestHttpFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.view.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.util.Log; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.Button; 10 | import android.widget.TextView; 11 | 12 | import com.peng.library.mantis.expand.data.MantisDataFragment; 13 | import com.peng.library.mantis.hint.HintConfig; 14 | import com.peng.library.mantis.mvp.BindPresent; 15 | import com.peng.mantis.R; 16 | import com.peng.mantis.contract.TestHttpContract; 17 | import com.peng.mantis.present.TestHttpPresent; 18 | 19 | import butterknife.BindView; 20 | import butterknife.ButterKnife; 21 | import butterknife.OnClick; 22 | 23 | /** 24 | * Created by pyt on 2017/7/5. 25 | */ 26 | @BindPresent(TestHttpPresent.class) 27 | public class TestHttpFragment extends MantisDataFragment implements TestHttpContract.View { 28 | 29 | private static final String TAG = "TestHttpFragment"; 30 | 31 | @BindView(R.id.btn_post) 32 | Button btnPost; 33 | @BindView(R.id.btn_get) 34 | Button btnGet; 35 | @BindView(R.id.tv_response) 36 | TextView tvResponse; 37 | 38 | 39 | @Override 40 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState, HintConfig.Builder builder) { 41 | View contentView = inflater.inflate(R.layout.fragment_test_http, container, false); 42 | ButterKnife.bind(this, contentView); 43 | return contentView; 44 | } 45 | 46 | @Override 47 | public void onReceiveData(String s) { 48 | getViewDelegate().showContentView(); 49 | tvResponse.setText(com.alibaba.fastjson.JSON.toJSONString(s)); 50 | } 51 | 52 | @Override 53 | public void onReceiveError(Throwable error) { 54 | error.printStackTrace(); 55 | getViewDelegate().showContentView(); 56 | Log.i(TAG, "onReceiveError: "+error); 57 | tvResponse.setText("发生错误:" + error); 58 | } 59 | 60 | 61 | @OnClick({R.id.btn_post, R.id.btn_get}) 62 | public void onClick(View view) { 63 | getViewDelegate().showProgressView(); 64 | switch (view.getId()) { 65 | case R.id.btn_post: 66 | getPresent().startPostRequest(); 67 | break; 68 | case R.id.btn_get: 69 | getPresent().startGetRequest(); 70 | break; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/view/fragment/TestListFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.view.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | 10 | import com.bumptech.glide.Glide; 11 | import com.chad.library.adapter.base.BaseViewHolder; 12 | import com.peng.library.mantis.expand.list.MantisListFragment; 13 | import com.peng.library.mantis.expand.list.link.ListConfig; 14 | import com.peng.library.mantis.expand.refresh.link.RefreshConfig; 15 | import com.peng.library.mantis.hint.HintConfig; 16 | import com.peng.library.mantis.mvp.BindPresent; 17 | import com.peng.mantis.R; 18 | import com.peng.mantis.contract.TestListContract; 19 | import com.peng.mantis.present.TestListPresent; 20 | 21 | /** 22 | * Created by pyt on 2017/6/29. 23 | */ 24 | @BindPresent(TestListPresent.class) 25 | public class TestListFragment extends MantisListFragment implements TestListContract.View { 26 | 27 | @Override 28 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState, HintConfig.Builder HintConfigBuilder, RefreshConfig.Builder refreshConfigBuilder, ListConfig.Builder listConfigBuilder) { 29 | listConfigBuilder.canLoadMore(true).hasDivider(false); 30 | return super.onCreateView(inflater, container, savedInstanceState, HintConfigBuilder, refreshConfigBuilder, listConfigBuilder); 31 | } 32 | 33 | @Override 34 | public void onConvert(BaseViewHolder holder, String s, int position) { 35 | ImageView imageView = holder.getView(R.id.imageView); 36 | Glide.with(getContext()).load(s).placeholder(R.mipmap.ic_launcher_round).centerCrop().into(imageView); 37 | } 38 | 39 | @Override 40 | public void onReceiveError(Throwable throwable) { 41 | 42 | } 43 | 44 | @Override 45 | public void onRetry(int type, Object tag) { 46 | super.onRetry(type, tag); 47 | getViewDelegate().showContentView(); 48 | } 49 | 50 | @Override 51 | public int getItemLayout() { 52 | return R.layout.item_list_test_list; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/view/fragment/TestRefreshFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.view.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.util.Log; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import com.peng.library.mantis.expand.refresh.MantisRefreshFragment; 12 | import com.peng.library.mantis.expand.refresh.link.RefreshConfig; 13 | import com.peng.library.mantis.hint.HintConfig; 14 | import com.peng.library.mantis.mvp.BindPresent; 15 | import com.peng.library.mantis.mvp.IViewDelegate; 16 | import com.peng.mantis.R; 17 | import com.peng.mantis.contract.TestRefreshContract; 18 | import com.peng.mantis.present.TestRefreshPresent; 19 | 20 | import butterknife.BindView; 21 | import butterknife.ButterKnife; 22 | 23 | /** 24 | * Created by pyt on 2017/6/28. 25 | */ 26 | @BindPresent(TestRefreshPresent.class) 27 | public class TestRefreshFragment extends MantisRefreshFragment implements TestRefreshContract.View { 28 | 29 | private static final String TAG = "TestRefreshFragment"; 30 | 31 | @BindView(R.id.tv_no_1) 32 | TextView tvNo1; 33 | @BindView(R.id.tv_no_2) 34 | TextView tvNo2; 35 | 36 | @Override 37 | public void onReceiveData(String s) { 38 | Log.d(TAG, "onReceiveData() called with: s = [" + s + "]"); 39 | refreshComplete(); 40 | tvNo1.setText(s); 41 | tvNo2.setText(s); 42 | } 43 | 44 | @Override 45 | public void onReceiveError(Throwable error) { 46 | 47 | } 48 | 49 | @Override 50 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 51 | super.onViewCreated(view, savedInstanceState); 52 | ButterKnife.bind(this, view); 53 | } 54 | 55 | 56 | 57 | @Override 58 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 59 | super.onActivityCreated(savedInstanceState); 60 | } 61 | 62 | @Override 63 | public void onRetry(int type,Object tag) { 64 | if (type == IViewDelegate.INDEX_EMPTY) { 65 | getViewDelegate().showContentView(); 66 | autoRefresh(); 67 | } 68 | } 69 | 70 | @Override 71 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState, HintConfig.Builder hintBuilder, RefreshConfig.Builder refreshBuilder) { 72 | refreshBuilder.autoRefresh(false); 73 | return inflater.inflate(R.layout.fragment_test_refresh, container, false); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/peng/mantis/view/fragment/TestRepositoryFragment.java: -------------------------------------------------------------------------------- 1 | package com.peng.mantis.view.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.util.Log; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import com.peng.library.mantis.expand.refresh.MantisRefreshFragment; 12 | import com.peng.library.mantis.expand.refresh.link.RefreshConfig; 13 | import com.peng.library.mantis.hint.HintConfig; 14 | import com.peng.library.mantis.mvp.BindPresent; 15 | import com.peng.mantis.R; 16 | import com.peng.mantis.contract.TestRepositoryContract; 17 | import com.peng.mantis.model.db.entity.TodayWeather; 18 | import com.peng.mantis.present.TestRepositoryPresent; 19 | 20 | import butterknife.BindView; 21 | import butterknife.ButterKnife; 22 | import butterknife.Unbinder; 23 | 24 | /** 25 | * Created by pyt on 2017/7/11. 26 | */ 27 | @BindPresent(TestRepositoryPresent.class) 28 | public class TestRepositoryFragment extends MantisRefreshFragment implements TestRepositoryContract.View { 29 | 30 | 31 | private static final String TAG = "TestRepositoryFragment"; 32 | 33 | @BindView(R.id.tv_city) 34 | TextView tvCity; 35 | @BindView(R.id.tv_templature) 36 | TextView tvTemplature; 37 | @BindView(R.id.tv_wind_level) 38 | TextView tvWindLevel; 39 | @BindView(R.id.tv_weather) 40 | TextView tvWeather; 41 | @BindView(R.id.tv_cache_time) 42 | TextView tvCacheTime; 43 | private Unbinder bind; 44 | 45 | 46 | @Override 47 | public void onDestroyView() { 48 | super.onDestroyView(); 49 | bind.unbind(); 50 | } 51 | 52 | @Override 53 | public void setTodayWeather(TodayWeather todayWeather) { 54 | Log.d(TAG, "setTodayWeather() called with: todayWeather = [" + todayWeather + "]"); 55 | tvCity.setText(todayWeather.getCity()); 56 | tvTemplature.setText(todayWeather.getHigh()); 57 | tvCacheTime.setText(String.valueOf(todayWeather.getCacheTime())); 58 | tvWeather.setText(todayWeather.getType()); 59 | tvWindLevel.setText(todayWeather.getFengli()); 60 | } 61 | 62 | @Override 63 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState, HintConfig.Builder hintBuilder, RefreshConfig.Builder refreshBuilder) { 64 | refreshBuilder.autoRefresh(true); 65 | View contentView = inflater.inflate(R.layout.fragment_test_repository, container, false); 66 | bind = ButterKnife.bind(this,contentView); 67 | return contentView; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 |