├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── keystore.properties ├── lib_common ├── .gitignore ├── build.gradle ├── libs │ └── simple-xml-core.jar └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── guiying │ │ └── module │ │ └── common │ │ ├── base │ │ ├── BaseActionBarActivity.java │ │ ├── BaseActivity.java │ │ ├── BaseApplication.java │ │ ├── BaseFragment.java │ │ ├── BasePresenter.java │ │ ├── BaseView.java │ │ ├── ClassUtils.java │ │ ├── IApplicationDelegate.java │ │ ├── IViewDelegate.java │ │ ├── InfoCallback.java │ │ └── ViewManager.java │ │ ├── glide │ │ ├── ImageUtils.java │ │ ├── OkHttpGlideModule.java │ │ ├── OkHttpStreamFetcher.java │ │ └── OkHttpUrlLoader.java │ │ ├── http │ │ ├── ApiService.java │ │ ├── DataParseUtil.java │ │ ├── DataType.java │ │ ├── HttpClient.java │ │ ├── HttpsUtils.java │ │ ├── LoggerInterceptor.java │ │ └── OnResultListener.java │ │ ├── utils │ │ ├── CloseUtils.java │ │ ├── NetworkUtils.java │ │ ├── ScreenLockUtil.java │ │ ├── ShellUtils.java │ │ ├── StringUtils.java │ │ ├── ToastUtils.java │ │ └── Utils.java │ │ └── widget │ │ ├── HackyViewPager.java │ │ └── NoScrollViewPager.java │ └── res │ ├── drawable-xxhdpi │ └── ic_arrow_back.png │ ├── drawable │ └── shape_loading_bg.xml │ ├── layout │ ├── layout_load_error.xml │ ├── layout_load_more.xml │ ├── layout_load_no_more.xml │ ├── layout_load_progress.xml │ ├── layout_view_empty.xml │ ├── progress_dialog.xml │ └── toolbar.xml │ ├── mipmap-xxhdpi │ └── ic_launcher.jpg │ ├── values-v21 │ └── styles.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── module_app ├── .gitignore ├── build.gradle ├── libs │ └── acra-4.5.0.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── guiying │ │ └── module │ │ └── MyApplication.java │ └── res │ └── values │ └── strings.xml ├── module_girls ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── com │ │ └── guiying │ │ │ └── module │ │ │ └── girls │ │ │ ├── Constants.java │ │ │ ├── GirlsFragment.java │ │ │ ├── MyDelegate.java │ │ │ ├── MyViewDelegate.java │ │ │ ├── data │ │ │ ├── GirlsDataSource.java │ │ │ ├── bean │ │ │ │ ├── Girls.java │ │ │ │ └── GirlsParser.java │ │ │ └── source │ │ │ │ └── RemoteGirlsDataSource.java │ │ │ ├── girl │ │ │ ├── GirlActivity.java │ │ │ └── GirlAdapter.java │ │ │ └── main │ │ │ ├── GirlsActivity.java │ │ │ ├── GirlsAdapter.java │ │ │ ├── GirlsContract.java │ │ │ ├── GirlsPresenter.java │ │ │ └── GirlsView.java │ └── debug │ │ └── GirlsApplication.java │ ├── module │ └── AndroidManifest.xml │ └── res │ ├── layout │ ├── activity_girls.xml │ ├── fragment_girls.xml │ ├── item_girl.xml │ ├── item_girl_detail.xml │ └── view_girls_content.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ └── strings.xml ├── module_main ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── com │ │ └── guiying │ │ │ └── module │ │ │ └── main │ │ │ ├── BottomNavigationActivity.java │ │ │ ├── FragmentAdapter.java │ │ │ └── MainActivity.java │ └── debug │ │ └── MainApplication.java │ ├── module │ └── AndroidManifest.xml │ └── res │ ├── drawable │ ├── ic_dashboard_black_24dp.xml │ ├── ic_home_black_24dp.xml │ └── ic_notifications_black_24dp.xml │ ├── layout │ ├── activity_bottom_navigation.xml │ └── activity_main.xml │ ├── menu │ └── navigation.xml │ └── values │ ├── dimens.xml │ └── strings.xml ├── module_news ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── com │ │ └── guiying │ │ │ └── module │ │ │ └── news │ │ │ ├── Constants.java │ │ │ ├── MyDelegate.java │ │ │ ├── MyViewDelegate.java │ │ │ ├── NewsFragment.java │ │ │ ├── data │ │ │ ├── NewsDataSource.java │ │ │ ├── bean │ │ │ │ ├── MessageDetail.java │ │ │ │ ├── Story.java │ │ │ │ └── StoryList.java │ │ │ └── source │ │ │ │ └── RemoteNewsDataSource.java │ │ │ ├── detail │ │ │ ├── NewsDetailActivity.java │ │ │ ├── NewsDetailContract.java │ │ │ ├── NewsDetailPresenter.java │ │ │ └── NewsDetailView.java │ │ │ └── main │ │ │ ├── NewsCenterActivity.java │ │ │ ├── NewsListAdapter.java │ │ │ ├── NewsListContract.java │ │ │ ├── NewsListPresenter.java │ │ │ ├── NewsListView.java │ │ │ └── NewsListViewAdapter.java │ └── debug │ │ ├── LauncherActivity.java │ │ └── NewsApplication.java │ ├── module │ └── AndroidManifest.xml │ └── res │ ├── layout │ ├── activity_news.xml │ ├── fragment_news.xml │ ├── item_news_list.xml │ └── view_news_detail.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ └── strings.xml ├── screenshots ├── Screenshot_1.png ├── Screenshot_2.png ├── Screenshot_3.png ├── Screenshot_4.png └── develper.PNG ├── settings.gradle └── versions.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | .idea/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # Intellij 37 | *.iml 38 | .idea/workspace.xml 39 | .idea/vcs.xml 40 | .idea/libraries 41 | 42 | 43 | # Keystore files 44 | *.jks 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # 应用截图 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | # AndroidModulePattern 13 | 14 | Android项目组件化示例代码 15 | 16 | **Android组件化方案**:http://blog.csdn.net/guiying712/article/details/55213884 17 | 18 | **Android组件化之终极方案**:http://blog.csdn.net/guiying712/article/details/78057120 19 | 20 | 1. 现在的 AndroidModulePattern 使用 阿里ARouter作为路由; 21 | 22 | 2. Android组件化方案已经支持 **Fragment组件化**,使用方法请下载Demo查看; 23 | 24 | 3. 本项目已适配Android Studio 3.0.1版本(Google仓库会带来一定影响) 25 | 26 | 27 | ## 集成开发模式和组件开发模式转换 28 | 29 | **1、首先打开Android项目的 gradle.properties 文件,然后将 isModule 改为你需要的开发模式(true/false), 30 | 然后点击 "Sync Project" 按钮同步项目;** 31 | 32 | **2、![Image](/screenshots/develper.PNG) 在运行之前,请先按照图中选择一个能够运行的组件;** 33 | 34 | 35 | ## 组件功能介绍 36 | 37 | ### app组件功能(空壳工程): 38 | 1. 配置整个项目的Gradle脚本,例如 混淆、签名等; 39 | 2. app组件中可以初始化全局的库,例如Lib.init(this); 40 | 3. 添加 multiDex 功能 41 | 4. 业务组件管理(组装); 42 | 43 | ### main组件功能(业务组件): 44 | 1. 声明应用的launcherActivity----->android.intent.category.LAUNCHER; 45 | 2. 添加SplashActivity; 46 | 3. 添加LoginActivity; 47 | 4. 添加MainActivity; 48 | 49 | ### girls/news组件功能(业务组件): 50 | 1. 这两个组件都是业务组件,根据产品的业务逻辑独立成一个组件; 51 | 52 | ### common组件功能(功能组件): 53 | 1. common组件是基础库,添加一些公用的类; 54 | 2. 例如:网络请求、图片加载、工具类、base类等等; 55 | 3. 声明APP需要的uses-permission; 56 | 4. 定义全局通用的主题(Theme); 57 | 58 | ## License 59 | 60 | Copyright 2017 guiying712, AndroidModulePattern Open Source Project 61 | 62 | Licensed under the Apache License, Version 2.0 (the "License"); 63 | you may not use this file except in compliance with the License. 64 | You may obtain a copy of the License at 65 | 66 | http://www.apache.org/licenses/LICENSE-2.0 67 | 68 | Unless required by applicable law or agreed to in writing, software 69 | distributed under the License is distributed on an "AS IS" BASIS, 70 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 71 | See the License for the specific language governing permissions and 72 | limitations under the License. 73 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | apply from: 'versions.gradle' 5 | addRepos(repositories) 6 | dependencies { 7 | /* classpath deps.android_gradle_plugin*/ 8 | classpath deps.android_gradle_plugin 9 | classpath deps.kotlin.plugin 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | addRepos(repositories) 17 | // Android dependency 'com.android.support:design' has different version for the compile (25.3.1) and runtime (25.4.0) classpath. 18 | // You should manually set the same version via DependencyResolution 19 | subprojects { 20 | project.configurations.all { 21 | resolutionStrategy.eachDependency { details -> 22 | if (details.requested.group == 'com.android.support' 23 | && !details.requested.name.contains('multidex')) { 24 | details.useVersion "27.0.2" 25 | } 26 | } 27 | } 28 | } 29 | 30 | // 组件缓存更新时间设置(默认每次build都更新) 31 | configurations.all { 32 | resolutionStrategy.cacheChangingModulesFor 0, 'minutes' 33 | } 34 | } 35 | 36 | task clean(type: Delete) { 37 | delete rootProject.buildDir 38 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/gradle.properties -------------------------------------------------------------------------------- /keystore.properties: -------------------------------------------------------------------------------- 1 | storePassword=guiying712 2 | keyPassword=guiying712 3 | keyAlias=guiying712 4 | storeFile=/mykey.jks -------------------------------------------------------------------------------- /lib_common/.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea/workspace.xml 38 | .idea/vcs.xml 39 | 40 | # Keystore files 41 | *.jks 42 | -------------------------------------------------------------------------------- /lib_common/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion build_versions.target_sdk 5 | defaultConfig { 6 | minSdkVersion build_versions.min_sdk 7 | targetSdkVersion build_versions.target_sdk 8 | versionCode 1 9 | versionName "1.0" 10 | } 11 | 12 | 13 | compileOptions { 14 | sourceCompatibility JavaVersion.VERSION_1_8 15 | targetCompatibility JavaVersion.VERSION_1_8 16 | } 17 | 18 | buildTypes { 19 | release { 20 | buildConfigField "boolean", "LOG_DEBUG", "true" 21 | zipAlignEnabled false 22 | shrinkResources false 23 | minifyEnabled false 24 | debuggable true 25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | 29 | } 30 | 31 | dependencies { 32 | api fileTree(include: ['*.jar'], dir: 'libs') 33 | // Support libraries 34 | api deps.support.app_compat 35 | api deps.support.v4 36 | api deps.support.v13 37 | api deps.support.design 38 | api deps.support.cardview 39 | api deps.support.percent 40 | api deps.support.recyclerview 41 | api deps.constraint_layout 42 | 43 | // RxJava and retrofit 44 | api deps.rx_android 45 | api deps.rxjava2 46 | api deps.retrofit.runtime 47 | api deps.retrofit.gson 48 | api deps.persistent_cookie 49 | 50 | //Dagger 51 | api deps.dagger.runtime 52 | api deps.dagger.android 53 | api deps.dagger.android_support 54 | 55 | // other 56 | api deps.kotlin.stdlib 57 | api deps.event_bus 58 | api deps.gson 59 | api deps.permission 60 | api deps.utils 61 | api deps.glide 62 | 63 | //view 64 | api deps.photo_view 65 | api deps.easy_recycler 66 | api deps.material_dialog 67 | api deps.logger 68 | api deps.toasty 69 | 70 | //router 71 | api deps.arouter_api 72 | 73 | //annotationProcessor 74 | annotationProcessor deps.dagger.android_support_compiler 75 | annotationProcessor deps.dagger.compiler 76 | } 77 | -------------------------------------------------------------------------------- /lib_common/libs/simple-xml-core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/lib_common/libs/simple-xml-core.jar -------------------------------------------------------------------------------- /lib_common/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/BaseActionBarActivity.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Keep; 5 | import android.support.annotation.StringRes; 6 | import android.support.v7.app.ActionBar; 7 | 8 | import com.guiying.module.common.R; 9 | 10 | /** 11 | * BaseActionBarActivity继承于BaseActivity,封装了actionBar的逻辑; 12 | * 继承于ActionBarBaseActivity的Activity都将默认带有ActionBar,并且只能使用AppTheme主题; 13 | * 只有那些ActionBar只带有Title和返回按钮的Activity方可继承 14 | * 15 | * @author 张华洋 2017/3/7 18:36 16 | * @version V1.2.0 17 | * @name BaseActionBarActivity 18 | */ 19 | @Keep 20 | public abstract class BaseActionBarActivity extends BaseActivity { 21 | 22 | /*默认的ActionBar*/ 23 | protected ActionBar mActionBar; 24 | 25 | /** 26 | * 设置默认标题id 27 | * 28 | * @return 标题id 29 | */ 30 | @StringRes 31 | protected abstract int setTitleId(); 32 | 33 | 34 | /** 35 | * 更新标题 36 | * 37 | * @param title String标题 38 | */ 39 | protected void setTitle(String title) { 40 | if (mActionBar != null) { 41 | mActionBar.setTitle(title); 42 | } 43 | } 44 | 45 | @Override 46 | protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | //标题栏设置 49 | mActionBar = getSupportActionBar(); 50 | if (mActionBar != null) { 51 | mActionBar.setHomeAsUpIndicator(R.drawable.ic_arrow_back); 52 | mActionBar.setDisplayHomeAsUpEnabled(true); 53 | mActionBar.setHomeButtonEnabled(true); 54 | mActionBar.setTitle(setTitleId()); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.IdRes; 5 | import android.support.annotation.Keep; 6 | import android.support.v7.app.ActionBar; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | import android.view.View; 10 | 11 | import com.guiying.module.common.R; 12 | import com.guiying.module.common.utils.Utils; 13 | 14 | /** 15 | *

Activity基类

