├── .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、 在运行之前,请先按照图中选择一个能够运行的组件;**
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 super Bitmap> 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 super GlideDrawable> 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 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
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 |
19 |
20 |
25 |
26 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/module_main/src/main/res/menu/navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
13 |
14 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/module_main/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/module_main/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | main组件
3 |
4 | 再按一次退出程序
5 | Fragment组件化
6 | news
7 | girls
8 | 预留
9 |
10 |
11 |
--------------------------------------------------------------------------------
/module_news/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/module_news/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_news/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
9 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/Constants.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news;
2 |
3 | /**
4 | * 保存项目中用到的常量
5 | */
6 | public interface Constants {
7 |
8 | /**
9 | * http://news.at.zhihu.com/api/4/news/before/20170225
10 | */
11 | String ZHIHU_DAILY_BEFORE_MESSAGE = "http://news.at.zhihu.com/api/4/news/before/";
12 |
13 | /**
14 | * http://news-at.zhihu.com/api/4/news/9241375
15 | */
16 | String ZHIHU_DAILY_BEFORE_MESSAGE_DETAIL = "http://news-at.zhihu.com/api/4/news/";
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/MyDelegate.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news;
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 | import com.orhanobut.logger.Logger;
8 |
9 | /**
10 | * 类说明
11 | *
12 | * @author 张华洋 2017/9/20 22:29
13 | * @version V2.8.3
14 | * @name MyDelegate
15 | */
16 | @Keep
17 | public class MyDelegate implements IApplicationDelegate {
18 |
19 | @Override
20 | public void onCreate() {
21 | Logger.init("pattern");
22 | //主动添加
23 | ViewManager.getInstance().addFragment(0, NewsFragment.newInstance());
24 | }
25 |
26 | @Override
27 | public void onTerminate() {
28 |
29 | }
30 |
31 | @Override
32 | public void onLowMemory() {
33 |
34 | }
35 |
36 | @Override
37 | public void onTrimMemory(int level) {
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/MyViewDelegate.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news;
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 NewsFragment.newInstance();
22 | }
23 |
24 | @Override
25 | public View getView(String name) {
26 | return null;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/NewsFragment.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news;
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 NewsFragment 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 NewsFragment.
23 | */
24 | public static NewsFragment newInstance() {
25 | return new NewsFragment();
26 | }
27 |
28 |
29 |
30 | public NewsFragment() {
31 | // Required empty public constructor
32 | }
33 |
34 |
35 | @Override
36 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
37 | Bundle savedInstanceState) {
38 | // Inflate the layout for this fragment
39 | return inflater.inflate(R.layout.fragment_news, container, false);
40 | }
41 |
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/data/NewsDataSource.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.data;
2 |
3 | import com.guiying.module.common.base.InfoCallback;
4 | import com.guiying.module.news.data.bean.MessageDetail;
5 | import com.guiying.module.news.data.bean.StoryList;
6 |
7 | /**
8 | * 类说明
9 | *
10 | * @author 张华洋 2017/4/20 22:02
11 | * @version V1.2.0
12 | * @name NewsDataSource
13 | */
14 | public interface NewsDataSource {
15 |
16 |
17 | /**
18 | * 获取当天的新闻列表
19 | *
20 | * @param date 日期
21 | * @param callback 回调
22 | */
23 | void getNewsList(String date, InfoCallback callback);
24 |
25 | /**
26 | * 获取某条新闻详情
27 | *
28 | * @param id 新闻Id
29 | * @param callback 回调
30 | */
31 | void getNewsDetail(String id, InfoCallback callback);
32 |
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/data/bean/MessageDetail.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.data.bean;
2 |
3 | import java.util.List;
4 |
5 | public class MessageDetail {
6 | private String body;
7 | private String image_source;
8 | private String title;
9 | private String image;
10 | private String share_url;
11 | private List recommenders;
12 | private String ga_prefix;
13 | private String type;
14 | private String id;
15 |
16 | public String getBody() {
17 | return body;
18 | }
19 |
20 | public void setBody(String body) {
21 | this.body = body;
22 | }
23 |
24 | public String getImage_source() {
25 | return image_source;
26 | }
27 |
28 | public void setImage_source(String image_source) {
29 | this.image_source = image_source;
30 | }
31 |
32 | public String getTitle() {
33 | return title;
34 | }
35 |
36 | public void setTitle(String title) {
37 | this.title = title;
38 | }
39 |
40 | public String getImage() {
41 | return image;
42 | }
43 |
44 | public void setImage(String image) {
45 | this.image = image;
46 | }
47 |
48 | public String getShare_url() {
49 | return share_url;
50 | }
51 |
52 | public void setShare_url(String share_url) {
53 | this.share_url = share_url;
54 | }
55 |
56 | public List getRecommenders() {
57 | return recommenders;
58 | }
59 |
60 | public void setRecommenders(List recommenders) {
61 | this.recommenders = recommenders;
62 | }
63 |
64 | public String getGa_prefix() {
65 | return ga_prefix;
66 | }
67 |
68 | public void setGa_prefix(String ga_prefix) {
69 | this.ga_prefix = ga_prefix;
70 | }
71 |
72 | public String getType() {
73 | return type;
74 | }
75 |
76 | public void setType(String type) {
77 | this.type = type;
78 | }
79 |
80 | public String getId() {
81 | return id;
82 | }
83 |
84 | public void setId(String id) {
85 | this.id = id;
86 | }
87 |
88 | @Override
89 | public String toString() {
90 | return "MessageDetail{" +
91 | "body='" + body + '\'' +
92 | ", image_source='" + image_source + '\'' +
93 | ", title='" + title + '\'' +
94 | ", image='" + image + '\'' +
95 | ", share_url='" + share_url + '\'' +
96 | ", recommenders=" + recommenders +
97 | ", ga_prefix='" + ga_prefix + '\'' +
98 | ", type='" + type + '\'' +
99 | ", id='" + id + '\'' +
100 | '}';
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/data/bean/Story.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.data.bean;
2 |
3 | /**
4 | * 日报新闻实体类
5 | */
6 | public class Story {
7 |
8 | /**
9 | * 新闻标题
10 | **/
11 | private String title;
12 | /**
13 | * 供 Google Analytics 使用
14 | **/
15 | private String ga_prefix;
16 | /**
17 | * 图像地址(官方 API 使用数组形式。目前暂未有使用多张图片的情形出现,曾见无 images 属性的情况,请在使用中注意 )
18 | **/
19 | private String[] images;
20 | /**
21 | * 消息是否包含多张图片(仅出现在包含多图的新闻中)
22 | **/
23 | private String multipic;
24 | private String type;
25 | /**
26 | * url 与 share_url 中最后的数字(应为内容的 id)
27 | **/
28 | private String id;
29 |
30 | public String getTitle() {
31 | return title;
32 | }
33 |
34 | public void setTitle(String title) {
35 | this.title = title;
36 | }
37 |
38 | public String getGa_prefix() {
39 | return ga_prefix;
40 | }
41 |
42 | public void setGa_prefix(String ga_prefix) {
43 | this.ga_prefix = ga_prefix;
44 | }
45 |
46 | public String[] getImages() {
47 | return images;
48 | }
49 |
50 | public void setImages(String[] images) {
51 | this.images = images;
52 | }
53 |
54 | public String getMultipic() {
55 | return multipic;
56 | }
57 |
58 | public void setMultipic(String multipic) {
59 | this.multipic = multipic;
60 | }
61 |
62 | public String getType() {
63 | return type;
64 | }
65 |
66 | public void setType(String type) {
67 | this.type = type;
68 | }
69 |
70 | public String getId() {
71 | return id;
72 | }
73 |
74 | public void setId(String id) {
75 | this.id = id;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/data/bean/StoryList.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.data.bean;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * 类说明
7 | *
8 | * @author 张华洋 2017/4/20 23:04
9 | * @version V1.2.0
10 | * @name StoryList
11 | */
12 | public class StoryList {
13 |
14 | private String date;
15 | private List stories;
16 |
17 | public String getDate() {
18 | return date;
19 | }
20 |
21 | public void setDate(String date) {
22 | this.date = date;
23 | }
24 |
25 | public List getStories() {
26 | return stories;
27 | }
28 |
29 | public void setStories(List stories) {
30 | this.stories = stories;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/data/source/RemoteNewsDataSource.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.data.source;
2 |
3 | import com.guiying.module.common.base.InfoCallback;
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.news.Constants;
8 | import com.guiying.module.news.data.NewsDataSource;
9 | import com.guiying.module.news.data.bean.MessageDetail;
10 | import com.guiying.module.news.data.bean.StoryList;
11 |
12 | /**
13 | * 类说明
14 | *
15 | * @author 张华洋 2017/4/20 23:32
16 | * @version V1.2.0
17 | * @name RemoteNewsDataSource
18 | */
19 | public class RemoteNewsDataSource implements NewsDataSource {
20 |
21 | @Override
22 | public void getNewsList(String date, final InfoCallback callback) {
23 | HttpClient client = new HttpClient.Builder()
24 | .baseUrl(Constants.ZHIHU_DAILY_BEFORE_MESSAGE)
25 | .url(date)
26 | .bodyType(DataType.JSON_OBJECT, StoryList.class)
27 | .build();
28 | client.get(new OnResultListener() {
29 |
30 | @Override
31 | public void onSuccess(StoryList result) {
32 | callback.onSuccess(result);
33 | }
34 |
35 | @Override
36 | public void onError(int code, String message) {
37 | callback.onError(code, message);
38 | }
39 |
40 | @Override
41 | public void onFailure(String message) {
42 | callback.onError(0, message);
43 | }
44 | });
45 | }
46 |
47 |
48 | @Override
49 | public void getNewsDetail(String id, final InfoCallback callback) {
50 | HttpClient client = new HttpClient.Builder()
51 | .baseUrl(Constants.ZHIHU_DAILY_BEFORE_MESSAGE_DETAIL)
52 | .url(id)
53 | .bodyType(DataType.JSON_OBJECT, MessageDetail.class)
54 | .build();
55 | client.get(new OnResultListener() {
56 |
57 | @Override
58 | public void onSuccess(MessageDetail result) {
59 | callback.onSuccess(result);
60 | }
61 |
62 | @Override
63 | public void onError(int code, String message) {
64 | callback.onError(code, message);
65 | }
66 |
67 | @Override
68 | public void onFailure(String message) {
69 | callback.onError(0, message);
70 | }
71 | });
72 | }
73 |
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/detail/NewsDetailActivity.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.detail;
2 |
3 | import android.os.Bundle;
4 |
5 | import com.alibaba.android.arouter.facade.annotation.Route;
6 | import com.guiying.module.common.base.BaseActivity;
7 |
8 | /**
9 | * 类说明
10 | *
11 | * @author 张华洋 2017/7/1 13:13
12 | * @version V1.2.0
13 | * @name NewsDetailActivity
14 | */
15 | @Route(path = "/news/detail")
16 | public class NewsDetailActivity extends BaseActivity {
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | NewsDetailView detailView = new NewsDetailView(this);
22 | setContentView(detailView);
23 | String id = getIntent().getStringExtra("id");
24 | new NewsDetailPresenter(detailView).getNewsDetail(id);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/detail/NewsDetailContract.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.detail;
2 |
3 | import com.guiying.module.common.base.BasePresenter;
4 | import com.guiying.module.common.base.BaseView;
5 | import com.guiying.module.news.data.bean.MessageDetail;
6 |
7 | /**
8 | * 类说明
9 | *
10 | * @author 张华洋 2017/2/22 20:33
11 | * @version V1.2.0
12 | * @name NewsContract
13 | */
14 | public interface NewsDetailContract {
15 |
16 | interface View extends BaseView {
17 |
18 | boolean isActive();
19 |
20 | void showNewsDetail(MessageDetail detail);
21 |
22 | }
23 |
24 | interface Presenter extends BasePresenter {
25 |
26 | /**
27 | * 获取最新列表
28 | *
29 | * @param newsId 新闻id
30 | */
31 | void getNewsDetail(String newsId);
32 |
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/detail/NewsDetailPresenter.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.detail;
2 |
3 | import com.guiying.module.common.base.InfoCallback;
4 | import com.guiying.module.news.data.NewsDataSource;
5 | import com.guiying.module.news.data.bean.MessageDetail;
6 | import com.guiying.module.news.data.source.RemoteNewsDataSource;
7 |
8 | /**
9 | * 类说明
10 | *
11 | * @author 张华洋 2017/2/22 20:33
12 | * @version V1.2.0
13 | * @name GirlsPresenter
14 | */
15 | public class NewsDetailPresenter implements NewsDetailContract.Presenter {
16 |
17 | private NewsDetailContract.View mView;
18 | private NewsDataSource mDataSource;
19 |
20 | public NewsDetailPresenter(NewsDetailContract.View view) {
21 | mView = view;
22 | mDataSource = new RemoteNewsDataSource();
23 | mView.setPresenter(this);
24 | }
25 |
26 | @Override
27 | public void start() {
28 |
29 | }
30 |
31 |
32 | @Override
33 | public void getNewsDetail(String newsId) {
34 | mDataSource.getNewsDetail(newsId, new InfoCallback() {
35 | @Override
36 | public void onSuccess(MessageDetail detail) {
37 | if (mView.isActive()) {
38 | mView.showNewsDetail(detail);
39 | }
40 | }
41 |
42 | @Override
43 | public void onError(int code, String message) {
44 |
45 | }
46 | });
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/detail/NewsDetailView.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.detail;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.drawable.BitmapDrawable;
8 | import android.graphics.drawable.Drawable;
9 | import android.support.design.widget.CollapsingToolbarLayout;
10 | import android.text.Html;
11 | import android.text.method.LinkMovementMethod;
12 | import android.util.AttributeSet;
13 | import android.widget.FrameLayout;
14 | import android.widget.ImageView;
15 | import android.widget.TextView;
16 |
17 | import com.bumptech.glide.Glide;
18 | import com.bumptech.glide.request.animation.GlideAnimation;
19 | import com.bumptech.glide.request.target.SimpleTarget;
20 | import com.guiying.module.news.R;
21 | import com.guiying.module.news.data.bean.MessageDetail;
22 |
23 | /**
24 | * 类说明
25 | *
26 | * @author 张华洋 2017/7/1 13:18
27 | * @version V1.2.0
28 | * @name NewsDetailView
29 | */
30 |
31 | public class NewsDetailView extends FrameLayout implements NewsDetailContract.View {
32 |
33 | private boolean isActive = false;
34 | private NewsDetailContract.Presenter mPresenter;
35 | private ImageView mToolbarImage;
36 | private TextView mToolbarText;
37 | private CollapsingToolbarLayout mCollapsingLayout;
38 | private TextView mDetailText;
39 |
40 |
41 | public NewsDetailView(Context context) {
42 | super(context);
43 | initView();
44 | }
45 |
46 | public NewsDetailView(Context context, AttributeSet attrs) {
47 | super(context, attrs);
48 | initView();
49 | }
50 |
51 | private void initView() {
52 | inflate(getContext(), R.layout.view_news_detail, this);
53 | mToolbarImage = (ImageView) findViewById(R.id.toolbar_image);
54 | mToolbarText = (TextView) findViewById(R.id.toolbar_text);
55 | mCollapsingLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_layout);
56 | mDetailText = (TextView) findViewById(R.id.news_detail_text);
57 |
58 | isActive = true;
59 | }
60 |
61 | @Override
62 | protected void onAttachedToWindow() {
63 | super.onAttachedToWindow();
64 | isActive = true;
65 | }
66 |
67 | @Override
68 | protected void onDetachedFromWindow() {
69 | super.onDetachedFromWindow();
70 | isActive = false;
71 | }
72 |
73 | @Override
74 | public boolean isActive() {
75 | return isActive;
76 | }
77 |
78 |
79 | @Override
80 | public void setPresenter(NewsDetailContract.Presenter presenter) {
81 | mPresenter = presenter;
82 | }
83 |
84 | @Override
85 | public void showNewsDetail(MessageDetail detail) {
86 | mCollapsingLayout.setTitle(detail.getTitle());
87 | //设置还没收缩时状态下字体颜色
88 | mCollapsingLayout.setExpandedTitleColor(Color.WHITE);
89 | //设置收缩后Toolbar上字体的颜色
90 | mCollapsingLayout.setCollapsedTitleTextColor(Color.WHITE);
91 | mToolbarText.setText(detail.getImage_source());
92 | Glide.with(getContext())
93 | .load(detail.getImage())
94 | .thumbnail(0.2f)
95 | .into(mToolbarImage);
96 | mDetailText.setMovementMethod(LinkMovementMethod.getInstance());
97 | mDetailText.setText(Html.fromHtml(detail.getBody(), new Html.ImageGetter() {
98 | @Override
99 | public Drawable getDrawable(String source) {
100 | final URLDrawable urlDrawable = new URLDrawable();
101 | Glide.with(getContext()).load(source).asBitmap().into(new SimpleTarget() {
102 |
103 | @Override
104 | public void onResourceReady(Bitmap resource, GlideAnimation super Bitmap> glideAnimation) {
105 | urlDrawable.bitmap = resource;
106 | urlDrawable.setBounds(0, 0, resource.getWidth(), resource.getHeight());
107 | mDetailText.invalidate();
108 | // 解决图文重叠
109 | mDetailText.setText(mDetailText.getText());
110 | }
111 | });
112 | return urlDrawable;
113 | }
114 | }, null));
115 | }
116 |
117 |
118 | private class URLDrawable extends BitmapDrawable {
119 |
120 | private Bitmap bitmap;
121 |
122 | @Override
123 | public void draw(Canvas canvas) {
124 | if (bitmap != null) {
125 | canvas.drawBitmap(bitmap, 0, 0, getPaint());
126 | }
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/main/NewsCenterActivity.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.main;
2 |
3 | import android.os.Bundle;
4 | import android.support.design.widget.TabLayout;
5 | import android.support.v4.view.ViewPager;
6 | import android.support.v7.widget.Toolbar;
7 |
8 | import com.alibaba.android.arouter.facade.annotation.Route;
9 | import com.guiying.module.common.base.BaseActivity;
10 | import com.guiying.module.news.R;
11 |
12 | import java.text.SimpleDateFormat;
13 | import java.util.ArrayList;
14 | import java.util.Calendar;
15 | import java.util.List;
16 | import java.util.Locale;
17 |
18 | /**
19 | * 类说明
20 | *
21 | * @author 张华洋 2017/4/20 22:26
22 | * @version V1.2.0
23 | * @name NewsCenterActivity
24 | */
25 | @Route(path = "/news/center")
26 | public class NewsCenterActivity extends BaseActivity {
27 |
28 | protected Toolbar mToolBar;
29 | protected TabLayout mTabLayout;
30 | protected ViewPager mViewPager;
31 | private NewsListViewAdapter mListAdapter;
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | super.setContentView(R.layout.activity_news);
37 | mToolBar = (Toolbar) findViewById(R.id.news_title_bar);
38 | mToolBar.setTitle("知乎日报");
39 | setupToolBar(mToolBar, false);
40 | mTabLayout = (TabLayout) findViewById(R.id.date_tab);
41 | mViewPager = (ViewPager) findViewById(R.id.message_pager);
42 | mListAdapter = new NewsListViewAdapter(getMessageListViews(), getWeekDate());
43 | mViewPager.setAdapter(mListAdapter);
44 | //setupWithViewPager必须在ViewPager.setAdapter()之后调用
45 | mTabLayout.setupWithViewPager(mViewPager);
46 | }
47 |
48 | /**
49 | * 获取ViewPager的viewList
50 | */
51 | private List getMessageListViews() {
52 | List viewList = new ArrayList<>();
53 | List weekDate = getWeekDate();
54 | if (weekDate != null) {
55 | for (String tab : weekDate) {
56 | viewList.add(new NewsListView(this, tab));
57 | }
58 | }
59 | return viewList;
60 | }
61 |
62 |
63 | /**
64 | * 获取过去7天的时期,格式为yymmdd
65 | **/
66 | public static List getWeekDate() {
67 | List dates = new ArrayList<>();
68 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
69 | for (int i = 0; i < 7; i++) {
70 | Calendar calendar = Calendar.getInstance();
71 | calendar.add(Calendar.DAY_OF_YEAR, 1 - i);
72 | dates.add(simpleDateFormat.format(calendar.getTime()));
73 | }
74 | return dates;
75 | }
76 |
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/main/NewsListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.main;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ImageView;
8 | import android.widget.TextView;
9 |
10 | import com.bumptech.glide.Glide;
11 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
12 | import com.guiying.module.news.R;
13 | import com.guiying.module.news.data.bean.Story;
14 | import com.guiying.module.news.detail.NewsDetailActivity;
15 | import com.jude.easyrecyclerview.adapter.BaseViewHolder;
16 | import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter;
17 |
18 | /**
19 | * 类说明
20 | *
21 | * @author 张华洋 2017/4/20 22:26
22 | * @version V1.2.0
23 | * @name NewsListAdapter
24 | */
25 | public class NewsListAdapter extends RecyclerArrayAdapter {
26 |
27 | public NewsListAdapter(Context context) {
28 | super(context);
29 | }
30 |
31 | @Override
32 | public BaseViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) {
33 | return new NewsListHolder(parent);
34 | }
35 |
36 | private class NewsListHolder extends BaseViewHolder {
37 |
38 | private TextView mTextView;
39 | private ImageView mImageView;
40 |
41 | NewsListHolder(ViewGroup parent) {
42 | super(parent, R.layout.item_news_list);
43 | mTextView = $(R.id.news_title);
44 | mImageView = $(R.id.news_image);
45 | }
46 |
47 | @Override
48 | public void setData(final Story data) {
49 | super.setData(data);
50 | mTextView.setText(data.getTitle());
51 | Glide.with(getContext())
52 | .load(data.getImages()[0])
53 | .centerCrop()
54 | .crossFade()
55 | .diskCacheStrategy(DiskCacheStrategy.SOURCE)
56 | .into(mImageView);
57 | itemView.setOnClickListener(new View.OnClickListener() {
58 | @Override
59 | public void onClick(View view) {
60 | Intent intent = new Intent(getContext(), NewsDetailActivity.class);
61 | intent.putExtra("id", data.getId());
62 | getContext().startActivity(intent);
63 | }
64 | });
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/main/NewsListContract.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.main;
2 |
3 | import com.guiying.module.common.base.BasePresenter;
4 | import com.guiying.module.common.base.BaseView;
5 | import com.guiying.module.news.data.bean.StoryList;
6 |
7 | /**
8 | * 类说明
9 | *
10 | * @author 张华洋 2017/2/22 20:33
11 | * @version V1.2.0
12 | * @name NewsContract
13 | */
14 | public interface NewsListContract {
15 |
16 | interface View extends BaseView {
17 |
18 | boolean isActive();
19 |
20 | void showNewsList(StoryList info);
21 |
22 | }
23 |
24 | interface Presenter extends BasePresenter {
25 |
26 | /**
27 | * 获取最新列表
28 | *
29 | * @param date
30 | */
31 | void getNewMessages(int page, int size, String date);
32 |
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/main/NewsListPresenter.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.main;
2 |
3 | import com.guiying.module.common.base.InfoCallback;
4 | import com.guiying.module.news.data.NewsDataSource;
5 | import com.guiying.module.news.data.bean.StoryList;
6 | import com.guiying.module.news.data.source.RemoteNewsDataSource;
7 |
8 | /**
9 | * 类说明
10 | *
11 | * @author 张华洋 2017/2/22 20:33
12 | * @version V1.2.0
13 | * @name GirlsPresenter
14 | */
15 | public class NewsListPresenter implements NewsListContract.Presenter {
16 |
17 | private NewsListContract.View mView;
18 | private NewsDataSource mDataSource;
19 |
20 | public NewsListPresenter(NewsListContract.View view) {
21 | mView = view;
22 | mDataSource = new RemoteNewsDataSource();
23 | mView.setPresenter(this);
24 | }
25 |
26 | @Override
27 | public void start() {
28 |
29 | }
30 |
31 | @Override
32 | public void getNewMessages(int page, int size, String date) {
33 | mDataSource.getNewsList(date, new InfoCallback() {
34 | @Override
35 | public void onSuccess(StoryList info) {
36 | if (mView.isActive()) {
37 | mView.showNewsList(info);
38 | }
39 | }
40 |
41 | @Override
42 | public void onError(int code, String message) {
43 |
44 | }
45 | });
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/main/NewsListView.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.main;
2 |
3 | import android.content.Context;
4 | import android.support.v4.content.ContextCompat;
5 | import android.support.v4.widget.SwipeRefreshLayout;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.util.AttributeSet;
8 |
9 | import com.guiying.module.news.R;
10 | import com.guiying.module.news.data.bean.StoryList;
11 | import com.jude.easyrecyclerview.EasyRecyclerView;
12 | import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter;
13 | import com.jude.easyrecyclerview.decoration.DividerDecoration;
14 |
15 | /**
16 | * 类说明
17 | *
18 | * @author 张华洋 2017/4/20 22:21
19 | * @version V1.2.0
20 | * @name NewListView
21 | */
22 | public class NewsListView extends EasyRecyclerView implements NewsListContract.View, SwipeRefreshLayout.OnRefreshListener {
23 | private NewsListContract.Presenter mPresenter;
24 | private String mDate;
25 | private NewsListAdapter mAdapter;
26 | private boolean isActive = false;
27 |
28 | public NewsListView(Context context, String date) {
29 | super(context);
30 | mDate = date;
31 | initView();
32 | }
33 |
34 | public NewsListView(Context context, AttributeSet attrs) {
35 | super(context, attrs);
36 | initView();
37 | }
38 |
39 | private void initView() {
40 | setRefreshingColor(
41 | ContextCompat.getColor(getContext(), R.color.colorPrimary),
42 | ContextCompat.getColor(getContext(), android.R.color.holo_blue_light),
43 | ContextCompat.getColor(getContext(), android.R.color.holo_green_light)
44 | );
45 | LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
46 | setLayoutManager(layoutManager);
47 | DividerDecoration dividerDecoration = new DividerDecoration(getResources().getColor(R.color.gray_e0), 20, 20, 0);
48 | dividerDecoration.setDrawLastItem(true);
49 | addItemDecoration(dividerDecoration);
50 | mAdapter = new NewsListAdapter(getContext());
51 | mAdapter.setOnItemClickListener(new RecyclerArrayAdapter.OnItemClickListener() {
52 | @Override
53 | public void onItemClick(int position) {
54 |
55 | }
56 | });
57 |
58 | setAdapterWithProgress(mAdapter);
59 | setRefreshListener(this);
60 | new NewsListPresenter(this);
61 | isActive = true;
62 | }
63 |
64 | @Override
65 | public void onRefresh() {
66 | mPresenter.getNewMessages(1, 20, mDate);
67 | }
68 |
69 | @Override
70 | protected void onAttachedToWindow() {
71 | super.onAttachedToWindow();
72 | isActive = true;
73 | mPresenter.getNewMessages(1, 20, mDate);
74 | }
75 |
76 | @Override
77 | protected void onDetachedFromWindow() {
78 | super.onDetachedFromWindow();
79 | isActive = false;
80 | }
81 |
82 | @Override
83 | public void setPresenter(NewsListContract.Presenter presenter) {
84 | mPresenter = presenter;
85 | }
86 |
87 | @Override
88 | public boolean isActive() {
89 | return isActive;
90 | }
91 |
92 | @Override
93 | public void showNewsList(StoryList info) {
94 | if (info != null) {
95 | mAdapter.clear();
96 | mAdapter.addAll(info.getStories());
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/module_news/src/main/java/com/guiying/module/news/main/NewsListViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.guiying.module.news.main;
2 |
3 | import android.support.v4.view.PagerAdapter;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 |
7 | import java.text.DateFormat;
8 | import java.util.Calendar;
9 | import java.util.List;
10 |
11 | /**
12 | * 类说明
13 | *
14 | * @author 张华洋 2017/4/20 23:41
15 | * @version V1.2.0
16 | * @name NewsListViewAdapter
17 | */
18 | public class NewsListViewAdapter extends PagerAdapter {
19 |
20 | private final List extends View> mViewList;
21 | private final List mTabList;
22 | private View mCurrentView;
23 |
24 | public NewsListViewAdapter(List extends View> list, List dates) {
25 | mViewList = list;
26 | mTabList = dates;
27 | }
28 |
29 | @Override
30 | public int getCount() {
31 | return mViewList == null ? 0 : mViewList.size();
32 | }
33 |
34 | @Override
35 | public boolean isViewFromObject(View view, Object object) {
36 | return view == object;
37 | }
38 |
39 | @Override
40 | public Object instantiateItem(ViewGroup container, int position) {
41 | container.addView((mViewList.get(position)));
42 | return mViewList.get(position);
43 | }
44 |
45 | @Override
46 | public void destroyItem(ViewGroup container, int position, Object object) {
47 | container.removeView(mViewList.get(position));
48 | }
49 |
50 | @Override
51 | public CharSequence getPageTitle(int position) {
52 | if (mTabList == null) {
53 | return null;
54 | }
55 | Calendar displayDate = Calendar.getInstance();
56 | displayDate.add(Calendar.DAY_OF_YEAR, -position);
57 |
58 | return DateFormat.getDateInstance().format(displayDate.getTime());
59 | }
60 |
61 | /**
62 | * 获取当前view的方法
63 | */
64 | View getCurrentView() {
65 | return mCurrentView;
66 | }
67 |
68 | @Override
69 | public void setPrimaryItem(ViewGroup container, int position, Object object) {
70 | super.setPrimaryItem(container, position, object);
71 | if (mViewList.size() > 0) {
72 | mCurrentView = mViewList.get(position);
73 | }
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/module_news/src/main/java/debug/LauncherActivity.java:
--------------------------------------------------------------------------------
1 | package debug;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 |
7 | import com.guiying.module.news.detail.NewsDetailActivity;
8 |
9 | /**
10 | * 组件开发模式下,用于传递数据的启动Activity,集成模式下无效
11 | *
12 | * @author 张华洋
13 | * @version V1.2.0
14 | * @name LauncherActivity
15 | */
16 | public class LauncherActivity extends AppCompatActivity {
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | //在这里传值给需要调试的Activity
22 | Intent intent = new Intent(this, NewsDetailActivity.class);
23 | intent.putExtra("id", "9500116");
24 | startActivity(intent);
25 | finish();
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/module_news/src/main/java/debug/NewsApplication.java:
--------------------------------------------------------------------------------
1 | package debug;
2 |
3 | import com.guiying.module.common.base.BaseApplication;
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.news.Constants;
8 | import com.guiying.module.news.data.bean.StoryList;
9 | import com.orhanobut.logger.Logger;
10 |
11 | /**
12 | * 类说明
13 | *
14 | * @author 张华洋 2017/2/15 20:11
15 | * @version V1.2.0
16 | * @name NewsApplication
17 | */
18 | public class NewsApplication extends BaseApplication {
19 |
20 | @Override
21 | public void onCreate() {
22 | super.onCreate();
23 | login();
24 | }
25 |
26 |
27 | /**
28 | * 在这里模拟登陆,然后拿到sessionId或者Token
29 | * 这样就能够在组件请求接口了
30 | */
31 | private void login() {
32 | HttpClient client = new HttpClient.Builder()
33 | .baseUrl(Constants.ZHIHU_DAILY_BEFORE_MESSAGE)
34 | .url("20170419")
35 | .bodyType(DataType.JSON_OBJECT, StoryList.class)
36 | .build();
37 | client.get(new OnResultListener() {
38 |
39 | @Override
40 | public void onSuccess(StoryList result) {
41 | Logger.e(result.toString());
42 | }
43 |
44 | @Override
45 | public void onError(int code, String message) {
46 | Logger.e(message);
47 | }
48 |
49 | @Override
50 | public void onFailure(String message) {
51 | Logger.e(message);
52 | }
53 | });
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/module_news/src/main/module/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
24 |
28 |
29 |
--------------------------------------------------------------------------------
/module_news/src/main/res/layout/activity_news.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
20 |
21 |
27 |
28 |
29 |
30 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/module_news/src/main/res/layout/fragment_news.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/module_news/src/main/res/layout/item_news_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
28 |
--------------------------------------------------------------------------------
/module_news/src/main/res/layout/view_news_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
12 |
20 |
21 |
25 |
26 |
32 |
33 |
42 |
43 |
44 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
60 |
61 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/module_news/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/module_news/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/module_news/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | News组件
3 |
4 | News
5 |
6 |
7 | Hello blank fragment
8 |
9 |
10 |
--------------------------------------------------------------------------------
/screenshots/Screenshot_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/screenshots/Screenshot_1.png
--------------------------------------------------------------------------------
/screenshots/Screenshot_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/screenshots/Screenshot_2.png
--------------------------------------------------------------------------------
/screenshots/Screenshot_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/screenshots/Screenshot_3.png
--------------------------------------------------------------------------------
/screenshots/Screenshot_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/screenshots/Screenshot_4.png
--------------------------------------------------------------------------------
/screenshots/develper.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guiying712/AndroidModulePattern/494e7deda04ea1a9dc0bad006ca218c635a8957f/screenshots/develper.PNG
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':lib_common',
2 | ':module_app',
3 | ':module_main',
4 | ':module_girls',
5 | ':module_news'
6 |
7 |
--------------------------------------------------------------------------------
/versions.gradle:
--------------------------------------------------------------------------------
1 | /**
2 | * Shared file between builds so that they can all use the same dependencies and
3 | * maven repositories.
4 | **/
5 | ext.deps = [:]
6 |
7 | def versions = [:]
8 | versions.android_gradle_plugin = "3.0.1"
9 | versions.kotlin = "1.1.51"
10 | versions.support = "27.0.2"
11 | versions.multidex = "1.0.2"
12 | versions.constraint_layout = "1.0.2"
13 | versions.dagger = "2.11"
14 | versions.glide = "3.8.0"
15 | versions.rxjava2 = "2.1.7"
16 | versions.rx_android = "2.0.1"
17 | versions.retrofit = "2.3.0"
18 | versions.event_bus = "3.1.1"
19 | versions.photo_view = "2.0.0"
20 | versions.persistent_cookie = "v1.0.1"
21 | versions.gson = "2.8.2"
22 | versions.qmui = "1.0.4"
23 | versions.flow_layout = "1.0.3"
24 | versions.swipe_recycler = "1.1.3"
25 | versions.easy_recycler = "4.4.2"
26 | versions.permission = "1.1.2"
27 | versions.utils = "1.10.0"
28 | versions.top_snackbar = "1.1.1"
29 | versions.litepal = "1.6.1"
30 | versions.toasty = "1.1.3"
31 | versions.logger = "1.15"
32 | versions.material_dialog = "0.9.6.0"
33 | //Arouter
34 | versions.arouter_compiler = "1.1.4"
35 | versions.arouter_api = "1.3.1"
36 |
37 |
38 |
39 | def deps = [:]
40 |
41 | def support = [:]
42 | support.annotations = "com.android.support:support-annotations:$versions.support"
43 | support.app_compat = "com.android.support:appcompat-v7:$versions.support"
44 | support.v13 = "com.android.support:support-v13:$versions.support"
45 | support.percent = "com.android.support:percent:$versions.support"
46 | support.recyclerview = "com.android.support:recyclerview-v7:$versions.support"
47 | support.cardview = "com.android.support:cardview-v7:$versions.support"
48 | support.design = "com.android.support:design:$versions.support"
49 | support.v4 = "com.android.support:support-v4:$versions.support"
50 | support.core_utils = "com.android.support:support-core-utils:$versions.support"
51 | support.multidex = "com.android.support:multidex:$versions.multidex"
52 | deps.support = support
53 |
54 |
55 | def retrofit = [:]
56 | retrofit.runtime = "com.squareup.retrofit2:retrofit:$versions.retrofit"
57 | retrofit.adapter = "com.squareup.retrofit2:adapter-rxjava2:$versions.retrofi"
58 | retrofit.gson = "com.squareup.retrofit2:converter-gson:$versions.retrofit"
59 | deps.retrofit = retrofit
60 |
61 |
62 | def dagger = [:]
63 | dagger.runtime = "com.google.dagger:dagger:$versions.dagger"
64 | dagger.android = "com.google.dagger:dagger-android:$versions.dagger"
65 | dagger.android_support = "com.google.dagger:dagger-android-support:$versions.dagger"
66 | dagger.compiler = "com.google.dagger:dagger-compiler:$versions.dagger"
67 | dagger.android_support_compiler = "com.google.dagger:dagger-android-processor:$versions.dagger"
68 | deps.dagger = dagger
69 |
70 |
71 | def kotlin = [:]
72 | kotlin.stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jre7:$versions.kotlin"
73 | kotlin.test = "org.jetbrains.kotlin:kotlin-test-junit:$versions.kotlin"
74 | kotlin.plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin"
75 | deps.kotlin = kotlin
76 |
77 | //view
78 | deps.constraint_layout = "com.android.support.constraint:constraint-layout:$versions.constraint_layout"
79 | deps.qmui = "com.qmuiteam:qmui:$versions.qmui"
80 | deps.flow_layout = "com.zhy:flowlayout-lib:$versions.flow_layout"
81 | deps.swipe_recycler = "com.yanzhenjie:recyclerview-swipe:$versions.swipe_recycler"
82 | deps.easy_recycler = "com.jude:easyrecyclerview:$versions.easy_recycler"
83 | deps.photo_view = "com.github.chrisbanes:PhotoView:$versions.photo_view"
84 | deps.material_dialog = "com.afollestad.material-dialogs:core:$versions.material_dialog"
85 |
86 | deps.android_gradle_plugin = "com.android.tools.build:gradle:$versions.android_gradle_plugin"
87 | deps.rxjava2 = "io.reactivex.rxjava2:rxjava:$versions.rxjava2"
88 | deps.rx_android = "io.reactivex.rxjava2:rxandroid:$versions.rx_android"
89 | //other
90 | deps.glide = "com.github.bumptech.glide:glide:$versions.glide"
91 | deps.event_bus = "org.greenrobot:eventbus:$versions.event_bus"
92 | deps.persistent_cookie = "com.github.franmontiel:PersistentCookieJar:$versions.persistent_cookie"
93 | deps.gson = "com.google.code.gson:gson:$versions.gson"
94 | deps.permission = "com.yanzhenjie:permission:$versions.permission"
95 | deps.utils = "com.blankj:utilcode:$versions.utils"
96 | deps.top_snackbar ="com.androidadvance:topsnackbar:$versions.top_snackbar"
97 | deps.litepal = "org.litepal.android:core:$versions.litepal"
98 | deps.toasty = "com.github.GrenderG:Toasty:$versions.toasty"
99 | deps.logger = "com.orhanobut:logger:$versions.logger"
100 | deps.arouter_api = "com.alibaba:arouter-api:$versions.arouter_api"
101 | deps.arouter_compiler = "com.alibaba:arouter-compiler:$versions.arouter_compiler"
102 |
103 | ext.deps = deps
104 |
105 | def build_versions = [:]
106 | build_versions.min_sdk = 16
107 | build_versions.target_sdk = 27
108 | build_versions.build_tools = "27.0.2"
109 | ext.build_versions = build_versions
110 |
111 |
112 | def addRepos(RepositoryHandler handler) {
113 | handler.google()
114 | handler.jcenter()
115 | handler.mavenCentral()
116 | //Add the JitPack repository
117 | handler.maven { url "https://jitpack.io" }
118 | handler.maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
119 | }
120 |
121 | ext.addRepos = this.&addRepos
122 |
--------------------------------------------------------------------------------