16 | * 17 | * @author 2016/12/2 17:33 18 | * @version V1.0.0 19 | * @name BaseActivity 20 | */ 21 | @Keep 22 | public abstract class BaseActivity extends AppCompatActivity { 23 | 24 | 25 | /** 26 | * 封装的findViewByID方法 27 | */ 28 | @SuppressWarnings("unchecked") 29 | protected T $(@IdRes int id) { 30 | return (T) super.findViewById(id); 31 | } 32 | 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | ViewManager.getInstance().addActivity(this); 38 | } 39 | 40 | 41 | @Override 42 | protected void onDestroy() { 43 | super.onDestroy(); 44 | ViewManager.getInstance().finishActivity(this); 45 | } 46 | 47 | @Override 48 | public boolean onSupportNavigateUp() { 49 | onBackPressed(); 50 | return true; 51 | } 52 | 53 | 54 | /** 55 | * Setup the toolbar. 56 | * 57 | * @param toolbar toolbar 58 | * @param hideTitle 是否隐藏Title 59 | */ 60 | protected void setupToolBar(Toolbar toolbar, boolean hideTitle) { 61 | setSupportActionBar(toolbar); 62 | ActionBar actionBar = getSupportActionBar(); 63 | if (actionBar != null) { 64 | actionBar.setHomeAsUpIndicator(R.drawable.ic_arrow_back); 65 | actionBar.setDisplayHomeAsUpEnabled(true); 66 | actionBar.setDisplayShowHomeEnabled(true); 67 | if (hideTitle) { 68 | //隐藏Title 69 | actionBar.setDisplayShowTitleEnabled(false); 70 | } 71 | } 72 | } 73 | 74 | 75 | /** 76 | * 添加fragment 77 | * 78 | * @param fragment 79 | * @param frameId 80 | */ 81 | protected void addFragment(BaseFragment fragment, @IdRes int frameId) { 82 | Utils.checkNotNull(fragment); 83 | getSupportFragmentManager().beginTransaction() 84 | .add(frameId, fragment, fragment.getClass().getSimpleName()) 85 | .addToBackStack(fragment.getClass().getSimpleName()) 86 | .commitAllowingStateLoss(); 87 | 88 | } 89 | 90 | 91 | /** 92 | * 替换fragment 93 | * @param fragment 94 | * @param frameId 95 | */ 96 | protected void replaceFragment(BaseFragment fragment, @IdRes int frameId) { 97 | Utils.checkNotNull(fragment); 98 | getSupportFragmentManager().beginTransaction() 99 | .replace(frameId, fragment, fragment.getClass().getSimpleName()) 100 | .addToBackStack(fragment.getClass().getSimpleName()) 101 | .commitAllowingStateLoss(); 102 | 103 | } 104 | 105 | 106 | /** 107 | * 隐藏fragment 108 | * @param fragment 109 | */ 110 | protected void hideFragment(BaseFragment fragment) { 111 | Utils.checkNotNull(fragment); 112 | getSupportFragmentManager().beginTransaction() 113 | .hide(fragment) 114 | .commitAllowingStateLoss(); 115 | 116 | } 117 | 118 | 119 | /** 120 | * 显示fragment 121 | * @param fragment 122 | */ 123 | protected void showFragment(BaseFragment fragment) { 124 | Utils.checkNotNull(fragment); 125 | getSupportFragmentManager().beginTransaction() 126 | .show(fragment) 127 | .commitAllowingStateLoss(); 128 | 129 | } 130 | 131 | 132 | /** 133 | * 移除fragment 134 | * @param fragment 135 | */ 136 | protected void removeFragment(BaseFragment fragment) { 137 | Utils.checkNotNull(fragment); 138 | getSupportFragmentManager().beginTransaction() 139 | .remove(fragment) 140 | .commitAllowingStateLoss(); 141 | 142 | } 143 | 144 | 145 | /** 146 | * 弹出栈顶部的Fragment 147 | */ 148 | protected void popFragment() { 149 | if (getSupportFragmentManager().getBackStackEntryCount() > 1) { 150 | getSupportFragmentManager().popBackStack(); 151 | } else { 152 | finish(); 153 | } 154 | } 155 | 156 | 157 | } 158 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/BaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | import android.app.Application; 4 | 5 | import com.guiying.module.common.utils.Utils; 6 | import com.orhanobut.logger.LogLevel; 7 | import com.orhanobut.logger.Logger; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * 要想使用BaseApplication,必须在组件中实现自己的Application,并且继承BaseApplication; 13 | * 组件中实现的Application必须在debug包中的AndroidManifest.xml中注册,否则无法使用; 14 | * 组件的Application需置于java/debug文件夹中,不得放于主代码; 15 | * 组件中获取Context的方法必须为:Utils.getContext(),不允许其他写法; 16 | * 17 | * @author 2016/12/2 17:02 18 | * @version V1.0.0 19 | * @name BaseApplication 20 | */ 21 | public class BaseApplication extends Application { 22 | 23 | public static final String ROOT_PACKAGE = "com.guiying.module"; 24 | 25 | private static BaseApplication sInstance; 26 | 27 | private List mAppDelegateList; 28 | 29 | 30 | public static BaseApplication getIns() { 31 | return sInstance; 32 | } 33 | 34 | @Override 35 | public void onCreate() { 36 | super.onCreate(); 37 | sInstance = this; 38 | Logger.init("pattern").logLevel(LogLevel.FULL); 39 | Utils.init(this); 40 | mAppDelegateList = ClassUtils.getObjectsWithInterface(this, IApplicationDelegate.class, ROOT_PACKAGE); 41 | for (IApplicationDelegate delegate : mAppDelegateList) { 42 | delegate.onCreate(); 43 | } 44 | 45 | } 46 | 47 | @Override 48 | public void onTerminate() { 49 | super.onTerminate(); 50 | for (IApplicationDelegate delegate : mAppDelegateList) { 51 | delegate.onTerminate(); 52 | } 53 | } 54 | 55 | 56 | @Override 57 | public void onLowMemory() { 58 | super.onLowMemory(); 59 | for (IApplicationDelegate delegate : mAppDelegateList) { 60 | delegate.onLowMemory(); 61 | } 62 | } 63 | 64 | @Override 65 | public void onTrimMemory(int level) { 66 | super.onTrimMemory(level); 67 | for (IApplicationDelegate delegate : mAppDelegateList) { 68 | delegate.onTrimMemory(level); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.IdRes; 5 | import android.support.annotation.Keep; 6 | import android.support.v4.app.Fragment; 7 | 8 | import com.guiying.module.common.utils.Utils; 9 | 10 | /** 11 | *

Fragment的基类

12 | * 13 | * @author 张华洋 14 | * @name BaseFragment 15 | */ 16 | @Keep 17 | public abstract class BaseFragment extends Fragment { 18 | 19 | protected BaseActivity mActivity; 20 | 21 | @Override 22 | public void onAttach(Context context) { 23 | super.onAttach(context); 24 | this.mActivity = (BaseActivity) context; 25 | } 26 | 27 | 28 | /** 29 | * 获取宿主Activity 30 | * 31 | * @return BaseActivity 32 | */ 33 | protected BaseActivity getHoldingActivity() { 34 | return mActivity; 35 | } 36 | 37 | 38 | /** 39 | * 添加fragment 40 | * 41 | * @param fragment 42 | * @param frameId 43 | */ 44 | protected void addFragment(BaseFragment fragment, @IdRes int frameId) { 45 | Utils.checkNotNull(fragment); 46 | getHoldingActivity().addFragment(fragment, frameId); 47 | 48 | } 49 | 50 | 51 | /** 52 | * 替换fragment 53 | * 54 | * @param fragment 55 | * @param frameId 56 | */ 57 | protected void replaceFragment(BaseFragment fragment, @IdRes int frameId) { 58 | Utils.checkNotNull(fragment); 59 | getHoldingActivity().replaceFragment(fragment, frameId); 60 | } 61 | 62 | 63 | /** 64 | * 隐藏fragment 65 | * 66 | * @param fragment 67 | */ 68 | protected void hideFragment(BaseFragment fragment) { 69 | Utils.checkNotNull(fragment); 70 | getHoldingActivity().hideFragment(fragment); 71 | } 72 | 73 | 74 | /** 75 | * 显示fragment 76 | * 77 | * @param fragment 78 | */ 79 | protected void showFragment(BaseFragment fragment) { 80 | Utils.checkNotNull(fragment); 81 | getHoldingActivity().showFragment(fragment); 82 | } 83 | 84 | 85 | /** 86 | * 移除Fragment 87 | * 88 | * @param fragment 89 | */ 90 | protected void removeFragment(BaseFragment fragment) { 91 | Utils.checkNotNull(fragment); 92 | getHoldingActivity().removeFragment(fragment); 93 | 94 | } 95 | 96 | 97 | /** 98 | * 弹出栈顶部的Fragment 99 | */ 100 | protected void popFragment() { 101 | getHoldingActivity().popFragment(); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | import android.support.annotation.Keep; 4 | 5 | /** 6 | *

Presenter的基类

7 | * 8 | * @author 张华洋 9 | * @name BasePresenter 10 | */ 11 | @Keep 12 | public interface BasePresenter { 13 | 14 | void start(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/BaseView.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | 4 | import android.support.annotation.Keep; 5 | 6 | /** 7 | *

View接口的基类

8 | * 9 | * @author 张华洋 10 | * @name BaseView 11 | */ 12 | @Keep 13 | public interface BaseView { 14 | 15 | void setPresenter(T presenter); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/IApplicationDelegate.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | import android.support.annotation.Keep; 4 | 5 | /** 6 | *

类说明

7 | * 8 | * @author 张华洋 2017/9/20 22:23 9 | * @version V2.8.3 10 | * @name ApplicationDelegate 11 | */ 12 | @Keep 13 | public interface IApplicationDelegate { 14 | 15 | void onCreate(); 16 | 17 | void onTerminate(); 18 | 19 | void onLowMemory(); 20 | 21 | void onTrimMemory(int level); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/IViewDelegate.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | 4 | import android.support.annotation.Keep; 5 | import android.view.View; 6 | 7 | /** 8 | *

类说明

9 | * 10 | * @author 张华洋 2018/1/4 22:10 11 | * @version V2.8.3 12 | * @name IFragmentDelegate 13 | */ 14 | @Keep 15 | public interface IViewDelegate { 16 | 17 | BaseFragment getFragment(String name); 18 | 19 | View getView(String name); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/InfoCallback.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | import android.support.annotation.Keep; 4 | 5 | /** 6 | *

数据回调接口

7 | * 8 | * @author 张华洋 2017/3/22 13:36 9 | * @version V1.2.0 10 | * @name InfoCallback 11 | */ 12 | @Keep 13 | public interface InfoCallback { 14 | 15 | void onSuccess(T info); 16 | 17 | void onError(int code, String message); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/base/ViewManager.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.base; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.support.annotation.Keep; 6 | import android.util.Log; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Stack; 11 | 12 | /** 13 | *

14 | * 15 | * @author 张华洋 2017/9/26 22:26 16 | * @version V1.1 17 | * @name ViewManager 18 | */ 19 | @Keep 20 | public class ViewManager { 21 | 22 | private static Stack activityStack; 23 | private static List fragmentList; 24 | 25 | public static ViewManager getInstance() { 26 | return ViewManagerHolder.sInstance; 27 | } 28 | 29 | private static class ViewManagerHolder { 30 | private static final ViewManager sInstance = new ViewManager(); 31 | } 32 | 33 | private ViewManager() { 34 | } 35 | 36 | public void addFragment(int index, BaseFragment fragment) { 37 | if (fragmentList == null) { 38 | fragmentList = new ArrayList<>(); 39 | } 40 | fragmentList.add(index, fragment); 41 | } 42 | 43 | 44 | public BaseFragment getFragment(int index) { 45 | if (fragmentList != null) { 46 | return fragmentList.get(index); 47 | } 48 | return null; 49 | } 50 | 51 | 52 | public List getAllFragment() { 53 | if (fragmentList != null) { 54 | return fragmentList; 55 | } 56 | return null; 57 | } 58 | 59 | 60 | /** 61 | * 添加指定Activity到堆栈 62 | */ 63 | public void addActivity(Activity activity) { 64 | if (activityStack == null) { 65 | activityStack = new Stack(); 66 | } 67 | activityStack.add(activity); 68 | } 69 | 70 | 71 | /** 72 | * 获取当前Activity 73 | */ 74 | public Activity currentActivity() { 75 | Activity activity = activityStack.lastElement(); 76 | return activity; 77 | } 78 | 79 | 80 | /** 81 | * 结束当前Activity 82 | */ 83 | public void finishActivity() { 84 | Activity activity = activityStack.lastElement(); 85 | finishActivity(activity); 86 | } 87 | 88 | 89 | /** 90 | * 结束指定的Activity 91 | */ 92 | public void finishActivity(Activity activity) { 93 | if (activity != null) { 94 | activityStack.remove(activity); 95 | activity.finish(); 96 | activity = null; 97 | } 98 | } 99 | 100 | 101 | /** 102 | * 结束指定Class的Activity 103 | */ 104 | public void finishActivity(Class cls) { 105 | for (Activity activity : activityStack) { 106 | if (activity.getClass().equals(cls)) { 107 | finishActivity(activity); 108 | return; 109 | } 110 | } 111 | } 112 | 113 | 114 | /** 115 | * 结束全部的Activity 116 | */ 117 | public void finishAllActivity() { 118 | for (int i = 0, size = activityStack.size(); i < size; i++) { 119 | if (null != activityStack.get(i)) { 120 | activityStack.get(i).finish(); 121 | } 122 | } 123 | activityStack.clear(); 124 | } 125 | 126 | 127 | /** 128 | * 退出应用程序 129 | */ 130 | public void exitApp(Context context) { 131 | try { 132 | finishAllActivity(); 133 | //杀死后台进程需要在AndroidManifest中声明android.permission.KILL_BACKGROUND_PROCESSES; 134 | android.app.ActivityManager activityManager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 135 | activityManager.killBackgroundProcesses(context.getPackageName()); 136 | //System.exit(0); 137 | } catch (Exception e) { 138 | Log.e("ActivityManager", "app exit" + e.getMessage()); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/glide/ImageUtils.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.glide; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.drawable.Drawable; 6 | import android.view.View; 7 | import android.widget.ImageView; 8 | 9 | import com.bumptech.glide.Glide; 10 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 11 | import com.bumptech.glide.load.resource.drawable.GlideDrawable; 12 | import com.bumptech.glide.request.animation.GlideAnimation; 13 | import com.bumptech.glide.request.target.GlideDrawableImageViewTarget; 14 | import com.bumptech.glide.request.target.SimpleTarget; 15 | import com.guiying.module.common.utils.Utils; 16 | 17 | /** 18 | *

图片加载工具类

19 | * 20 | * @name ImageUtils 21 | */ 22 | public class ImageUtils { 23 | 24 | /** 25 | * 默认加载 26 | */ 27 | public static void loadImageView(String path, ImageView mImageView) { 28 | Glide.with(mImageView.getContext()).load(path).into(mImageView); 29 | } 30 | 31 | public static void loadImageWithError(String path, int errorRes, ImageView mImageView) { 32 | Glide.with(mImageView.getContext()) 33 | .load(path) 34 | .crossFade() 35 | .diskCacheStrategy(DiskCacheStrategy.SOURCE) 36 | .error(errorRes) 37 | .into(mImageView); 38 | } 39 | 40 | /** 41 | * 设置加载中以及加载失败图片 42 | */ 43 | public static void loadImageWithLoading(String path, ImageView mImageView, int lodingImage, int errorRes) { 44 | Glide.with(mImageView.getContext()).load(path).placeholder(lodingImage). 45 | error(errorRes).into(mImageView); 46 | } 47 | 48 | /** 49 | * 设置加载动画 50 | * api也提供了几个常用的动画:比如crossFade() 51 | */ 52 | public static void loadImageViewAnim(String path, int anim, ImageView mImageView) { 53 | Glide.with(mImageView.getContext()).load(path).animate(anim).into(mImageView); 54 | } 55 | 56 | 57 | /** 58 | * 加载为bitmap 59 | * 60 | * @param path 图片地址 61 | * @param listener 回调 62 | */ 63 | public static void loadBitMap(String path, final onLoadBitmap listener) { 64 | Glide.with(Utils.getContext()).load(path).asBitmap().into(new SimpleTarget() { 65 | 66 | @Override 67 | public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) { 68 | listener.onReady(bitmap); 69 | } 70 | 71 | @Override 72 | public void onLoadFailed(Exception e, Drawable errorDrawable) { 73 | listener.onFailed(); 74 | } 75 | }); 76 | } 77 | 78 | /** 79 | * 显示加载进度 80 | * 81 | * @param path 图片地址 82 | * @param mImageView 图片控件 83 | * @param loadView 加载view 84 | */ 85 | public static void loadImageWithProgress(String path, final ImageView mImageView, final View loadView, int errorRes) { 86 | Glide.with(mImageView.getContext()).load(path).error(errorRes).into(new GlideDrawableImageViewTarget(mImageView) { 87 | @Override 88 | public void onResourceReady(GlideDrawable resource, GlideAnimation animation) { 89 | super.onResourceReady(resource, animation); 90 | loadView.setVisibility(View.GONE); 91 | } 92 | 93 | @Override 94 | public void onLoadFailed(Exception e, Drawable errorDrawable) { 95 | super.onLoadFailed(e, errorDrawable); 96 | loadView.setVisibility(View.GONE); 97 | } 98 | }); 99 | } 100 | 101 | /** 102 | * 清除view上的图片 103 | * 104 | * @param view 视图 105 | */ 106 | public static void clearImageView(View view) { 107 | Glide.clear(view); 108 | } 109 | 110 | /** 111 | * 清理磁盘缓存需要在子线程中执行 112 | */ 113 | public static void GuideClearDiskCache(Context mContext) { 114 | Glide.get(mContext).clearDiskCache(); 115 | } 116 | 117 | /** 118 | * 清理内存缓存可以在UI主线程中进行 119 | */ 120 | public static void GuideClearMemory(Context mContext) { 121 | Glide.get(mContext).clearMemory(); 122 | } 123 | 124 | /** 125 | * 加载bitmap回调 126 | */ 127 | public interface onLoadBitmap { 128 | void onReady(Bitmap resource); 129 | 130 | void onFailed(); 131 | } 132 | 133 | } -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/glide/OkHttpGlideModule.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.glide; 2 | 3 | import android.content.Context; 4 | 5 | import com.bumptech.glide.Glide; 6 | import com.bumptech.glide.GlideBuilder; 7 | import com.bumptech.glide.load.DecodeFormat; 8 | import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool; 9 | import com.bumptech.glide.load.engine.cache.LruResourceCache; 10 | import com.bumptech.glide.load.engine.cache.MemorySizeCalculator; 11 | import com.bumptech.glide.module.GlideModule; 12 | 13 | /** 14 | * A {@link GlideModule} implementation to replace Glide's default 15 | * {@link java.net.HttpURLConnection} based {@link com.bumptech.glide.load.model.ModelLoader} with an OkHttp based 16 | * {@link com.bumptech.glide.load.model.ModelLoader}. 17 | *

18 | *

19 | * If you're using gradle, you can include this module simply by depending on the aar, the module will be merged 20 | * in by manifest merger. For other build systems or for more more information, see 21 | * {@link GlideModule}. 22 | *

23 | */ 24 | public class OkHttpGlideModule implements GlideModule { 25 | 26 | @Override 27 | public void applyOptions(Context context, GlideBuilder builder) { 28 | builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); 29 | 30 | MemorySizeCalculator calculator = new MemorySizeCalculator(context); 31 | int defaultMemoryCacheSize = calculator.getMemoryCacheSize(); 32 | int defaultBitmapPoolSize = calculator.getBitmapPoolSize(); 33 | 34 | int customMemoryCacheSize = (int) (1.2 * defaultMemoryCacheSize); 35 | int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize); 36 | 37 | builder.setMemoryCache(new LruResourceCache(customMemoryCacheSize)); 38 | builder.setBitmapPool(new LruBitmapPool(customBitmapPoolSize)); 39 | } 40 | 41 | @Override 42 | public void registerComponents(Context context, Glide glide) { 43 | // HttpsUtil.SSLParams sslParams = HttpsUtil.getSslSocketFactory(BaseApplication.context, null, , ""); 44 | // OkHttpClient okHttpClient = new OkHttpClient.Builder() 45 | // .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager) 46 | // .hostnameVerifier(new HostnameVerifier() { 47 | // @Override 48 | // public boolean verify(String hostname, SSLSession session) { 49 | // return true; 50 | // } 51 | // }) 52 | // .build(); 53 | // glide.register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okHttpClient)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/glide/OkHttpStreamFetcher.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.glide; 2 | 3 | import com.bumptech.glide.Priority; 4 | import com.bumptech.glide.load.data.DataFetcher; 5 | import com.bumptech.glide.load.model.GlideUrl; 6 | import com.bumptech.glide.util.ContentLengthInputStream; 7 | import com.guiying.module.common.utils.CloseUtils; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.util.Map; 12 | 13 | import okhttp3.OkHttpClient; 14 | import okhttp3.Request; 15 | import okhttp3.Response; 16 | import okhttp3.ResponseBody; 17 | 18 | /** 19 | * Fetches an {@link InputStream} using the okhttp library. 20 | */ 21 | public class OkHttpStreamFetcher implements DataFetcher { 22 | private final OkHttpClient client; 23 | private final GlideUrl url; 24 | private InputStream stream; 25 | private ResponseBody responseBody; 26 | 27 | public OkHttpStreamFetcher(OkHttpClient client, GlideUrl url) { 28 | this.client = client; 29 | this.url = url; 30 | } 31 | 32 | @Override 33 | public InputStream loadData(Priority priority) throws Exception { 34 | Request.Builder requestBuilder = new Request.Builder() 35 | .url(url.toStringUrl()); 36 | 37 | for (Map.Entry headerEntry : url.getHeaders().entrySet()) { 38 | String key = headerEntry.getKey(); 39 | requestBuilder.addHeader(key, headerEntry.getValue()); 40 | } 41 | 42 | Request request = requestBuilder.build(); 43 | 44 | Response response = client.newCall(request).execute(); 45 | responseBody = response.body(); 46 | if (!response.isSuccessful()) { 47 | throw new IOException("Request failed with code: " + response.code()); 48 | } 49 | 50 | long contentLength = responseBody.contentLength(); 51 | stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength); 52 | return stream; 53 | } 54 | 55 | @Override 56 | public void cleanup() { 57 | if (stream != null) { 58 | try { 59 | stream.close(); 60 | } catch (IOException e) { 61 | // Ignored 62 | } 63 | } 64 | if (responseBody != null) { 65 | CloseUtils.closeIO(responseBody); 66 | } 67 | } 68 | 69 | @Override 70 | public String getId() { 71 | return url.getCacheKey(); 72 | } 73 | 74 | @Override 75 | public void cancel() { 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/glide/OkHttpUrlLoader.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.glide; 2 | 3 | import android.content.Context; 4 | 5 | import com.bumptech.glide.load.data.DataFetcher; 6 | import com.bumptech.glide.load.model.GenericLoaderFactory; 7 | import com.bumptech.glide.load.model.GlideUrl; 8 | import com.bumptech.glide.load.model.ModelLoader; 9 | import com.bumptech.glide.load.model.ModelLoaderFactory; 10 | 11 | import java.io.InputStream; 12 | 13 | import okhttp3.OkHttpClient; 14 | 15 | /** 16 | * A simple model loader for fetching media over http/https using OkHttp. 17 | */ 18 | public class OkHttpUrlLoader implements ModelLoader { 19 | 20 | /** 21 | * The default factory for {@link OkHttpUrlLoader}s. 22 | */ 23 | public static class Factory implements ModelLoaderFactory { 24 | private static volatile OkHttpClient internalClient; 25 | private OkHttpClient client; 26 | 27 | private static OkHttpClient getInternalClient() { 28 | if (internalClient == null) { 29 | synchronized (Factory.class) { 30 | if (internalClient == null) { 31 | internalClient = new OkHttpClient(); 32 | } 33 | } 34 | } 35 | return internalClient; 36 | } 37 | 38 | /** 39 | * Constructor for a new Factory that runs requests using a static singleton client. 40 | */ 41 | public Factory() { 42 | this(getInternalClient()); 43 | } 44 | 45 | /** 46 | * Constructor for a new Factory that runs requests using given client. 47 | */ 48 | public Factory(OkHttpClient client) { 49 | this.client = client; 50 | } 51 | 52 | @Override 53 | public ModelLoader build(Context context, GenericLoaderFactory factories) { 54 | return new OkHttpUrlLoader(client); 55 | } 56 | 57 | @Override 58 | public void teardown() { 59 | // Do nothing, this instance doesn't own the client. 60 | } 61 | } 62 | 63 | private final OkHttpClient client; 64 | 65 | public OkHttpUrlLoader(OkHttpClient client) { 66 | this.client = client; 67 | } 68 | 69 | @Override 70 | public DataFetcher getResourceFetcher(GlideUrl model, int width, int height) { 71 | return new OkHttpStreamFetcher(client, model); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/http/ApiService.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.http; 2 | 3 | import java.util.Map; 4 | 5 | import okhttp3.ResponseBody; 6 | import retrofit2.Call; 7 | import retrofit2.http.FieldMap; 8 | import retrofit2.http.FormUrlEncoded; 9 | import retrofit2.http.GET; 10 | import retrofit2.http.HeaderMap; 11 | import retrofit2.http.POST; 12 | import retrofit2.http.Streaming; 13 | import retrofit2.http.Url; 14 | 15 | /** 16 | *

17 | * 注意:如果方法的泛型指定的类不是ResponseBody,retrofit会将返回的string用json转换器自动转换该类的一个对象,转换不成功就报错 18 | * 如果不需要Gson转换,那么就指定泛型为ResponseBody,只能是ResponseBody,子类都不行. 19 | *

20 | * 21 | * @author 张华洋 2016/12/5 15:22 22 | * @version V1.0.0 23 | * @name HttpParams 24 | */ 25 | public interface ApiService { 26 | 27 | @GET 28 | Call executeGet(@Url String url); 29 | 30 | /** 31 | * POST方式将以表单的方式传递键值对作为请求体发送到服务器 32 | * 其中@FormUrlEncoded 以表单的方式传递键值对 33 | * 其中 @Path:所有在网址中的参数(URL的问号前面) 34 | * 另外@FieldMap 用于POST请求,提交多个表单数据,@Field:用于POST请求,提交单个数据 35 | * 使用@url是为了防止URL被转义为https://10.33.31.200:8890/msp%2Fmobile%2Flogin%3 36 | */ 37 | @FormUrlEncoded 38 | @POST 39 | Call executePost(@Url String url, @FieldMap Map map); 40 | 41 | 42 | /** 43 | * 流式下载,不加这个注解的话,会整个文件字节数组全部加载进内存,可能导致oom 44 | */ 45 | @Streaming 46 | @GET 47 | Call download(@Url String fileUrl, @HeaderMap Map headers); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/http/DataParseUtil.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.http; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.google.gson.Gson; 6 | import com.google.gson.JsonObject; 7 | import com.google.gson.reflect.TypeToken; 8 | 9 | import org.simpleframework.xml.Serializer; 10 | import org.simpleframework.xml.core.Persister; 11 | 12 | import java.io.ByteArrayInputStream; 13 | import java.io.InputStreamReader; 14 | import java.lang.reflect.Type; 15 | import java.util.ArrayList; 16 | import java.util.Arrays; 17 | import java.util.List; 18 | 19 | /** 20 | *

21 | * 服务器返回数据的解析工具; 22 | * 支持XML,json对象,json数组 23 | *

24 | * 25 | * @author 张华洋 2017/1/9 16:00 26 | * @version V1.2.0 27 | * @name DataParseUtil 28 | */ 29 | 30 | 31 | public class DataParseUtil { 32 | 33 | private DataParseUtil() { 34 | throw new UnsupportedOperationException("u can't instantiate me..."); 35 | } 36 | 37 | /** 38 | * 解析json对象 39 | * 40 | * @param string 要解析的json 41 | * @param clazz 解析类 42 | */ 43 | public static T parseObject(String string, Class clazz) { 44 | return new Gson().fromJson(string, clazz); 45 | } 46 | 47 | /** 48 | * 解析json数组为ArrayList 49 | * 50 | * @param json 要解析的json 51 | * @param clazz 解析类 52 | * @return ArrayList 53 | */ 54 | public static ArrayList parseToArrayList(String json, Class clazz) { 55 | Type type = new TypeToken>() { 56 | }.getType(); 57 | ArrayList jsonObjects = new Gson().fromJson(json, type); 58 | ArrayList arrayList = new ArrayList<>(); 59 | for (JsonObject jsonObject : jsonObjects) { 60 | arrayList.add(new Gson().fromJson(jsonObject, clazz)); 61 | } 62 | return arrayList; 63 | } 64 | 65 | /** 66 | * 解析json数组为List 67 | * 68 | * @param json 要解析的json 69 | * @param clazz 解析类 70 | * @return List 71 | */ 72 | public static List parseToList(String json, Class clazz) { 73 | Gson gson = new Gson(); 74 | T[] array = gson.fromJson(json, clazz); 75 | return Arrays.asList(array); 76 | } 77 | 78 | 79 | /** 80 | * 解析Xml格式数据 81 | * 82 | * @param json 要解析的json 83 | * @param clazz 解析类 84 | */ 85 | public static Object parseXml(String json, Class clazz) { 86 | try { 87 | if (!TextUtils.isEmpty(json) && clazz != null) { 88 | Serializer serializer = new Persister(); 89 | InputStreamReader is = new InputStreamReader(new ByteArrayInputStream(json.getBytes("UTF-8")), "utf-8"); 90 | return serializer.read(clazz, is); 91 | } 92 | } catch (Exception e) { 93 | e.printStackTrace(); 94 | } 95 | return null; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/http/DataType.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.http; 2 | 3 | import android.support.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | /** 9 | *

服务端响应的数据类型

10 | * 11 | * @author 张华洋 2017/5/2 21:53 12 | * @version V1.2.0 13 | * @name DataType 14 | */ 15 | public class DataType { 16 | 17 | /*返回数据为String*/ 18 | public static final int STRING = 1; 19 | /*返回数据为xml类型*/ 20 | public static final int XML = 2; 21 | /*返回数据为json对象*/ 22 | public static final int JSON_OBJECT = 3; 23 | /*返回数据为json数组*/ 24 | public static final int JSON_ARRAY = 4; 25 | 26 | /** 27 | * 自定义一个播放器状态注解 28 | */ 29 | @Retention(RetentionPolicy.SOURCE) 30 | @IntDef({STRING, XML, JSON_OBJECT, JSON_ARRAY}) 31 | public @interface Type { 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/http/HttpsUtils.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.http; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.RawRes; 5 | import android.text.TextUtils; 6 | 7 | import com.guiying.module.common.utils.CloseUtils; 8 | 9 | import java.io.ByteArrayInputStream; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.net.InetAddress; 13 | import java.net.Socket; 14 | import java.security.InvalidKeyException; 15 | import java.security.KeyManagementException; 16 | import java.security.KeyStore; 17 | import java.security.KeyStoreException; 18 | import java.security.NoSuchAlgorithmException; 19 | import java.security.NoSuchProviderException; 20 | import java.security.SecureRandom; 21 | import java.security.SignatureException; 22 | import java.security.UnrecoverableKeyException; 23 | import java.security.cert.Certificate; 24 | import java.security.cert.CertificateException; 25 | import java.security.cert.CertificateFactory; 26 | import java.security.cert.X509Certificate; 27 | 28 | import javax.net.ssl.HostnameVerifier; 29 | import javax.net.ssl.HttpsURLConnection; 30 | import javax.net.ssl.KeyManagerFactory; 31 | import javax.net.ssl.SSLContext; 32 | import javax.net.ssl.SSLSession; 33 | import javax.net.ssl.SSLSocket; 34 | import javax.net.ssl.SSLSocketFactory; 35 | import javax.net.ssl.TrustManager; 36 | import javax.net.ssl.TrustManagerFactory; 37 | import javax.net.ssl.X509TrustManager; 38 | 39 | /** 40 | *

Https证书校验工具类

41 | * 42 | * @author 张华洋 2017/5/11 16:14 43 | * @version V1.2.0 44 | * @name HttpsUtils 45 | */ 46 | public class HttpsUtils { 47 | 48 | 49 | public static class SSLParams { 50 | public SSLSocketFactory sSLSocketFactory; 51 | public X509TrustManager trustManager; 52 | } 53 | 54 | /** 55 | * @param context 上下文 56 | * @param bksFileId "XXX.bks"文件(文件位置res/raw/XXX.bks) 57 | * @param password The certificate's password. 58 | * @return SSLParams 59 | */ 60 | public static SSLParams getSslSocketFactory(Context context, @RawRes int bksFileId, String password, String alias) { 61 | if (context == null) { 62 | throw new NullPointerException("context == null"); 63 | } 64 | if (TextUtils.isEmpty(password) || TextUtils.isEmpty(alias)) { 65 | throw new NullPointerException("password == null or alias == null!"); 66 | } 67 | SSLParams sslParams = new SSLParams(); 68 | try { 69 | // 创建一个BKS类型的KeyStore,存储我们信任的证书 70 | KeyStore clientKeyStore = KeyStore.getInstance("BKS"); 71 | clientKeyStore.load(context.getResources().openRawResource(bksFileId), password.toCharArray()); 72 | //通过alias直接从密钥库中读取证书 73 | Certificate rootCA = clientKeyStore.getCertificate(alias); 74 | // Turn it to X509 format. 75 | InputStream certInput = new ByteArrayInputStream(rootCA.getEncoded()); 76 | X509Certificate serverCert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certInput); 77 | //关闭流 78 | CloseUtils.closeIO(certInput); 79 | 80 | TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 81 | //用我们之前的keyStore实例初始化TrustManagerFactory,这样trustManagerFactory就会信任keyStore中的证书 82 | trustManagerFactory.init(clientKeyStore); 83 | 84 | KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 85 | keyManagerFactory.init(clientKeyStore, password.toCharArray()); 86 | 87 | X509TrustManager x509TrustManager = new SafeTrustManager(serverCert); 88 | 89 | //创建TLS类型的SSLContext对象,that uses our TrustManager 90 | SSLContext sslContext = SSLContext.getInstance("TLS"); 91 | 92 | //用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书 93 | sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); 94 | 95 | //Android 4.X 对TLS1.1、TLS1.2的支持 96 | sslParams.sSLSocketFactory = new Tls12SocketFactory(sslContext.getSocketFactory()); 97 | sslParams.trustManager = x509TrustManager; 98 | return sslParams; 99 | } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException | IOException | CertificateException e) { 100 | throw new AssertionError(e); 101 | } 102 | } 103 | 104 | /** 105 | * 不做证书校验,信任所有证书 106 | */ 107 | public static SSLParams getSslSocketFactoryUnsafe() { 108 | SSLParams sslParams = new SSLParams(); 109 | try { 110 | X509TrustManager x509TrustManager = new UnSafeTrustManager(); 111 | 112 | //创建TLS类型的SSLContext对象,that uses our TrustManager 113 | SSLContext sslContext = SSLContext.getInstance("TLS"); 114 | 115 | //用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书 116 | sslContext.init(null, new TrustManager[]{x509TrustManager}, null); 117 | 118 | //Android 4.X 对TLS1.1、TLS1.2的支持 119 | sslParams.sSLSocketFactory = new Tls12SocketFactory(sslContext.getSocketFactory()); 120 | sslParams.trustManager = x509TrustManager; 121 | return sslParams; 122 | } catch (NoSuchAlgorithmException | KeyManagementException e) { 123 | throw new AssertionError(e); 124 | } 125 | } 126 | 127 | 128 | /** 129 | * 主机名校验方法,请把”192.168.0.10”换成你们公司的主机IP: 130 | */ 131 | public static HostnameVerifier getHostnameVerifier() { 132 | return new HostnameVerifier() { 133 | @Override 134 | public boolean verify(String hostname, SSLSession session) { 135 | if ("192.168.0.10".equals(hostname)) { 136 | return true; 137 | } else { 138 | HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); 139 | return hv.verify(hostname, session); 140 | } 141 | } 142 | }; 143 | } 144 | 145 | 146 | /** 147 | * 对服务器证书域名进行强校验 148 | */ 149 | private static class SafeTrustManager implements X509TrustManager { 150 | private X509Certificate mCertificate; 151 | 152 | private SafeTrustManager(X509Certificate serverCert) { 153 | mCertificate = serverCert; 154 | } 155 | 156 | @Override 157 | public void checkClientTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException { 158 | 159 | } 160 | 161 | @Override 162 | public void checkServerTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException { 163 | if (x509Certificates == null) { 164 | throw new IllegalArgumentException("Check Server x509Certificates is null"); 165 | } 166 | 167 | if (x509Certificates.length < 0) { 168 | throw new IllegalArgumentException("Check Server x509Certificates is empty"); 169 | } 170 | 171 | try { 172 | for (X509Certificate cert : x509Certificates) { 173 | // Make sure that it hasn't expired. 174 | cert.checkValidity(); 175 | //和App预埋的证书做对比 176 | cert.verify(mCertificate.getPublicKey()); 177 | } 178 | } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException | SignatureException e) { 179 | e.printStackTrace(); 180 | } 181 | } 182 | 183 | @Override 184 | public X509Certificate[] getAcceptedIssuers() { 185 | return new X509Certificate[0]; 186 | } 187 | } 188 | 189 | 190 | /** 191 | * 客户端不对证书做任何验证的做法有很大的安全漏洞。 192 | */ 193 | private static class UnSafeTrustManager implements X509TrustManager { 194 | 195 | @Override 196 | public void checkClientTrusted(X509Certificate[] chain, String authType) 197 | throws CertificateException { 198 | } 199 | 200 | @Override 201 | public void checkServerTrusted(X509Certificate[] chain, String authType) 202 | throws CertificateException { 203 | } 204 | 205 | @Override 206 | public X509Certificate[] getAcceptedIssuers() { 207 | return new X509Certificate[]{}; 208 | } 209 | } 210 | 211 | 212 | /** 213 | * 自定义SSLSocketFactory ,实现Android 4.X 对TLSv1.1、TLSv1.2的支持 214 | */ 215 | private static class Tls12SocketFactory extends SSLSocketFactory { 216 | 217 | private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"}; 218 | 219 | final SSLSocketFactory delegate; 220 | 221 | private Tls12SocketFactory(SSLSocketFactory base) { 222 | this.delegate = base; 223 | } 224 | 225 | @Override 226 | public String[] getDefaultCipherSuites() { 227 | return delegate.getDefaultCipherSuites(); 228 | } 229 | 230 | @Override 231 | public String[] getSupportedCipherSuites() { 232 | return delegate.getSupportedCipherSuites(); 233 | } 234 | 235 | @Override 236 | public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { 237 | return patch(delegate.createSocket(s, host, port, autoClose)); 238 | } 239 | 240 | @Override 241 | public Socket createSocket(String host, int port) throws IOException { 242 | return patch(delegate.createSocket(host, port)); 243 | } 244 | 245 | @Override 246 | public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { 247 | return patch(delegate.createSocket(host, port, localHost, localPort)); 248 | } 249 | 250 | @Override 251 | public Socket createSocket(InetAddress host, int port) throws IOException { 252 | return patch(delegate.createSocket(host, port)); 253 | } 254 | 255 | @Override 256 | public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { 257 | return patch(delegate.createSocket(address, port, localAddress, localPort)); 258 | } 259 | 260 | private Socket patch(Socket s) { 261 | //代理SSLSocketFactory在创建一个Socket连接的时候,会设置Socket的可用的TLS版本。 262 | if (s instanceof SSLSocket) { 263 | ((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION); 264 | } 265 | return s; 266 | } 267 | } 268 | 269 | } 270 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/http/LoggerInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.http; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.orhanobut.logger.Logger; 6 | 7 | import java.io.IOException; 8 | 9 | import okhttp3.Headers; 10 | import okhttp3.Interceptor; 11 | import okhttp3.MediaType; 12 | import okhttp3.Request; 13 | import okhttp3.RequestBody; 14 | import okhttp3.Response; 15 | import okhttp3.ResponseBody; 16 | import okio.Buffer; 17 | 18 | public class LoggerInterceptor implements Interceptor { 19 | 20 | public static final String TAG = "HttpClient"; 21 | private String tag; 22 | private boolean showResponse; 23 | 24 | public LoggerInterceptor(String tag, boolean showResponse) { 25 | if (TextUtils.isEmpty(tag)) { 26 | tag = TAG; 27 | } 28 | this.showResponse = showResponse; 29 | this.tag = tag; 30 | } 31 | 32 | public LoggerInterceptor(String tag) { 33 | this(tag, false); 34 | } 35 | 36 | @Override 37 | public Response intercept(Chain chain) throws IOException { 38 | 39 | Request request = chain.request(); 40 | logForRequest(request); 41 | Response response = chain.proceed(request); 42 | return logForResponse(response); 43 | } 44 | 45 | private void logForRequest(Request request) { 46 | try { 47 | String url = request.url().toString(); 48 | Headers headers = request.headers(); 49 | 50 | Logger.d("method : " + request.method() + " ║ url : " + url); 51 | if (headers != null && headers.size() > 0) { 52 | //Logger.d("headers : " + headers.toString()); 53 | } 54 | 55 | RequestBody requestBody = request.body(); 56 | if (requestBody != null) { 57 | MediaType mediaType = requestBody.contentType(); 58 | if (mediaType != null) { 59 | //Logger.d("requestBody's contentType : " + mediaType.toString()); 60 | if (isText(mediaType)) { 61 | Logger.d("requestBody's content : " + bodyToString(request)); 62 | } else { 63 | //Logger.e("requestBody's content : " + " maybe [file part] , too large too print , ignored!"); 64 | } 65 | } 66 | } 67 | } catch (Exception e) { 68 | // e.printStackTrace(); 69 | } 70 | } 71 | 72 | private Response logForResponse(Response response) { 73 | try { 74 | Response.Builder builder = response.newBuilder(); 75 | Response clone = builder.build(); 76 | Logger.d("url : " + clone.request().url() + " ║ code : " + clone.code() + " ║ protocol : " + clone.protocol()); 77 | if (!TextUtils.isEmpty(clone.message())) 78 | //Logger.d("message : " + clone.message()); 79 | 80 | if (showResponse) { 81 | ResponseBody body = clone.body(); 82 | if (body != null) { 83 | MediaType mediaType = body.contentType(); 84 | if (mediaType != null) { 85 | //Logger.d("responseBody's contentType : " + mediaType.toString()); 86 | if (isText(mediaType)) { 87 | String resp = body.string(); 88 | //打印json格式或者xml格式日志 89 | switch (mediaType.subtype()) { 90 | case "xml": 91 | Logger.xml(resp); 92 | break; 93 | case "json": 94 | Logger.json(resp); 95 | break; 96 | default: 97 | Logger.d(resp); 98 | break; 99 | } 100 | body = ResponseBody.create(mediaType, resp); 101 | return response.newBuilder().body(body).build(); 102 | } else { 103 | Logger.e("responseBody's content : " + " maybe [file part] , too large too print , ignored!"); 104 | } 105 | } 106 | } 107 | } 108 | } catch (Exception e) { 109 | // e.printStackTrace(); 110 | } 111 | 112 | return response; 113 | } 114 | 115 | 116 | private boolean isText(MediaType mediaType) { 117 | if (mediaType.type() != null && mediaType.type().equals("text")) { 118 | return true; 119 | } 120 | if (mediaType.subtype() != null) { 121 | if (mediaType.subtype().equals("json") || 122 | mediaType.subtype().equals("xml") || 123 | mediaType.subtype().equals("html") || 124 | mediaType.subtype().equals("webviewhtml") 125 | ) 126 | return true; 127 | } 128 | return false; 129 | } 130 | 131 | private String bodyToString(final Request request) { 132 | try { 133 | final Request copy = request.newBuilder().build(); 134 | final Buffer buffer = new Buffer(); 135 | copy.body().writeTo(buffer); 136 | return buffer.readUtf8(); 137 | } catch (final IOException e) { 138 | return "something error when show requestBody."; 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/http/OnResultListener.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.http; 2 | 3 | /** 4 | *

在Retrofit中接口会导致泛型擦除,所以这里回调使用Class

5 | * 6 | * @author 张华洋 2016/12/15 10:27 7 | * @version V1.0.0 8 | * @name OnResultListener 9 | */ 10 | public class OnResultListener { 11 | 12 | /** 13 | * 请求成功的情况 14 | * 15 | * @param result 需要解析的解析类 16 | */ 17 | public void onSuccess(T result) { 18 | } 19 | 20 | /** 21 | * 响应成功,但是出错的情况 22 | * 23 | * @param code 错误码 24 | * @param message 错误信息 25 | */ 26 | public void onError(int code, String message) { 27 | } 28 | 29 | /** 30 | * 请求失败的情况 31 | * 32 | * @param message 失败信息 33 | */ 34 | public void onFailure(String message) { 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/utils/CloseUtils.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.utils; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | 6 | /** 7 | * 关闭相关工具类 8 | */ 9 | public class CloseUtils { 10 | 11 | private CloseUtils() { 12 | throw new UnsupportedOperationException("u can't instantiate me..."); 13 | } 14 | 15 | /** 16 | * 关闭IO 17 | * 18 | * @param closeables closeable 19 | */ 20 | public static void closeIO(Closeable... closeables) { 21 | if (closeables == null) return; 22 | for (Closeable closeable : closeables) { 23 | if (closeable != null) { 24 | try { 25 | closeable.close(); 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | } 31 | } 32 | 33 | /** 34 | * 安静关闭IO 35 | * 36 | * @param closeables closeable 37 | */ 38 | public static void closeIOQuietly(Closeable... closeables) { 39 | if (closeables == null) return; 40 | for (Closeable closeable : closeables) { 41 | if (closeable != null) { 42 | try { 43 | closeable.close(); 44 | } catch (IOException ignored) { 45 | } 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/utils/ScreenLockUtil.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.utils; 2 | 3 | import android.app.Activity; 4 | import android.app.KeyguardManager; 5 | import android.app.KeyguardManager.KeyguardLock; 6 | import android.content.Context; 7 | import android.os.PowerManager; 8 | import android.os.PowerManager.WakeLock; 9 | import android.util.Log; 10 | 11 | import java.util.HashMap; 12 | 13 | /** 14 | * 用于保持屏幕高亮的工具 15 | */ 16 | public class ScreenLockUtil { 17 | private static final String TAG = "ScreenLockUtil"; 18 | 19 | private ScreenLockUtil() { 20 | throw new UnsupportedOperationException("cannot be instantiated"); 21 | } 22 | 23 | static private HashMap mWakeLockArray = new HashMap<>(); 24 | static private HashMap mIsUnlockArray = new HashMap<>(); 25 | 26 | 27 | /** 28 | * 保持屏幕常亮 29 | * 30 | * @param activity you know 31 | */ 32 | public static void keepScreenOn(Activity activity) { 33 | WakeLock wakeLock = mWakeLockArray.get(activity); 34 | if (wakeLock == null) { 35 | PowerManager powerManager = (PowerManager) activity.getSystemService(Context.POWER_SERVICE); 36 | wakeLock = powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.FULL_WAKE_LOCK, 37 | activity.getClass().getName()); 38 | } 39 | 40 | if (!wakeLock.isHeld()) { 41 | wakeLock.acquire(); 42 | } 43 | 44 | mWakeLockArray.put(activity, wakeLock); 45 | 46 | cancelLockScreen(activity); 47 | 48 | Log.i(TAG, "开启屏幕常亮"); 49 | } 50 | 51 | 52 | /** 53 | * 取消屏幕常亮 54 | * 55 | * @param activity you know 56 | */ 57 | public static void cancelKeepScreen(Activity activity) { 58 | WakeLock wakeLock = mWakeLockArray.get(activity); 59 | if (wakeLock != null) { 60 | if (wakeLock.isHeld()) { 61 | wakeLock.release(); 62 | } 63 | } 64 | 65 | Log.i(TAG, "取消屏幕常亮"); 66 | } 67 | 68 | /** 69 | * 取消锁屏限制 70 | * 71 | * @param activity you know 72 | */ 73 | private static void cancelLockScreen(Activity activity) { 74 | Boolean isUnlock = mIsUnlockArray.get(activity); 75 | if (isUnlock != null && isUnlock) { 76 | return; 77 | } 78 | KeyguardManager mKeyguardManager = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE); 79 | KeyguardLock mKeyguardLock = mKeyguardManager.newKeyguardLock(activity.getClass().getName()); 80 | mKeyguardLock.disableKeyguard(); 81 | 82 | mIsUnlockArray.put(activity, true); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/utils/ShellUtils.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.utils; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.DataOutputStream; 5 | import java.io.InputStreamReader; 6 | import java.util.List; 7 | 8 | /** 9 | * Shell相关工具类 10 | */ 11 | public class ShellUtils { 12 | 13 | private ShellUtils() { 14 | throw new UnsupportedOperationException("u can't instantiate me..."); 15 | } 16 | 17 | /** 18 | * 是否是在root下执行命令 19 | * 20 | * @param command 命令 21 | * @param isRoot 是否需要root权限执行 22 | * @return CommandResult 23 | */ 24 | public static CommandResult execCmd(String command, boolean isRoot) { 25 | return execCmd(new String[]{command}, isRoot, true); 26 | } 27 | 28 | /** 29 | * 是否是在root下执行命令 30 | * 31 | * @param commands 多条命令链表 32 | * @param isRoot 是否需要root权限执行 33 | * @return CommandResult 34 | */ 35 | public static CommandResult execCmd(List commands, boolean isRoot) { 36 | return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRoot, true); 37 | } 38 | 39 | /** 40 | * 是否是在root下执行命令 41 | * 42 | * @param commands 多条命令数组 43 | * @param isRoot 是否需要root权限执行 44 | * @return CommandResult 45 | */ 46 | public static CommandResult execCmd(String[] commands, boolean isRoot) { 47 | return execCmd(commands, isRoot, true); 48 | } 49 | 50 | /** 51 | * 是否是在root下执行命令 52 | * 53 | * @param command 命令 54 | * @param isRoot 是否需要root权限执行 55 | * @param isNeedResultMsg 是否需要结果消息 56 | * @return CommandResult 57 | */ 58 | public static CommandResult execCmd(String command, boolean isRoot, boolean isNeedResultMsg) { 59 | return execCmd(new String[]{command}, isRoot, isNeedResultMsg); 60 | } 61 | 62 | /** 63 | * 是否是在root下执行命令 64 | * 65 | * @param commands 命令链表 66 | * @param isRoot 是否需要root权限执行 67 | * @param isNeedResultMsg 是否需要结果消息 68 | * @return CommandResult 69 | */ 70 | public static CommandResult execCmd(List commands, boolean isRoot, boolean isNeedResultMsg) { 71 | return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg); 72 | } 73 | 74 | /** 75 | * 是否是在root下执行命令 76 | * 77 | * @param commands 命令数组 78 | * @param isRoot 是否需要root权限执行 79 | * @param isNeedResultMsg 是否需要结果消息 80 | * @return CommandResult 81 | */ 82 | public static CommandResult execCmd(String[] commands, boolean isRoot, boolean isNeedResultMsg) { 83 | int result = -1; 84 | if (commands == null || commands.length == 0) { 85 | return new CommandResult(result, null, null); 86 | } 87 | Process process = null; 88 | BufferedReader successResult = null; 89 | BufferedReader errorResult = null; 90 | StringBuilder successMsg = null; 91 | StringBuilder errorMsg = null; 92 | DataOutputStream os = null; 93 | try { 94 | process = Runtime.getRuntime().exec(isRoot ? "su" : "sh"); 95 | os = new DataOutputStream(process.getOutputStream()); 96 | for (String command : commands) { 97 | if (command == null) continue; 98 | os.write(command.getBytes()); 99 | os.writeBytes("\n"); 100 | os.flush(); 101 | } 102 | os.writeBytes("exit\n"); 103 | os.flush(); 104 | result = process.waitFor(); 105 | if (isNeedResultMsg) { 106 | successMsg = new StringBuilder(); 107 | errorMsg = new StringBuilder(); 108 | successResult = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); 109 | errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); 110 | String s; 111 | while ((s = successResult.readLine()) != null) { 112 | successMsg.append(s); 113 | } 114 | while ((s = errorResult.readLine()) != null) { 115 | errorMsg.append(s); 116 | } 117 | } 118 | } catch (Exception e) { 119 | e.printStackTrace(); 120 | } finally { 121 | CloseUtils.closeIO(os, successResult, errorResult); 122 | if (process != null) { 123 | process.destroy(); 124 | } 125 | } 126 | return new CommandResult( 127 | result, 128 | successMsg == null ? null : successMsg.toString(), 129 | errorMsg == null ? null : errorMsg.toString() 130 | ); 131 | } 132 | 133 | /** 134 | * 返回的命令结果 135 | */ 136 | public static class CommandResult { 137 | /** 138 | * 结果码 139 | **/ 140 | public int result; 141 | /** 142 | * 成功信息 143 | **/ 144 | public String successMsg; 145 | /** 146 | * 错误信息 147 | **/ 148 | public String errorMsg; 149 | 150 | public CommandResult(int result, String successMsg, String errorMsg) { 151 | this.result = result; 152 | this.successMsg = successMsg; 153 | this.errorMsg = errorMsg; 154 | } 155 | } 156 | } -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.utils; 2 | 3 | /** 4 | * 字符串相关工具类 5 | */ 6 | public class StringUtils { 7 | 8 | private StringUtils() { 9 | throw new UnsupportedOperationException("u can't instantiate me..."); 10 | } 11 | 12 | /** 13 | * 字符串拼接,线程安全 14 | */ 15 | public static String buffer(String... array) { 16 | StringBuffer s = new StringBuffer(); 17 | for (String str : array) { 18 | s.append(str); 19 | } 20 | return s.toString(); 21 | } 22 | 23 | /** 24 | * 字符串拼接,线程不安全,效率高 25 | */ 26 | public static String builder(String... array) { 27 | StringBuilder s = new StringBuilder(); 28 | for (String str : array) { 29 | s.append(str); 30 | } 31 | return s.toString(); 32 | } 33 | 34 | 35 | /** 36 | * 判断字符串是否为null或长度为0 37 | * 38 | * @param s 待校验字符串 39 | * @return {@code true}: 空
{@code false}: 不为空 40 | */ 41 | public static boolean isEmpty(CharSequence s) { 42 | return s == null || s.length() == 0; 43 | } 44 | 45 | /** 46 | * 判断字符串是否为null或全为空格 47 | * 48 | * @param s 待校验字符串 49 | * @return {@code true}: null或全空格
{@code false}: 不为null且不全空格 50 | */ 51 | public static boolean isSpace(String s) { 52 | return (s == null || s.trim().length() == 0); 53 | } 54 | 55 | /** 56 | * 判断两字符串是否相等 57 | * 58 | * @param a 待校验字符串a 59 | * @param b 待校验字符串b 60 | * @return {@code true}: 相等
{@code false}: 不相等 61 | */ 62 | public static boolean equals(CharSequence a, CharSequence b) { 63 | if (a == b) return true; 64 | int length; 65 | if (a != null && b != null && (length = a.length()) == b.length()) { 66 | if (a instanceof String && b instanceof String) { 67 | return a.equals(b); 68 | } else { 69 | for (int i = 0; i < length; i++) { 70 | if (a.charAt(i) != b.charAt(i)) return false; 71 | } 72 | return true; 73 | } 74 | } 75 | return false; 76 | } 77 | 78 | /** 79 | * 判断两字符串忽略大小写是否相等 80 | * 81 | * @param a 待校验字符串a 82 | * @param b 待校验字符串b 83 | * @return {@code true}: 相等
{@code false}: 不相等 84 | */ 85 | public static boolean equalsIgnoreCase(String a, String b) { 86 | return (a == b) || (b != null) && (a.length() == b.length()) && a.regionMatches(true, 0, b, 0, b.length()); 87 | } 88 | 89 | /** 90 | * null转为长度为0的字符串 91 | * 92 | * @param s 待转字符串 93 | * @return s为null转为长度为0字符串,否则不改变 94 | */ 95 | public static String null2Length0(String s) { 96 | return s == null ? "" : s; 97 | } 98 | 99 | /** 100 | * 返回字符串长度 101 | * 102 | * @param s 字符串 103 | * @return null返回0,其他返回自身长度 104 | */ 105 | public static int length(CharSequence s) { 106 | return s == null ? 0 : s.length(); 107 | } 108 | 109 | /** 110 | * 首字母大写 111 | * 112 | * @param s 待转字符串 113 | * @return 首字母大写字符串 114 | */ 115 | public static String upperFirstLetter(String s) { 116 | if (isEmpty(s) || !Character.isLowerCase(s.charAt(0))) return s; 117 | return String.valueOf((char) (s.charAt(0) - 32)) + s.substring(1); 118 | } 119 | 120 | /** 121 | * 首字母小写 122 | * 123 | * @param s 待转字符串 124 | * @return 首字母小写字符串 125 | */ 126 | public static String lowerFirstLetter(String s) { 127 | if (isEmpty(s) || !Character.isUpperCase(s.charAt(0))) return s; 128 | return String.valueOf((char) (s.charAt(0) + 32)) + s.substring(1); 129 | } 130 | 131 | /** 132 | * 反转字符串 133 | * 134 | * @param s 待反转字符串 135 | * @return 反转字符串 136 | */ 137 | public static String reverse(String s) { 138 | int len = length(s); 139 | if (len <= 1) return s; 140 | int mid = len >> 1; 141 | char[] chars = s.toCharArray(); 142 | char c; 143 | for (int i = 0; i < mid; ++i) { 144 | c = chars[i]; 145 | chars[i] = chars[len - i - 1]; 146 | chars[len - i - 1] = c; 147 | } 148 | return new String(chars); 149 | } 150 | 151 | /** 152 | * 转化为半角字符 153 | * 154 | * @param s 待转字符串 155 | * @return 半角字符串 156 | */ 157 | public static String toDBC(String s) { 158 | if (isEmpty(s)) return s; 159 | char[] chars = s.toCharArray(); 160 | for (int i = 0, len = chars.length; i < len; i++) { 161 | if (chars[i] == 12288) { 162 | chars[i] = ' '; 163 | } else if (65281 <= chars[i] && chars[i] <= 65374) { 164 | chars[i] = (char) (chars[i] - 65248); 165 | } else { 166 | chars[i] = chars[i]; 167 | } 168 | } 169 | return new String(chars); 170 | } 171 | 172 | /** 173 | * 转化为全角字符 174 | * 175 | * @param s 待转字符串 176 | * @return 全角字符串 177 | */ 178 | public static String toSBC(String s) { 179 | if (isEmpty(s)) return s; 180 | char[] chars = s.toCharArray(); 181 | for (int i = 0, len = chars.length; i < len; i++) { 182 | if (chars[i] == ' ') { 183 | chars[i] = (char) 12288; 184 | } else if (33 <= chars[i] && chars[i] <= 126) { 185 | chars[i] = (char) (chars[i] + 65248); 186 | } else { 187 | chars[i] = chars[i]; 188 | } 189 | } 190 | return new String(chars); 191 | } 192 | } -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/utils/ToastUtils.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.utils; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | import android.support.annotation.StringRes; 6 | import android.view.Gravity; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | /** 11 | * Toast相关工具类 12 | */ 13 | public class ToastUtils { 14 | 15 | private ToastUtils() { 16 | throw new UnsupportedOperationException("u can't instantiate me..."); 17 | } 18 | 19 | private static Toast sToast; 20 | private static Handler sHandler = new Handler(Looper.getMainLooper()); 21 | private static boolean isJumpWhenMore; 22 | 23 | /** 24 | * 吐司初始化 25 | * 26 | * @param isJumpWhenMore 当连续弹出吐司时,是要弹出新吐司还是只修改文本内容 27 | *

{@code true}: 弹出新吐司
{@code false}: 只修改文本内容

28 | *

如果为{@code false}的话可用来做显示任意时长的吐司

29 | */ 30 | public static void init(boolean isJumpWhenMore) { 31 | ToastUtils.isJumpWhenMore = isJumpWhenMore; 32 | } 33 | 34 | /** 35 | * 安全地显示短时吐司 36 | * 37 | * @param text 文本 38 | */ 39 | public static void showShortToastSafe(final CharSequence text) { 40 | sHandler.post(new Runnable() { 41 | @Override 42 | public void run() { 43 | showToast(text, Toast.LENGTH_SHORT); 44 | } 45 | }); 46 | } 47 | 48 | /** 49 | * 安全地显示短时吐司 50 | * 51 | * @param resId 资源Id 52 | */ 53 | public static void showShortToastSafe(final @StringRes int resId) { 54 | sHandler.post(new Runnable() { 55 | @Override 56 | public void run() { 57 | showToast(resId, Toast.LENGTH_SHORT); 58 | } 59 | }); 60 | } 61 | 62 | /** 63 | * 安全地显示短时吐司 64 | * 65 | * @param resId 资源Id 66 | * @param args 参数 67 | */ 68 | public static void showShortToastSafe(final @StringRes int resId, final Object... args) { 69 | sHandler.post(new Runnable() { 70 | @Override 71 | public void run() { 72 | showToast(resId, Toast.LENGTH_SHORT, args); 73 | } 74 | }); 75 | } 76 | 77 | /** 78 | * 安全地显示短时吐司 79 | * 80 | * @param format 格式 81 | * @param args 参数 82 | */ 83 | public static void showShortToastSafe(final String format, final Object... args) { 84 | sHandler.post(new Runnable() { 85 | @Override 86 | public void run() { 87 | showToast(format, Toast.LENGTH_SHORT, args); 88 | } 89 | }); 90 | } 91 | 92 | /** 93 | * 安全地显示长时吐司 94 | * 95 | * @param text 文本 96 | */ 97 | public static void showLongToastSafe(final CharSequence text) { 98 | sHandler.post(new Runnable() { 99 | @Override 100 | public void run() { 101 | showToast(text, Toast.LENGTH_LONG); 102 | } 103 | }); 104 | } 105 | 106 | /** 107 | * 安全地显示长时吐司 108 | * 109 | * @param resId 资源Id 110 | */ 111 | public static void showLongToastSafe(final @StringRes int resId) { 112 | sHandler.post(new Runnable() { 113 | @Override 114 | public void run() { 115 | showToast(resId, Toast.LENGTH_LONG); 116 | } 117 | }); 118 | } 119 | 120 | /** 121 | * 安全地显示长时吐司 122 | * 123 | * @param resId 资源Id 124 | * @param args 参数 125 | */ 126 | public static void showLongToastSafe(final @StringRes int resId, final Object... args) { 127 | sHandler.post(new Runnable() { 128 | @Override 129 | public void run() { 130 | showToast(resId, Toast.LENGTH_LONG, args); 131 | } 132 | }); 133 | } 134 | 135 | /** 136 | * 安全地显示长时吐司 137 | * 138 | * @param format 格式 139 | * @param args 参数 140 | */ 141 | public static void showLongToastSafe(final String format, final Object... args) { 142 | sHandler.post(new Runnable() { 143 | @Override 144 | public void run() { 145 | showToast(format, Toast.LENGTH_LONG, args); 146 | } 147 | }); 148 | } 149 | 150 | /** 151 | * 显示短时吐司 152 | * 153 | * @param text 文本 154 | */ 155 | public static void showShortToast(CharSequence text) { 156 | showToast(text, Toast.LENGTH_SHORT); 157 | } 158 | 159 | /** 160 | * 显示短时吐司 161 | * 162 | * @param resId 资源Id 163 | */ 164 | public static void showShortToast(@StringRes int resId) { 165 | showToast(resId, Toast.LENGTH_SHORT); 166 | } 167 | 168 | /** 169 | * 显示短时吐司 170 | * 171 | * @param resId 资源Id 172 | * @param args 参数 173 | */ 174 | public static void showShortToast(@StringRes int resId, Object... args) { 175 | showToast(resId, Toast.LENGTH_SHORT, args); 176 | } 177 | 178 | /** 179 | * 显示短时吐司 180 | * 181 | * @param format 格式 182 | * @param args 参数 183 | */ 184 | public static void showShortToast(String format, Object... args) { 185 | showToast(format, Toast.LENGTH_SHORT, args); 186 | } 187 | 188 | /** 189 | * 显示长时吐司 190 | * 191 | * @param text 文本 192 | */ 193 | public static void showLongToast(CharSequence text) { 194 | showToast(text, Toast.LENGTH_LONG); 195 | } 196 | 197 | /** 198 | * 显示长时吐司 199 | * 200 | * @param resId 资源Id 201 | */ 202 | public static void showLongToast(@StringRes int resId) { 203 | showToast(resId, Toast.LENGTH_LONG); 204 | } 205 | 206 | /** 207 | * 显示长时吐司 208 | * 209 | * @param resId 资源Id 210 | * @param args 参数 211 | */ 212 | public static void showLongToast(@StringRes int resId, Object... args) { 213 | showToast(resId, Toast.LENGTH_LONG, args); 214 | } 215 | 216 | /** 217 | * 显示长时吐司 218 | * 219 | * @param format 格式 220 | * @param args 参数 221 | */ 222 | public static void showLongToast(String format, Object... args) { 223 | showToast(format, Toast.LENGTH_LONG, args); 224 | } 225 | 226 | /** 227 | * 显示吐司 228 | * 229 | * @param resId 资源Id 230 | * @param duration 显示时长 231 | */ 232 | private static void showToast(@StringRes int resId, int duration) { 233 | showToast(Utils.getContext().getResources().getText(resId).toString(), duration); 234 | } 235 | 236 | /** 237 | * 显示吐司 238 | * 239 | * @param resId 资源Id 240 | * @param duration 显示时长 241 | * @param args 参数 242 | */ 243 | private static void showToast(@StringRes int resId, int duration, Object... args) { 244 | showToast(String.format(Utils.getContext().getResources().getString(resId), args), duration); 245 | } 246 | 247 | /** 248 | * 显示吐司 249 | * 250 | * @param format 格式 251 | * @param duration 显示时长 252 | * @param args 参数 253 | */ 254 | private static void showToast(String format, int duration, Object... args) { 255 | showToast(String.format(format, args), duration); 256 | } 257 | 258 | /** 259 | * 显示吐司 260 | * 261 | * @param text 文本 262 | * @param duration 显示时长 263 | */ 264 | private static void showToast(CharSequence text, int duration) { 265 | if (isJumpWhenMore) cancelToast(); 266 | if (sToast == null) { 267 | sToast = Toast.makeText(Utils.getContext(), text, duration); 268 | TextView tv = (TextView) sToast.getView().findViewById(android.R.id.message); 269 | tv.setTextSize(18); 270 | sToast.setGravity(Gravity.CENTER, 0, 0); 271 | } else { 272 | sToast.setText(text); 273 | sToast.setDuration(duration); 274 | } 275 | sToast.show(); 276 | } 277 | 278 | /** 279 | * 取消吐司显示 280 | */ 281 | public static void cancelToast() { 282 | if (sToast != null) { 283 | sToast.cancel(); 284 | sToast = null; 285 | } 286 | } 287 | } -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.utils; 2 | 3 | 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.content.ContextWrapper; 7 | import android.content.pm.ApplicationInfo; 8 | import android.content.pm.PackageManager; 9 | import android.support.annotation.NonNull; 10 | import android.support.annotation.StringRes; 11 | import android.support.v4.app.Fragment; 12 | import android.support.v4.app.FragmentManager; 13 | import android.support.v4.app.FragmentTransaction; 14 | import android.view.View; 15 | 16 | /** 17 | *

Utils初始化相关

18 | */ 19 | public class Utils { 20 | 21 | private static Context context; 22 | 23 | private Utils() { 24 | throw new UnsupportedOperationException("u can't instantiate me..."); 25 | } 26 | 27 | /** 28 | * 初始化工具类 29 | * 30 | * @param context 上下文 31 | */ 32 | public static void init(Context context) { 33 | Utils.context = context.getApplicationContext(); 34 | } 35 | 36 | /** 37 | * 获取ApplicationContext 38 | * 39 | * @return ApplicationContext 40 | */ 41 | public static Context getContext() { 42 | if (context != null) return context; 43 | throw new NullPointerException("u should init first"); 44 | } 45 | 46 | /** 47 | * View获取Activity的工具 48 | * 49 | * @param view view 50 | * @return Activity 51 | */ 52 | public static 53 | @NonNull 54 | Activity getActivity(View view) { 55 | Context context = view.getContext(); 56 | 57 | while (context instanceof ContextWrapper) { 58 | if (context instanceof Activity) { 59 | return (Activity) context; 60 | } 61 | context = ((ContextWrapper) context).getBaseContext(); 62 | } 63 | 64 | throw new IllegalStateException("View " + view + " is not attached to an Activity"); 65 | } 66 | 67 | /** 68 | * 全局获取String的方法 69 | * 70 | * @param id 资源Id 71 | * @return String 72 | */ 73 | public static String getString(@StringRes int id) { 74 | return context.getResources().getString(id); 75 | } 76 | 77 | /** 78 | * 判断App是否是Debug版本 79 | * 80 | * @return {@code true}: 是
{@code false}: 否 81 | */ 82 | public static boolean isAppDebug() { 83 | if (StringUtils.isSpace(context.getPackageName())) return false; 84 | try { 85 | PackageManager pm = context.getPackageManager(); 86 | ApplicationInfo ai = pm.getApplicationInfo(context.getPackageName(), 0); 87 | return ai != null && (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; 88 | } catch (PackageManager.NameNotFoundException e) { 89 | e.printStackTrace(); 90 | return false; 91 | } 92 | } 93 | 94 | 95 | /** 96 | * The {@code fragment} is added to the container view with id {@code frameId}. The operation is 97 | * performed by the {@code fragmentManager}. 98 | */ 99 | public static void addFragmentToActivity(@NonNull FragmentManager fragmentManager, 100 | @NonNull Fragment fragment, int frameId) { 101 | checkNotNull(fragmentManager); 102 | checkNotNull(fragment); 103 | FragmentTransaction transaction = fragmentManager.beginTransaction(); 104 | transaction.add(frameId, fragment); 105 | transaction.commit(); 106 | } 107 | 108 | 109 | public static T checkNotNull(T obj) { 110 | if (obj == null) { 111 | throw new NullPointerException(); 112 | } 113 | return obj; 114 | } 115 | 116 | } -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/widget/HackyViewPager.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.widget; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ViewPager; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | /** 9 | *

解决图片缩放崩溃的问题

10 | * @name HackyViewPager 11 | * @author 张华洋 2017/9/27 10:10 12 | * @version V1.1 13 | */ 14 | public class HackyViewPager extends ViewPager { 15 | 16 | public HackyViewPager(Context context) { 17 | super(context); 18 | } 19 | 20 | public HackyViewPager(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | @Override 25 | public boolean onInterceptTouchEvent(MotionEvent ev) { 26 | try { 27 | return super.onInterceptTouchEvent(ev); 28 | } catch (IllegalArgumentException | ArrayIndexOutOfBoundsException e) { 29 | e.printStackTrace(); 30 | } 31 | return false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib_common/src/main/java/com/guiying/module/common/widget/NoScrollViewPager.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.common.widget; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ViewPager; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | /** 9 | *

可以禁止滑动翻页的ViewPager

10 | * 11 | * @author 张华洋 2017/9/27 10:10 12 | * @version V1.1 13 | * @name NoScrollViewPager 14 | */ 15 | public class NoScrollViewPager extends ViewPager { 16 | 17 | private boolean isPagingEnabled = true; 18 | 19 | public NoScrollViewPager(Context context) { 20 | super(context); 21 | } 22 | 23 | public NoScrollViewPager(Context context, AttributeSet attrs) { 24 | super(context, attrs); 25 | } 26 | 27 | @Override 28 | public boolean onTouchEvent(MotionEvent event) { 29 | return this.isPagingEnabled && super.onTouchEvent(event); 30 | } 31 | 32 | @Override 33 | public boolean onInterceptTouchEvent(MotionEvent event) { 34 | return this.isPagingEnabled && super.onInterceptTouchEvent(event); 35 | } 36 | 37 | public void setPagerEnabled(boolean b) { 38 | this.isPagingEnabled = b; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /lib_common/src/main/res/drawable-xxhdpi/ic_arrow_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/lib_common/src/main/res/drawable-xxhdpi/ic_arrow_back.png -------------------------------------------------------------------------------- /lib_common/src/main/res/drawable/shape_loading_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /lib_common/src/main/res/layout/layout_load_error.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /lib_common/src/main/res/layout/layout_load_more.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /lib_common/src/main/res/layout/layout_load_no_more.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /lib_common/src/main/res/layout/layout_load_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /lib_common/src/main/res/layout/layout_view_empty.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /lib_common/src/main/res/layout/progress_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 18 | 26 | 27 | -------------------------------------------------------------------------------- /lib_common/src/main/res/layout/toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | -------------------------------------------------------------------------------- /lib_common/src/main/res/mipmap-xxhdpi/ic_launcher.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/lib_common/src/main/res/mipmap-xxhdpi/ic_launcher.jpg -------------------------------------------------------------------------------- /lib_common/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /lib_common/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #F44336 5 | #D32F2F 6 | #FF5252 7 | 8 | 9 | #fff7f7f7 10 | @android:color/primary_text_light 11 | @color/gray_AD 12 | @color/gray_cc 13 | @color/black_alpha40 14 | #CA2C32 15 | @android:color/transparent 16 | #00ffffff 17 | #4d4d4d 18 | #908f94 19 | #999999 20 | #dedede 21 | #404040 22 | #F9686D 23 | 24 | #ffffffff 25 | #1affffff 26 | #33ffffff 27 | #4dffffff 28 | 29 | 30 | #ff000000 31 | #1a000000 32 | #26000000 33 | #33000000 34 | #4d000000 35 | #52000000 36 | #66000000 37 | #0d000000 38 | #80000000 39 | #89000000 40 | #99000000 41 | #cc000000 42 | 43 | 44 | #ff323232 45 | #ff333333 46 | #ff353535 47 | #ff666666 48 | #ff7f7f7f 49 | #ff808080 50 | #ff888888 51 | #88323232 52 | #ffadadad 53 | #ffc8c8c8 54 | #ffd5d5d5 55 | #ffe6e6e6 56 | #ffcccccc 57 | #ffd9d9d9 58 | #fff0f0f0 59 | #fff2f2f2 60 | #fff3f3f3 61 | #fff4f4f4 62 | #fff6f6f6 63 | #fffcfcfc 64 | #e0e0e0 65 | 66 | 67 | -------------------------------------------------------------------------------- /lib_common/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Common 3 | 4 | 当前网络未连接 5 | baseUrl不能为空 6 | 7 | 8 | 载入中··· 9 | 10 | 11 | 加载中… 12 | 没有更多了 13 | 加载出错,点击重试 14 | 更多 15 | 暂无数据 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib_common/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 39 | 40 | 41 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /module_app/.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea/workspace.xml 38 | 39 | # Keystore files 40 | *.jks 41 | -------------------------------------------------------------------------------- /module_app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | // Create a variable called keystorePropertiesFile, and initialize it to your 4 | // keystore.properties file, in the rootProject folder. 5 | def keystorePropertiesFile = rootProject.file("keystore.properties") 6 | // Initialize a new Properties() object called keystoreProperties. 7 | def keystoreProperties = new Properties() 8 | // Load your keystore.properties file into the keystoreProperties object. 9 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 10 | 11 | static def buildTime() { 12 | return new Date().format("yyyyMMdd"); 13 | } 14 | 15 | android { 16 | signingConfigs { 17 | release { 18 | keyAlias keystoreProperties['keyAlias'] 19 | keyPassword keystoreProperties['keyPassword'] 20 | storeFile file(keystoreProperties['storeFile']) 21 | storePassword keystoreProperties['storePassword'] 22 | } 23 | } 24 | 25 | compileSdkVersion build_versions.target_sdk 26 | defaultConfig { 27 | applicationId "com.guiying.module" 28 | minSdkVersion build_versions.min_sdk 29 | targetSdkVersion build_versions.target_sdk 30 | versionCode 1 31 | versionName "1.0" 32 | multiDexEnabled true 33 | //打包时间 34 | resValue "string", "build_time", buildTime() 35 | } 36 | 37 | 38 | compileOptions { 39 | sourceCompatibility JavaVersion.VERSION_1_8 40 | targetCompatibility JavaVersion.VERSION_1_8 41 | } 42 | 43 | buildTypes { 44 | release { 45 | //更改AndroidManifest.xml中预先定义好占位符信息 46 | //manifestPlaceholders = [app_icon: "@drawable/icon"] 47 | // 不显示Log 48 | buildConfigField "boolean", "LEO_DEBUG", "false" 49 | //是否zip对齐 50 | zipAlignEnabled true 51 | // 缩减resource文件 52 | shrinkResources true 53 | //Proguard 54 | minifyEnabled true 55 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 56 | //签名 57 | signingConfig signingConfigs.release 58 | } 59 | 60 | debug { 61 | //给applicationId添加后缀“.debug” 62 | applicationIdSuffix ".debug" 63 | //manifestPlaceholders = [app_icon: "@drawable/launch_beta"] 64 | buildConfigField "boolean", "LOG_DEBUG", "true" 65 | zipAlignEnabled false 66 | shrinkResources false 67 | minifyEnabled false 68 | debuggable true 69 | } 70 | } 71 | 72 | 73 | } 74 | 75 | dependencies { 76 | implementation fileTree(dir: 'libs', include: ['*.jar']) 77 | implementation deps.support.multidex 78 | implementation project(':lib_common') 79 | if (!isModule.toBoolean()) { 80 | implementation project(':module_main') 81 | implementation project(':module_girls') 82 | implementation project(':module_news') 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /module_app/libs/acra-4.5.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/module_app/libs/acra-4.5.0.jar -------------------------------------------------------------------------------- /module_app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /module_app/src/main/java/com/guiying/module/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module; 2 | 3 | import android.content.Context; 4 | import android.support.multidex.MultiDex; 5 | 6 | import com.alibaba.android.arouter.launcher.ARouter; 7 | import com.guiying.module.common.base.BaseApplication; 8 | import com.guiying.module.common.utils.Utils; 9 | 10 | import org.acra.ACRA; 11 | import org.acra.ReportField; 12 | import org.acra.ReportingInteractionMode; 13 | import org.acra.annotation.ReportsCrashes; 14 | import org.acra.collector.CrashReportData; 15 | import org.acra.sender.EmailIntentSender; 16 | import org.acra.sender.ReportSender; 17 | import org.acra.sender.ReportSenderException; 18 | 19 | /** 20 | *

这里仅需做一些初始化的工作

21 | * 22 | * @author 张华洋 2017/2/15 20:14 23 | * @version V1.2.0 24 | * @name MyApplication 25 | */ 26 | @ReportsCrashes( 27 | mailTo = "guiying705@Gmail.com", 28 | mode = ReportingInteractionMode.DIALOG, 29 | customReportContent = { 30 | ReportField.APP_VERSION_NAME, 31 | ReportField.ANDROID_VERSION, 32 | ReportField.PHONE_MODEL, 33 | ReportField.CUSTOM_DATA, 34 | ReportField.BRAND, 35 | ReportField.STACK_TRACE, 36 | ReportField.LOGCAT, 37 | ReportField.USER_COMMENT}, 38 | resToastText = R.string.crash_toast_text, 39 | resDialogText = R.string.crash_dialog_text, 40 | resDialogTitle = R.string.crash_dialog_title) 41 | public class MyApplication extends BaseApplication { 42 | 43 | 44 | @Override 45 | public void onCreate() { 46 | super.onCreate(); 47 | if (Utils.isAppDebug()) { 48 | //开启InstantRun之后,一定要在ARouter.init之前调用openDebug 49 | ARouter.openDebug(); 50 | ARouter.openLog(); 51 | } 52 | ARouter.init(this); 53 | //崩溃日志记录初始化 54 | ACRA.init(this); 55 | ACRA.getErrorReporter().removeAllReportSenders(); 56 | ACRA.getErrorReporter().setReportSender(new CrashReportSender()); 57 | } 58 | 59 | 60 | @Override 61 | protected void attachBaseContext(Context base) { 62 | super.attachBaseContext(base); 63 | // dex突破65535的限制 64 | MultiDex.install(this); 65 | } 66 | 67 | 68 | /** 69 | * 发送崩溃日志 70 | */ 71 | private class CrashReportSender implements ReportSender { 72 | CrashReportSender() { 73 | ACRA.getErrorReporter().putCustomData("PLATFORM", "ANDROID"); 74 | ACRA.getErrorReporter().putCustomData("BUILD_ID", android.os.Build.ID); 75 | ACRA.getErrorReporter().putCustomData("DEVICE_NAME", android.os.Build.PRODUCT); 76 | } 77 | 78 | @Override 79 | public void send(Context context, CrashReportData crashReportData) throws ReportSenderException { 80 | EmailIntentSender emailSender = new EmailIntentSender(getApplicationContext()); 81 | emailSender.send(context, crashReportData); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /module_app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 组件化项目 3 | 4 | module 5 | 6 | 7 | 程序崩溃了 8 | 感谢您对我们的支持! 9 | 发送崩溃日志 10 | 发送成功 11 | 12 | 13 | -------------------------------------------------------------------------------- /module_girls/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /module_girls/build.gradle: -------------------------------------------------------------------------------- 1 | if (isModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | 7 | android { 8 | compileSdkVersion build_versions.target_sdk 9 | defaultConfig { 10 | minSdkVersion build_versions.min_sdk 11 | targetSdkVersion build_versions.target_sdk 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | javaCompileOptions { 16 | annotationProcessorOptions { 17 | arguments = [ moduleName : project.getName() ] 18 | } 19 | } 20 | } 21 | 22 | compileOptions { 23 | sourceCompatibility JavaVersion.VERSION_1_8 24 | targetCompatibility JavaVersion.VERSION_1_8 25 | } 26 | 27 | sourceSets { 28 | main { 29 | if (isModule.toBoolean()) { 30 | manifest.srcFile 'src/main/module/AndroidManifest.xml' 31 | } else { 32 | manifest.srcFile 'src/main/AndroidManifest.xml' 33 | //集成开发模式下排除debug文件夹中的所有Java文件 34 | java { 35 | exclude 'debug/**' 36 | } 37 | } 38 | } 39 | } 40 | 41 | buildTypes { 42 | release { 43 | minifyEnabled false 44 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 45 | } 46 | } 47 | } 48 | 49 | dependencies { 50 | implementation fileTree(dir: 'libs', include: ['*.jar']) 51 | annotationProcessor deps.arouter_compiler 52 | implementation project(':lib_common') 53 | } 54 | -------------------------------------------------------------------------------- /module_girls/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 8 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/Constants.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls; 2 | 3 | /** 4 | * 保存项目中用到的常量 5 | */ 6 | public interface Constants { 7 | 8 | /** 9 | * http://gank.io/api/data/福利/10/1 10 | */ 11 | String GAN_HUO_API = "http://gank.io/api/data/"; 12 | 13 | String INTENT_GIRLS = "girls"; 14 | String INTENT_INDEX = "index"; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/GirlsFragment.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.guiying.module.common.base.BaseFragment; 11 | 12 | 13 | /** 14 | * A simple {@link Fragment} subclass. 15 | */ 16 | public class GirlsFragment extends BaseFragment { 17 | 18 | /** 19 | * Use this factory method to create a new instance of 20 | * this fragment using the provided parameters. 21 | * 22 | * @return A new instance of fragment GirlsFragment. 23 | */ 24 | public static GirlsFragment newInstance() { 25 | return new GirlsFragment(); 26 | } 27 | 28 | 29 | public GirlsFragment() { 30 | // Required empty public constructor 31 | } 32 | 33 | 34 | @Override 35 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 36 | Bundle savedInstanceState) { 37 | // Inflate the layout for this fragment 38 | return inflater.inflate(R.layout.fragment_girls, container, false); 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/MyDelegate.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls; 2 | 3 | import android.support.annotation.Keep; 4 | 5 | import com.guiying.module.common.base.IApplicationDelegate; 6 | import com.guiying.module.common.base.ViewManager; 7 | 8 | /** 9 | *

类说明

10 | * 11 | * @author 张华洋 2017/9/20 22:29 12 | * @version V2.8.3 13 | * @name MyDelegate 14 | */ 15 | @Keep 16 | public class MyDelegate implements IApplicationDelegate { 17 | 18 | @Override 19 | public void onCreate() { 20 | //主动添加 21 | ViewManager.getInstance().addFragment(0, GirlsFragment.newInstance()); 22 | } 23 | 24 | @Override 25 | public void onTerminate() { 26 | 27 | } 28 | 29 | @Override 30 | public void onLowMemory() { 31 | 32 | } 33 | 34 | @Override 35 | public void onTrimMemory(int level) { 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/MyViewDelegate.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls; 2 | 3 | import android.support.annotation.Keep; 4 | import android.view.View; 5 | 6 | import com.guiying.module.common.base.BaseFragment; 7 | import com.guiying.module.common.base.IViewDelegate; 8 | 9 | /** 10 | *

类说明

11 | * 12 | * @author 张华洋 2018/1/4 22:16 13 | * @version V2.8.3 14 | * @name MyViewDelegate 15 | */ 16 | @Keep 17 | public class MyViewDelegate implements IViewDelegate { 18 | 19 | @Override 20 | public BaseFragment getFragment(String name) { 21 | return GirlsFragment.newInstance(); 22 | } 23 | 24 | @Override 25 | public View getView(String name) { 26 | return null; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/data/GirlsDataSource.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.data; 2 | 3 | import com.guiying.module.girls.data.bean.GirlsParser; 4 | 5 | public interface GirlsDataSource { 6 | 7 | interface LoadGirlsCallback { 8 | 9 | void onGirlsLoaded(GirlsParser girlsParser); 10 | 11 | void onDataNotAvailable(); 12 | } 13 | 14 | void getGirls(int size, int page, LoadGirlsCallback callback); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/data/bean/Girls.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.data.bean; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | /** 7 | *

类说明

8 | * 9 | * @author 张华洋 2017/2/22 20:51 10 | * @version V1.2.0 11 | * @name Girls 12 | */ 13 | 14 | 15 | public class Girls implements Parcelable { 16 | 17 | private String _id; 18 | private String createdAt; 19 | private String desc; 20 | private String publishedAt; 21 | private String source; 22 | private String type; 23 | private String url; 24 | private boolean used; 25 | private String who; 26 | 27 | public void set_id(String _id) { 28 | this._id = _id; 29 | } 30 | 31 | public void setCreatedAt(String createdAt) { 32 | this.createdAt = createdAt; 33 | } 34 | 35 | public void setDesc(String desc) { 36 | this.desc = desc; 37 | } 38 | 39 | public void setPublishedAt(String publishedAt) { 40 | this.publishedAt = publishedAt; 41 | } 42 | 43 | public void setSource(String source) { 44 | this.source = source; 45 | } 46 | 47 | public void setType(String type) { 48 | this.type = type; 49 | } 50 | 51 | public void setUrl(String url) { 52 | this.url = url; 53 | } 54 | 55 | public void setUsed(boolean used) { 56 | this.used = used; 57 | } 58 | 59 | public void setWho(String who) { 60 | this.who = who; 61 | } 62 | 63 | public String get_id() { 64 | return _id; 65 | } 66 | 67 | public String getCreatedAt() { 68 | return createdAt; 69 | } 70 | 71 | public String getDesc() { 72 | return desc; 73 | } 74 | 75 | public String getPublishedAt() { 76 | return publishedAt; 77 | } 78 | 79 | public String getSource() { 80 | return source; 81 | } 82 | 83 | public String getType() { 84 | return type; 85 | } 86 | 87 | public String getUrl() { 88 | return url; 89 | } 90 | 91 | public boolean isUsed() { 92 | return used; 93 | } 94 | 95 | public String getWho() { 96 | return who; 97 | } 98 | 99 | 100 | @Override 101 | public int describeContents() { 102 | return 0; 103 | } 104 | 105 | @Override 106 | public void writeToParcel(Parcel dest, int flags) { 107 | dest.writeString(this._id); 108 | dest.writeString(this.createdAt); 109 | dest.writeString(this.desc); 110 | dest.writeString(this.publishedAt); 111 | dest.writeString(this.source); 112 | dest.writeString(this.type); 113 | dest.writeString(this.url); 114 | dest.writeByte(this.used ? (byte) 1 : (byte) 0); 115 | dest.writeString(this.who); 116 | } 117 | 118 | public Girls() { 119 | } 120 | 121 | protected Girls(Parcel in) { 122 | this._id = in.readString(); 123 | this.createdAt = in.readString(); 124 | this.desc = in.readString(); 125 | this.publishedAt = in.readString(); 126 | this.source = in.readString(); 127 | this.type = in.readString(); 128 | this.url = in.readString(); 129 | this.used = in.readByte() != 0; 130 | this.who = in.readString(); 131 | } 132 | 133 | public static final Creator CREATOR = new Creator() { 134 | @Override 135 | public Girls createFromParcel(Parcel source) { 136 | return new Girls(source); 137 | } 138 | 139 | @Override 140 | public Girls[] newArray(int size) { 141 | return new Girls[size]; 142 | } 143 | }; 144 | } 145 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/data/bean/GirlsParser.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.data.bean; 2 | 3 | import java.util.List; 4 | 5 | public class GirlsParser { 6 | 7 | /** 8 | * error : false 9 | * results : [{"_id":"5771d5eb421aa931ddcc50d6","createdAt":"2016-06-28T09:42:03.761Z","desc":"Dagger2图文完全教程","publishedAt":"2016-06-28T11:33:25.276Z","source":"web","type":"Android","url":"https://github.com/luxiaoming/dagger2Demo","used":true,"who":"代码GG陆晓明"},{"_id":"5771c9ca421aa931ca5a7e59","createdAt":"2016-06-28T08:50:18.731Z","desc":"Android Design 设计模板","publishedAt":"2016-06-28T11:33:25.276Z","source":"chrome","type":"Android","url":"https://github.com/andreasschrade/android-design-template","used":true,"who":"代码家"}] 10 | */ 11 | 12 | private boolean error; 13 | /** 14 | * _id : 5771d5eb421aa931ddcc50d6 15 | * createdAt : 2016-06-28T09:42:03.761Z 16 | * desc : Dagger2图文完全教程 17 | * publishedAt : 2016-06-28T11:33:25.276Z 18 | * source : web 19 | * type : Android 20 | * url : https://github.com/luxiaoming/dagger2Demo 21 | * used : true 22 | * who : 代码GG陆晓明 23 | */ 24 | 25 | private List results; 26 | 27 | public void setError(boolean error) { 28 | this.error = error; 29 | } 30 | 31 | public void setResults(List results) { 32 | this.results = results; 33 | } 34 | 35 | public boolean isError() { 36 | return error; 37 | } 38 | 39 | public List getResults() { 40 | return results; 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/data/source/RemoteGirlsDataSource.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.data.source; 2 | 3 | 4 | import com.guiying.module.common.http.DataType; 5 | import com.guiying.module.common.http.HttpClient; 6 | import com.guiying.module.common.http.OnResultListener; 7 | import com.guiying.module.girls.Constants; 8 | import com.guiying.module.girls.data.GirlsDataSource; 9 | import com.guiying.module.girls.data.bean.GirlsParser; 10 | 11 | 12 | 13 | public class RemoteGirlsDataSource implements GirlsDataSource { 14 | 15 | @Override 16 | public void getGirls(int size, int page, final LoadGirlsCallback callback) { 17 | HttpClient client = new HttpClient.Builder() 18 | .baseUrl(Constants.GAN_HUO_API) 19 | .url("福利/" + size + "/" + page) 20 | .bodyType(DataType.JSON_OBJECT, GirlsParser.class) 21 | .build(); 22 | client.get(new OnResultListener() { 23 | 24 | @Override 25 | public void onSuccess(GirlsParser result) { 26 | callback.onGirlsLoaded(result); 27 | } 28 | 29 | @Override 30 | public void onError(int code, String message) { 31 | callback.onDataNotAvailable(); 32 | } 33 | 34 | @Override 35 | public void onFailure(String message) { 36 | callback.onDataNotAvailable(); 37 | } 38 | }); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/girl/GirlActivity.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.girl; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.view.ViewPager; 5 | import android.view.WindowManager; 6 | 7 | import com.alibaba.android.arouter.facade.annotation.Route; 8 | import com.guiying.module.common.base.BaseActivity; 9 | import com.guiying.module.common.widget.HackyViewPager; 10 | import com.guiying.module.girls.Constants; 11 | import com.guiying.module.girls.data.bean.Girls; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | *

17 | * 18 | * @author 张华洋 2017/5/19 20:24 19 | * @version V1.1 20 | * @name GirlActivity 21 | */ 22 | @Route(path = "/girls/detail") 23 | public class GirlActivity extends BaseActivity { 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 29 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 30 | if (getIntent() != null) { 31 | List mData = getIntent().getParcelableArrayListExtra(Constants.INTENT_GIRLS); 32 | int mCurrentIndex = getIntent().getIntExtra(Constants.INTENT_INDEX, 0); 33 | HackyViewPager viewPager = new HackyViewPager(this); 34 | setContentView(viewPager); 35 | GirlAdapter adapter = new GirlAdapter(this, mData); 36 | viewPager.setAdapter(adapter); 37 | viewPager.setCurrentItem(mCurrentIndex); 38 | viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 39 | @Override 40 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 41 | 42 | } 43 | 44 | @Override 45 | public void onPageSelected(int position) { 46 | 47 | } 48 | 49 | @Override 50 | public void onPageScrollStateChanged(int state) { 51 | 52 | } 53 | }); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/girl/GirlAdapter.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.girl; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.PagerAdapter; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.bumptech.glide.Glide; 10 | import com.github.chrisbanes.photoview.PhotoView; 11 | import com.guiying.module.girls.R; 12 | import com.guiying.module.girls.data.bean.Girls; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | *

18 | * 19 | * @author 张华洋 2017/5/19 20:31 20 | * @version V1.1 21 | * @name GirlAdapter 22 | */ 23 | public class GirlAdapter extends PagerAdapter { 24 | 25 | private Context mContext; 26 | private List mData; 27 | private LayoutInflater layoutInflater; 28 | private View mCurrentView; 29 | 30 | public GirlAdapter(Context context, List data) { 31 | mContext = context; 32 | mData = data; 33 | layoutInflater = LayoutInflater.from(this.mContext); 34 | } 35 | 36 | @Override 37 | public int getCount() { 38 | if (mData == null) { 39 | return 0; 40 | } 41 | return mData.size(); 42 | } 43 | 44 | @Override 45 | public void setPrimaryItem(ViewGroup container, int position, Object object) { 46 | super.setPrimaryItem(container, position, object); 47 | mCurrentView = (View) object; 48 | } 49 | 50 | @Override 51 | public View instantiateItem(ViewGroup container, int position) { 52 | final String imageUrl = mData.get(position).getUrl(); 53 | View view = layoutInflater.inflate(R.layout.item_girl_detail, container, false); 54 | PhotoView imageView = (PhotoView) view.findViewById(R.id.girl_image); 55 | Glide.with(mContext) 56 | .load(imageUrl) 57 | .thumbnail(0.2f) 58 | .into(imageView); 59 | container.addView(view); 60 | return view; 61 | } 62 | 63 | @Override 64 | public void destroyItem(ViewGroup container, int position, Object object) { 65 | container.removeView((View) object); 66 | } 67 | 68 | @Override 69 | public boolean isViewFromObject(View view, Object object) { 70 | return view == object; 71 | } 72 | 73 | public View getPrimaryItem() { 74 | return mCurrentView; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/main/GirlsActivity.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.main; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.alibaba.android.arouter.facade.annotation.Route; 6 | import com.guiying.module.common.base.BaseActionBarActivity; 7 | import com.guiying.module.girls.R; 8 | 9 | @Route(path = "/girls/list") 10 | public class GirlsActivity extends BaseActionBarActivity { 11 | 12 | private GirlsView mView; 13 | private GirlsContract.Presenter mPresenter; 14 | 15 | @Override 16 | protected int setTitleId() { 17 | return R.string.girls_activity_title; 18 | } 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | mView = new GirlsView(this); 24 | setContentView(mView); 25 | mPresenter = new GirlsPresenter(mView); 26 | mPresenter.start(); 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/main/GirlsAdapter.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.main; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.ImageView; 7 | 8 | import com.bumptech.glide.Glide; 9 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 10 | import com.guiying.module.girls.R; 11 | import com.guiying.module.girls.data.bean.Girls; 12 | import com.jude.easyrecyclerview.adapter.BaseViewHolder; 13 | import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter; 14 | 15 | public class GirlsAdapter extends RecyclerArrayAdapter { 16 | 17 | public OnMyItemClickListener mOnItemClickListener; 18 | 19 | public GirlsAdapter(Context context) { 20 | super(context); 21 | } 22 | 23 | @Override 24 | public BaseViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) { 25 | return new GirlsViewHolder(parent); 26 | } 27 | 28 | @Override 29 | public void OnBindViewHolder(final BaseViewHolder holder, final int position) { 30 | super.OnBindViewHolder(holder, position); 31 | holder.itemView.setOnClickListener(new View.OnClickListener() { 32 | @Override 33 | public void onClick(View v) { 34 | if (mOnItemClickListener != null) { 35 | mOnItemClickListener.onItemClick(position, holder); 36 | } 37 | } 38 | }); 39 | } 40 | 41 | private class GirlsViewHolder extends BaseViewHolder { 42 | 43 | private ImageView image; 44 | 45 | private GirlsViewHolder(ViewGroup parent) { 46 | super(parent, R.layout.item_girl); 47 | image = $(R.id.girl_img); 48 | } 49 | 50 | @Override 51 | public void setData(Girls data) { 52 | super.setData(data); 53 | Glide.with(getContext()) 54 | .load(data.getUrl()) 55 | .diskCacheStrategy(DiskCacheStrategy.SOURCE) 56 | .into(image); 57 | } 58 | } 59 | 60 | public interface OnMyItemClickListener { 61 | void onItemClick(int position, BaseViewHolder holder); 62 | } 63 | 64 | public void setOnMyItemClickListener(OnMyItemClickListener listener) { 65 | this.mOnItemClickListener = listener; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/main/GirlsContract.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.main; 2 | 3 | import com.guiying.module.common.base.BasePresenter; 4 | import com.guiying.module.common.base.BaseView; 5 | import com.guiying.module.girls.data.bean.Girls; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | *

类说明

11 | * 12 | * @author 张华洋 2017/2/22 20:33 13 | * @version V1.2.0 14 | * @name GirlsContract 15 | */ 16 | public interface GirlsContract { 17 | 18 | interface View extends BaseView { 19 | 20 | /** 21 | * View 的存活状态 22 | * 23 | * @return true or false 24 | */ 25 | boolean isActive(); 26 | 27 | void refresh(List data); 28 | 29 | void load(List data); 30 | 31 | void showError(); 32 | 33 | void showNormal(); 34 | 35 | } 36 | 37 | interface Presenter extends BasePresenter { 38 | 39 | void getGirls(int page, int size, boolean isRefresh); 40 | 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/main/GirlsPresenter.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.main; 2 | 3 | import com.guiying.module.girls.data.GirlsDataSource; 4 | import com.guiying.module.girls.data.bean.GirlsParser; 5 | import com.guiying.module.girls.data.source.RemoteGirlsDataSource; 6 | 7 | /** 8 | *

类说明

9 | * 10 | * @author 张华洋 2017/2/22 20:33 11 | * @version V1.2.0 12 | * @name GirlsPresenter 13 | */ 14 | public class GirlsPresenter implements GirlsContract.Presenter { 15 | 16 | private GirlsContract.View mView; 17 | private GirlsDataSource mDataSource; 18 | 19 | public GirlsPresenter(GirlsContract.View view) { 20 | mView = view; 21 | mView.setPresenter(this); 22 | mDataSource = new RemoteGirlsDataSource(); 23 | } 24 | 25 | @Override 26 | public void getGirls(int size, int page, final boolean isRefresh) { 27 | mDataSource.getGirls(size, page, new GirlsDataSource.LoadGirlsCallback() { 28 | @Override 29 | public void onGirlsLoaded(GirlsParser girlsParser) { 30 | if (isRefresh) { 31 | mView.refresh(girlsParser.getResults()); 32 | } else { 33 | mView.load(girlsParser.getResults()); 34 | } 35 | mView.showNormal(); 36 | } 37 | 38 | @Override 39 | public void onDataNotAvailable() { 40 | if (isRefresh) { 41 | mView.showError(); 42 | } 43 | } 44 | }); 45 | } 46 | 47 | @Override 48 | public void start() { 49 | getGirls(20, 1, true); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /module_girls/src/main/java/com/guiying/module/girls/main/GirlsView.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.girls.main; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.support.v4.app.ActivityOptionsCompat; 6 | import android.support.v4.content.ContextCompat; 7 | import android.support.v4.widget.SwipeRefreshLayout; 8 | import android.support.v7.widget.StaggeredGridLayoutManager; 9 | import android.util.AttributeSet; 10 | import android.view.View; 11 | import android.view.ViewStub; 12 | import android.widget.FrameLayout; 13 | 14 | import com.guiying.module.common.utils.Utils; 15 | import com.guiying.module.girls.Constants; 16 | import com.guiying.module.girls.R; 17 | import com.guiying.module.girls.data.bean.Girls; 18 | import com.guiying.module.girls.girl.GirlActivity; 19 | import com.jude.easyrecyclerview.EasyRecyclerView; 20 | import com.jude.easyrecyclerview.adapter.BaseViewHolder; 21 | import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | /** 27 | *

类说明

28 | * 29 | * @author 张华洋 2017/2/22 20:33 30 | * @version V1.2.0 31 | * @name GirlsView 32 | */ 33 | public class GirlsView extends FrameLayout implements GirlsContract.View, SwipeRefreshLayout.OnRefreshListener, RecyclerArrayAdapter.OnLoadMoreListener { 34 | 35 | private GirlsContract.Presenter mPresenter; 36 | private boolean mActive; 37 | 38 | private EasyRecyclerView mGirlsRecyclerView; 39 | private ViewStub mNetworkErrorLayout; 40 | private View networkErrorView; 41 | private GirlsAdapter mAdapter; 42 | private ArrayList mData; 43 | private int page = 1; 44 | private int size = 20; 45 | 46 | public GirlsView(Context context) { 47 | super(context); 48 | initView(); 49 | } 50 | 51 | public GirlsView(Context context, AttributeSet attrs) { 52 | super(context, attrs); 53 | initView(); 54 | } 55 | 56 | 57 | private void initView() { 58 | inflate(getContext(), R.layout.view_girls_content, this); 59 | mNetworkErrorLayout = (ViewStub) findViewById(R.id.network_error_layout); 60 | mGirlsRecyclerView = (EasyRecyclerView) findViewById(R.id.girls_recycler_view); 61 | StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); 62 | mGirlsRecyclerView.setLayoutManager(staggeredGridLayoutManager); 63 | mAdapter = new GirlsAdapter(getContext()); 64 | 65 | mGirlsRecyclerView.setAdapterWithProgress(mAdapter); 66 | mGirlsRecyclerView.setRefreshingColor( 67 | ContextCompat.getColor(getContext(), R.color.colorPrimary), 68 | ContextCompat.getColor(getContext(), android.R.color.holo_blue_light), 69 | ContextCompat.getColor(getContext(), android.R.color.holo_green_light) 70 | ); 71 | mAdapter.setMore(R.layout.layout_load_more, this); 72 | mAdapter.setNoMore(R.layout.layout_load_no_more); 73 | mAdapter.setError(R.layout.layout_load_error); 74 | mAdapter.setOnMyItemClickListener(new GirlsAdapter.OnMyItemClickListener() { 75 | @Override 76 | public void onItemClick(int position, BaseViewHolder holder) { 77 | Intent intent = new Intent(Utils.getActivity(GirlsView.this), GirlActivity.class); 78 | intent.putParcelableArrayListExtra(Constants.INTENT_GIRLS, mData); 79 | intent.putExtra(Constants.INTENT_INDEX, position); 80 | ActivityOptionsCompat options = ActivityOptionsCompat.makeScaleUpAnimation(holder.itemView, holder.itemView.getWidth() / 2, holder.itemView.getHeight() / 2, 0, 0); 81 | Utils.getActivity(GirlsView.this).startActivity(intent, options.toBundle()); 82 | } 83 | }); 84 | 85 | mGirlsRecyclerView.setRefreshListener(this); 86 | 87 | mData = new ArrayList<>(); 88 | mActive = true; 89 | } 90 | 91 | 92 | @Override 93 | protected void onAttachedToWindow() { 94 | super.onAttachedToWindow(); 95 | mActive = true; 96 | } 97 | 98 | @Override 99 | protected void onDetachedFromWindow() { 100 | super.onDetachedFromWindow(); 101 | mActive = false; 102 | } 103 | 104 | @Override 105 | public void setPresenter(GirlsContract.Presenter presenter) { 106 | this.mPresenter = presenter; 107 | } 108 | 109 | @Override 110 | public boolean isActive() { 111 | return mActive; 112 | } 113 | 114 | 115 | @Override 116 | public void refresh(List data) { 117 | mData.clear(); 118 | mData.addAll(data); 119 | mAdapter.clear(); 120 | mAdapter.addAll(data); 121 | } 122 | 123 | @Override 124 | public void load(List data) { 125 | mData.addAll(data); 126 | mAdapter.addAll(data); 127 | } 128 | 129 | @Override 130 | public void showError() { 131 | mGirlsRecyclerView.showError(); 132 | 133 | if (networkErrorView != null) { 134 | networkErrorView.setVisibility(View.VISIBLE); 135 | return; 136 | } 137 | 138 | networkErrorView = mNetworkErrorLayout.inflate(); 139 | } 140 | 141 | @Override 142 | public void showNormal() { 143 | if (networkErrorView != null) { 144 | networkErrorView.setVisibility(View.GONE); 145 | } 146 | } 147 | 148 | 149 | @Override 150 | public void onLoadMore() { 151 | if (mData.size() % size == 0) { 152 | page++; 153 | mPresenter.getGirls(size, page, false); 154 | } 155 | } 156 | 157 | @Override 158 | public void onRefresh() { 159 | mPresenter.getGirls(size, page, true); 160 | page = 1; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /module_girls/src/main/java/debug/GirlsApplication.java: -------------------------------------------------------------------------------- 1 | package debug; 2 | 3 | import com.guiying.module.common.base.BaseApplication; 4 | import com.guiying.module.common.http.HttpClient; 5 | import com.guiying.module.common.http.OnResultListener; 6 | import com.orhanobut.logger.Logger; 7 | 8 | /** 9 | *

类说明

10 | * 11 | * @author 张华洋 2017/2/15 20:09 12 | * @version V1.2.0 13 | * @name GirlsApplication 14 | */ 15 | public class GirlsApplication extends BaseApplication { 16 | 17 | @Override 18 | public void onCreate() { 19 | super.onCreate(); 20 | login(); 21 | } 22 | 23 | /** 24 | * 在这里模拟登陆,然后拿到sessionId或者Token 25 | * 这样就能够在组件请求接口了 26 | */ 27 | private void login() { 28 | HttpClient client = new HttpClient.Builder() 29 | .baseUrl("http://gank.io/api/data/") 30 | .url("福利/10/1") 31 | .build(); 32 | client.get(new OnResultListener() { 33 | 34 | @Override 35 | public void onSuccess(String result) { 36 | Logger.e(result); 37 | } 38 | 39 | @Override 40 | public void onError(int code, String message) { 41 | Logger.e(message); 42 | } 43 | 44 | @Override 45 | public void onFailure(String message) { 46 | Logger.e(message); 47 | } 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /module_girls/src/main/module/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /module_girls/src/main/res/layout/activity_girls.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /module_girls/src/main/res/layout/fragment_girls.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /module_girls/src/main/res/layout/item_girl.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 18 | 19 | -------------------------------------------------------------------------------- /module_girls/src/main/res/layout/item_girl_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /module_girls/src/main/res/layout/view_girls_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 17 | -------------------------------------------------------------------------------- /module_girls/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /module_girls/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /module_girls/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Girls组件 3 | 4 | Girls 5 | 6 | 7 | -------------------------------------------------------------------------------- /module_main/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /module_main/build.gradle: -------------------------------------------------------------------------------- 1 | if (isModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | 7 | android { 8 | compileSdkVersion build_versions.target_sdk 9 | defaultConfig { 10 | minSdkVersion build_versions.min_sdk 11 | targetSdkVersion build_versions.target_sdk 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | javaCompileOptions { 16 | annotationProcessorOptions { 17 | arguments = [ moduleName : project.getName() ] 18 | } 19 | } 20 | } 21 | 22 | compileOptions { 23 | sourceCompatibility JavaVersion.VERSION_1_8 24 | targetCompatibility JavaVersion.VERSION_1_8 25 | } 26 | 27 | sourceSets { 28 | main { 29 | if (isModule.toBoolean()) { 30 | manifest.srcFile 'src/main/module/AndroidManifest.xml' 31 | } else { 32 | manifest.srcFile 'src/main/AndroidManifest.xml' 33 | //集成开发模式下排除debug文件夹中的所有Java文件 34 | java { 35 | exclude 'debug/**' 36 | } 37 | } 38 | } 39 | } 40 | 41 | buildTypes { 42 | release { 43 | minifyEnabled false 44 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 45 | } 46 | } 47 | } 48 | 49 | dependencies { 50 | implementation fileTree(dir: 'libs', include: ['*.jar']) 51 | annotationProcessor deps.arouter_compiler 52 | implementation project(':lib_common') 53 | } 54 | -------------------------------------------------------------------------------- /module_main/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /module_main/src/main/java/com/guiying/module/main/BottomNavigationActivity.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.main; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.design.widget.BottomNavigationView; 7 | import android.view.MenuItem; 8 | 9 | import com.guiying.module.common.base.BaseActivity; 10 | import com.guiying.module.common.base.BaseFragment; 11 | import com.guiying.module.common.base.ClassUtils; 12 | import com.guiying.module.common.base.IViewDelegate; 13 | import com.guiying.module.common.base.ViewManager; 14 | import com.guiying.module.common.widget.NoScrollViewPager; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | *

20 | * 21 | * @author 张华洋 2017/9/27 10:23 22 | * @version V1.1 23 | * @name BottomNavigationActivity 24 | */ 25 | public class BottomNavigationActivity extends BaseActivity { 26 | 27 | private NoScrollViewPager mPager; 28 | private List mFragments; 29 | private FragmentAdapter mAdapter; 30 | 31 | private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener 32 | = new BottomNavigationView.OnNavigationItemSelectedListener() { 33 | 34 | @Override 35 | public boolean onNavigationItemSelected(@NonNull MenuItem item) { 36 | int i = item.getItemId(); 37 | if (i == R.id.navigation_home) { 38 | mPager.setCurrentItem(0); 39 | return true; 40 | } else if (i == R.id.navigation_dashboard) { 41 | mPager.setCurrentItem(1); 42 | return true; 43 | } else if (i == R.id.navigation_notifications) { 44 | mPager.setCurrentItem(2); 45 | return true; 46 | } 47 | return false; 48 | } 49 | 50 | }; 51 | 52 | @Override 53 | protected void onCreate(@Nullable Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | setContentView(R.layout.activity_bottom_navigation); 56 | BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation); 57 | navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); 58 | initViewPager(); 59 | } 60 | 61 | private void initViewPager() { 62 | mFragments = ViewManager.getInstance().getAllFragment();//这几个Fragment是主动添加到ViewManager中的 63 | BaseFragment newsFragment = getNewsFragment();//主动寻找 64 | mFragments.add(newsFragment); 65 | mPager = (NoScrollViewPager) findViewById(R.id.container_pager); 66 | mAdapter = new FragmentAdapter(getSupportFragmentManager(), mFragments); 67 | mPager.setPagerEnabled(false); 68 | mPager.setAdapter(mAdapter); 69 | } 70 | 71 | 72 | /** 73 | * 在News模块中寻找实现的Fragment 74 | * 75 | * @return Fragment 76 | */ 77 | private BaseFragment getNewsFragment() { 78 | BaseFragment newsFragment = null; 79 | List viewDelegates = ClassUtils.getObjectsWithInterface(this, IViewDelegate.class, "com.guiying.module.news"); 80 | if (viewDelegates != null && !viewDelegates.isEmpty()) { 81 | newsFragment = viewDelegates.get(0).getFragment(""); 82 | } 83 | return newsFragment; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /module_main/src/main/java/com/guiying/module/main/FragmentAdapter.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.main; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentStatePagerAdapter; 6 | 7 | import com.guiying.module.common.base.BaseFragment; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | *

Fragments适配器

13 | * 14 | * @author 张华洋 2017/9/27 10:14 15 | * @version V1.1 16 | * @name ResourcePagerAdapter 17 | */ 18 | public class FragmentAdapter extends FragmentStatePagerAdapter { 19 | private List mFragments; 20 | 21 | public FragmentAdapter(FragmentManager fm, List mFragments) { 22 | super(fm); 23 | this.mFragments = mFragments; 24 | } 25 | 26 | @Override 27 | public Fragment getItem(int position) { 28 | return mFragments.get(position); 29 | } 30 | 31 | @Override 32 | public int getCount() { 33 | return mFragments != null ? mFragments.size() : 0; 34 | } 35 | 36 | @Override 37 | public int getItemPosition(Object object) { 38 | return android.support.v4.view.PagerAdapter.POSITION_NONE; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /module_main/src/main/java/com/guiying/module/main/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.guiying.module.main; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.view.KeyEvent; 6 | import android.view.View; 7 | 8 | import com.alibaba.android.arouter.launcher.ARouter; 9 | import com.guiying.module.common.base.BaseActivity; 10 | import com.guiying.module.common.base.ViewManager; 11 | import com.guiying.module.common.utils.ToastUtils; 12 | 13 | /** 14 | *

类说明

15 | * 16 | * @author 张华洋 2017/7/1 13:13 17 | * @version V1.2.0 18 | * @name MainActivity 19 | */ 20 | public class MainActivity extends BaseActivity implements View.OnClickListener { 21 | 22 | private long mExitTime = 0; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_main); 28 | findViewById(R.id.news_button).setOnClickListener(this); 29 | findViewById(R.id.girls_button).setOnClickListener(this); 30 | findViewById(R.id.fragment_button).setOnClickListener(this); 31 | } 32 | 33 | @Override 34 | public void onClick(View view) { 35 | if (view.getId() == R.id.news_button) { 36 | //跳转到NewsCenterActivity 37 | ARouter.getInstance().build("/news/center").navigation(); 38 | } else if (view.getId() == R.id.girls_button) { 39 | //跳转到GirlsActivity 40 | ARouter.getInstance().build("/girls/list").navigation(); 41 | } else if (view.getId() == R.id.fragment_button) { 42 | startActivity(new Intent(this, BottomNavigationActivity.class)); 43 | } 44 | } 45 | 46 | 47 | @Override 48 | public boolean onKeyDown(int keyCode, KeyEvent event) { 49 | if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { 50 | //两秒之内按返回键就会退出 51 | if ((System.currentTimeMillis() - mExitTime) > 2000) { 52 | ToastUtils.showShortToast(getString(R.string.app_exit_hint)); 53 | mExitTime = System.currentTimeMillis(); 54 | } else { 55 | ViewManager.getInstance().exitApp(this); 56 | } 57 | return true; 58 | } 59 | return super.onKeyDown(keyCode, event); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /module_main/src/main/java/debug/MainApplication.java: -------------------------------------------------------------------------------- 1 | package debug; 2 | 3 | import com.guiying.module.common.base.BaseApplication; 4 | import com.guiying.module.common.http.HttpClient; 5 | import com.guiying.module.common.http.OnResultListener; 6 | import com.orhanobut.logger.Logger; 7 | 8 | /** 9 | *

类说明

10 | * 11 | * @author 张华洋 2017/2/15 20:09 12 | * @version V1.2.0 13 | * @name GirlsApplication 14 | */ 15 | public class MainApplication extends BaseApplication { 16 | 17 | @Override 18 | public void onCreate() { 19 | super.onCreate(); 20 | login(); 21 | } 22 | 23 | /** 24 | * 在这里模拟登陆,然后拿到sessionId或者Token 25 | * 这样就能够在组件请求接口了 26 | */ 27 | private void login() { 28 | HttpClient client = new HttpClient.Builder() 29 | .baseUrl("http://gank.io/api/data/") 30 | .url("福利/10/1") 31 | .build(); 32 | client.get(new OnResultListener() { 33 | 34 | @Override 35 | public void onSuccess(String result) { 36 | Logger.e(result); 37 | } 38 | 39 | @Override 40 | public void onError(int code, String message) { 41 | Logger.e(message); 42 | } 43 | 44 | @Override 45 | public void onFailure(String message) { 46 | Logger.e(message); 47 | } 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /module_main/src/main/module/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /module_main/src/main/res/drawable/ic_dashboard_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /module_main/src/main/res/drawable/ic_home_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /module_main/src/main/res/drawable/ic_notifications_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /module_main/src/main/res/layout/activity_bottom_navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /module_main/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 |