├── .gitignore
├── .idea
├── gradle.xml
├── misc.xml
├── modules.xml
└── runConfigurations.xml
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── senon
│ │ └── modularapp
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── senon
│ │ │ └── modularapp
│ │ │ ├── App.java
│ │ │ ├── MainActivity.java
│ │ │ └── TestActivity.java
│ └── res
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_test.xml
│ │ ├── pop_item.xml
│ │ └── pop_test.xml
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── senon
│ └── modularapp
│ └── ExampleUnitTest.java
├── build.gradle
├── dependencies.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── lib_common
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── senon
│ │ └── lib_common
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── senon
│ │ │ └── lib_common
│ │ │ ├── AppConfig.java
│ │ │ ├── ConstantArouter.java
│ │ │ ├── ConstantLoginArouter.java
│ │ │ ├── adapter
│ │ │ ├── CommonAdapter.java
│ │ │ ├── CommonHolder.java
│ │ │ ├── RecycleHolder.java
│ │ │ └── RecyclerAdapter.java
│ │ │ ├── api
│ │ │ └── BaseApi.java
│ │ │ ├── base
│ │ │ ├── BaseActivity.java
│ │ │ ├── BaseAppDeletage.java
│ │ │ ├── BaseApplication.java
│ │ │ ├── BaseEvent.java
│ │ │ ├── BaseFragment.java
│ │ │ ├── BaseLazyFragment.java
│ │ │ ├── BaseModelCallBack.java
│ │ │ ├── BaseNestingLazyFragment.java
│ │ │ ├── BasePresenter.java
│ │ │ ├── BaseResponse.java
│ │ │ └── BaseViewImp.java
│ │ │ ├── bean
│ │ │ ├── Chapter.java
│ │ │ └── Login.java
│ │ │ ├── common
│ │ │ ├── contract
│ │ │ │ ├── LoginContract.java
│ │ │ │ └── ModelRequestContract.java
│ │ │ ├── model
│ │ │ │ └── ModelRequestMod.java
│ │ │ ├── presenter
│ │ │ │ ├── LoginPresenter.java
│ │ │ │ └── ModelRequestPresenter.java
│ │ │ └── ui
│ │ │ │ ├── LoginActivity.java
│ │ │ │ ├── ModelRequestActivity.java
│ │ │ │ └── RegisterActivity.java
│ │ │ ├── net
│ │ │ ├── RequestInterceptor.java
│ │ │ ├── ServerUtils.java
│ │ │ ├── callback
│ │ │ │ ├── ErrorListener.java
│ │ │ │ ├── RequestCallback.java
│ │ │ │ └── RxErrorHandler.java
│ │ │ └── progress
│ │ │ │ ├── ProgressCancelListener.java
│ │ │ │ └── ProgressDialogHandler.java
│ │ │ └── utils
│ │ │ ├── ActivityCollector.java
│ │ │ ├── ComUtil.java
│ │ │ ├── ConstantUtils.java
│ │ │ ├── JsonServiceImpl.java
│ │ │ ├── LogUtils.java
│ │ │ ├── MD5Utils.java
│ │ │ ├── PreferenceTool.java
│ │ │ ├── RetryWithDelay.java
│ │ │ ├── RxUtils.java
│ │ │ ├── StatusBarUtils.java
│ │ │ └── ToastUtil.java
│ └── res
│ │ ├── drawable
│ │ ├── common_ic_launcher_background.xml
│ │ └── common_toast_shape.xml
│ │ ├── layout
│ │ ├── common_activity_login.xml
│ │ ├── common_activity_modelrequest.xml
│ │ ├── common_activity_register.xml
│ │ └── common_toast_layout.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── senon
│ └── lib_common
│ └── ExampleUnitTest.java
├── lib_opensource
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── senon
│ │ └── lib_opensource
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ └── AndroidManifest.xml
│ └── test
│ └── java
│ └── com
│ └── senon
│ └── lib_opensource
│ └── ExampleUnitTest.java
├── module_one
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── senon
│ │ └── module_one
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── debug
│ │ └── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── senon
│ │ │ └── module_one
│ │ │ ├── App_One.java
│ │ │ ├── MainActivity.java
│ │ │ └── TestActivity.java
│ ├── release
│ │ └── AndroidManifest.xml
│ └── res
│ │ ├── drawable
│ │ └── one_ic_launcher_background.xml
│ │ ├── layout
│ │ ├── one_activity_main.xml
│ │ └── one_activity_test.xml
│ │ ├── mipmap-xhdpi
│ │ ├── one_ic_launcher.png
│ │ └── one_ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── one_ic_launcher.png
│ │ └── one_ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── senon
│ └── module_one
│ └── ExampleUnitTest.java
├── module_two
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── senon
│ │ └── module_two
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── debug
│ │ └── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── senon
│ │ │ └── module_two
│ │ │ ├── App_Two.java
│ │ │ ├── MainActivity.java
│ │ │ └── TestActivity.java
│ ├── release
│ │ └── AndroidManifest.xml
│ └── res
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── two_activity_main.xml
│ │ └── two_activity_test.xml
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── senon
│ └── module_two
│ └── ExampleUnitTest.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
24 |
25 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | 1.8
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion rootProject.ext.android["compileSdkVersion"]
5 |
6 | defaultConfig {
7 | applicationId "com.senon.modularapp"
8 | minSdkVersion rootProject.ext.android["minSdkVersion"]
9 | targetSdkVersion rootProject.ext.android["targetSdkVersion"]
10 | versionCode rootProject.ext.android["versionCode"]
11 | versionName rootProject.ext.android["versionName"]
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 | javaCompileOptions {
15 | annotationProcessorOptions {
16 | arguments = [AROUTER_MODULE_NAME: project.getName()]
17 | }
18 | }
19 | }
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | }
27 |
28 | dependencies {
29 | if (isBuildModule.toBoolean()) {
30 | implementation project(':lib_common')
31 | } else {
32 | implementation project(':module_one')
33 | implementation project(':module_two')
34 | }
35 |
36 | annotationProcessor rootProject.ext.dependencies["butterknife-compiler"]
37 | annotationProcessor rootProject.ext.dependencies["router-compiler"]
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/senon/modularapp/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.modularapp;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.senon.modularapp", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/senon/modularapp/App.java:
--------------------------------------------------------------------------------
1 | package com.senon.modularapp;
2 |
3 | import com.alibaba.android.arouter.launcher.ARouter;
4 | import com.senon.lib_common.base.BaseApplication;
5 | import com.senon.lib_common.utils.ConstantUtils;
6 |
7 | /**
8 | * 工程Application
9 | */
10 | public class App extends BaseApplication {
11 | @Override
12 | public void onCreate() {
13 | super.onCreate();
14 |
15 | initARouter();
16 | }
17 |
18 | private void initARouter() {
19 | if (ConstantUtils.isAppDebug()) {
20 | //开启InstantRun之后,一定要在ARouter.init之前调用openDebug
21 | ARouter.openDebug();
22 | ARouter.openLog();
23 | }
24 | ARouter.init(this);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/senon/modularapp/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.modularapp;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.widget.TextView;
6 | import com.alibaba.android.arouter.facade.annotation.Autowired;
7 | import com.alibaba.android.arouter.facade.annotation.Route;
8 | import com.alibaba.android.arouter.launcher.ARouter;
9 | import com.senon.lib_common.ConstantLoginArouter;
10 | import com.senon.lib_common.bean.Login;
11 | import com.senon.lib_common.utils.ComUtil;
12 | import com.senon.lib_common.utils.StatusBarUtils;
13 |
14 | /**
15 | * app 模块主页面
16 | */
17 | @Route(path = ConstantLoginArouter.PATH_APP_MAINACTIVITY)
18 | public class MainActivity extends AppCompatActivity {
19 |
20 | @Autowired
21 | Login data;
22 |
23 | @Override
24 | protected void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | StatusBarUtils.with(this).init();//沉浸式
27 | setContentView(R.layout.activity_main);
28 | ComUtil.changeStatusBarTextColor(this,true);
29 |
30 | ARouter.getInstance().inject(this);
31 |
32 | if(data == null){
33 | ((TextView)findViewById(R.id.main_tv)).setText("这是app模块 主页面MainActivity"+"\n没有携带参数: ");
34 | }else{
35 | ((TextView)findViewById(R.id.main_tv)).setText("这是app模块 主页面MainActivity"+"\n携带参数: "+data.toString());
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/senon/modularapp/TestActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.modularapp;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.WindowManager;
8 | import android.widget.ListView;
9 | import android.widget.PopupWindow;
10 | import com.alibaba.android.arouter.facade.annotation.Route;
11 | import com.alibaba.android.arouter.launcher.ARouter;
12 | import com.senon.lib_common.ConstantArouter;
13 | import com.senon.lib_common.ConstantLoginArouter;
14 | import com.senon.lib_common.adapter.CommonAdapter;
15 | import com.senon.lib_common.adapter.CommonHolder;
16 | import com.senon.lib_common.utils.ComUtil;
17 | import com.senon.lib_common.utils.StatusBarUtils;
18 | import java.util.ArrayList;
19 | import java.util.Map;
20 |
21 | /**
22 | * app test页面
23 | */
24 | @Route(path = ConstantArouter.PATH_APP_TESTACTIVITY)
25 | public class TestActivity extends AppCompatActivity {
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | StatusBarUtils.with(this).init();
31 | setContentView(R.layout.activity_test);
32 | ComUtil.changeStatusBarTextColor(this,true);
33 |
34 | }
35 |
36 | public void toA(View view){
37 | // 应用内简单的跳转
38 | // String curUrl = ConstantLoginArouter.getCurRouter(this.getClass().getSimpleName());
39 | // String curUrl = ConstantLoginArouter.getCurRouter(ConstantLoginArouter.PATH_HOME_MAINACTIVITY);
40 | // ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)//指定跳到那个页面
41 | // .withString("targetUrl", ConstantLoginArouter.PATH_APP_MAINACTIVITY)//传入目标页面路由地址 可以在指定页面跳入到目标页面
42 | // .navigation();
43 |
44 | showPopwindow(view,ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY);
45 |
46 | // 进阶用法
47 | // Uri testUriMix = Uri.parse("router://com.senon.firstmoduel/firstmoduel/firstmainactivity");
48 | // ARouter.getInstance().build(testUriMix)
49 | // .withString("key1", "value1")
50 | // .navigation();
51 | }
52 |
53 | public void toB(View view){
54 | showPopwindow(view,null);
55 | }
56 |
57 | private void showPopwindow(View v,final String gotoUrl){
58 | View view = LayoutInflater.from(this).inflate(R.layout.pop_test,null);
59 | final PopupWindow pop = new PopupWindow(view,WindowManager.LayoutParams.WRAP_CONTENT,
60 | WindowManager.LayoutParams.WRAP_CONTENT);
61 | ListView lv = view.findViewById(R.id.pop_lv);
62 | lv.setAdapter(new CommonAdapter(this,getData(),R.layout.pop_item) {
63 | @Override
64 | public void convert(CommonHolder helper, final String item, final int position) {
65 | helper.setText(R.id.item_tv,position==0?item:item.substring(item.lastIndexOf("/") + 1));
66 | helper.setOnClickListener(R.id.item_tv,new View.OnClickListener() {
67 | @Override
68 | public void onClick(View v) {
69 | if(position == 0){
70 | return;
71 | }
72 | if(gotoUrl == null){
73 | ARouter.getInstance().build(item)
74 | .navigation();
75 | }else{
76 | ARouter.getInstance().build(gotoUrl)//指定跳到那个页面
77 | .withString("targetUrl",item)//传入目标页面路由地址 可以在指定页面跳入到目标页面
78 | .navigation();
79 | }
80 | pop.dismiss();
81 | }
82 | });
83 | }
84 | });
85 | //(注意一下!!)如果不设置popupWindow的背景,无论是点击外部区域还是Back键都无法
86 | pop.setBackgroundDrawable(null);
87 | //点击外部收起
88 | pop.setOutsideTouchable(true);
89 |
90 | pop.showAsDropDown(v);
91 |
92 | }
93 |
94 | private ArrayList getData(){
95 | ArrayList list = new ArrayList<>();
96 | for (Map.Entry entry : ConstantLoginArouter.activityRouterMap.entrySet()) {
97 | if(entry.getValue().contains(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)){
98 | continue;
99 | }
100 | list.add(entry.getValue());
101 | }
102 | list.add(0,"选择目标页面");
103 | return list;
104 | }
105 |
106 | public void modelRequest(View view) {
107 | ARouter.getInstance().build(ConstantArouter.PATH_MODELREQUESTACTIVITY)//指定跳到那个页面
108 | .navigation();
109 | }
110 |
111 | }
112 |
113 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
31 |
32 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/pop_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/pop_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ModularApp
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/senon/modularapp/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.modularapp;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | apply from: "dependencies.gradle"
3 |
4 | buildscript {
5 |
6 | repositories {
7 | google()
8 | jcenter()
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.2.1'
12 |
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | jcenter()
23 | }
24 | }
25 |
26 | task clean(type: Delete) {
27 | delete rootProject.buildDir
28 | }
29 |
--------------------------------------------------------------------------------
/dependencies.gradle:
--------------------------------------------------------------------------------
1 | def supportVersion = "27.1.1"
2 | def rxBindingVersion = "3.0.0-alpha1"
3 | def retrofitVersion = "2.4.0"
4 | def okHttpVersion = "3.11.0"
5 | def butterKnifeVersion = "8.5.1"
6 | def daggerVersion = "2.8"
7 |
8 | project.ext {
9 | android = [
10 | compileSdkVersion: 27,
11 | minSdkVersion : 19,
12 | targetSdkVersion : 27,
13 | versionCode : 1,
14 | versionName : "1.0"
15 | ]
16 |
17 | dependencies = [
18 | //android-support
19 | "support-v4" : "com.android.support:support-v4:${supportVersion}",
20 | "appcompat-v7" : "com.android.support:appcompat-v7:${supportVersion}",
21 | "design" : "com.android.support:design:${supportVersion}",
22 | "recyclerview-v7" : "com.android.support:recyclerview-v7:${supportVersion}",
23 | "cardview-v7" : "com.android.support:cardview-v7:${supportVersion}",
24 | "constraint-layout" : "com.android.support.constraint:constraint-layout:1.1.3",
25 |
26 | //java8-support
27 | "stream" : "com.annimon:stream:1.0.8",
28 |
29 | //rx
30 | "rxjava" : "io.reactivex.rxjava2:rxjava:2.2.3",
31 | "rxandroid" : "io.reactivex.rxjava2:rxandroid:2.1.0",
32 | "rxlifecycle" : "com.trello.rxlifecycle2:rxlifecycle:2.2.1",
33 | "rxlifecycle-components" : "com.trello.rxlifecycle2:rxlifecycle-components:2.2.1",
34 | "rxbinding" : "com.jakewharton.rxbinding3:rxbinding-core:${rxBindingVersion}",
35 | "rxbinding-appcompat-v7" : "com.jakewharton.rxbinding3:rxbinding-appcompat:${rxBindingVersion}",
36 | "rxbinding-recyclerview-v7" : "com.jakewharton.rxbinding3:rxbinding-recyclerview:${rxBindingVersion}",
37 |
38 | //retrofit
39 | "retrofit" : "com.squareup.retrofit2:retrofit:${retrofitVersion}",
40 | "adapter-rxjava" : "com.squareup.retrofit2:adapter-rxjava2:${retrofitVersion}",
41 | "retrofit-converter" : "com.squareup.retrofit2:converter-scalars:${retrofitVersion}",
42 | "retrofit-converter-gson" : "com.squareup.retrofit2:converter-gson:${retrofitVersion}",
43 | "gson" : "com.google.code.gson:gson:2.8.5",
44 |
45 | //dagger
46 | "dagger" : "com.google.dagger:dagger:${daggerVersion}",
47 | "dagger-compiler" : "com.google.dagger:dagger-compiler:${daggerVersion}",
48 |
49 | //router
50 | // 替换成最新版本, 需要注意的是api
51 | // 要与compiler匹配使用,均使用最新版可以保证兼容
52 | "router" : "com.alibaba:arouter-api:1.4.1",
53 | "router-compiler" : "com.alibaba:arouter-compiler:1.2.2",
54 |
55 | //butterKnife 子模块的libary与application转化 R 与R2文件转化(所以最好不用)
56 | //https://www.jianshu.com/p/1fa69ad55b0e
57 | "butterknife" : "com.jakewharton:butterknife:${butterKnifeVersion}",
58 | "butterknife-compiler" : "com.jakewharton:butterknife-compiler:${butterKnifeVersion}",
59 |
60 | //okHttp3
61 | "okhttp3" : "com.squareup.okhttp3:okhttp:${okHttpVersion}",
62 | "okhttp3-logging-interceptor" : "com.squareup.okhttp3:logging-interceptor:${okHttpVersion}",
63 |
64 | //test
65 | "junit" : "junit:junit:4.12",
66 |
67 | //sweet alert dialog
68 | "sweetalert" : "com.github.f0ris.sweetalert:library:1.5.1",
69 |
70 | //autosize
71 | "autosize" : "me.jessyan:autosize:1.0.6",
72 | "glide" : "com.github.bumptech.glide:glide:3.7.0",
73 | "eventbus" : "org.greenrobot:eventbus:3.1.1",
74 |
75 |
76 | ]
77 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/gradle.properties
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jan 03 09:40:54 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/lib_common/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/lib_common/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion rootProject.ext.android["compileSdkVersion"]
5 |
6 | defaultConfig {
7 | minSdkVersion rootProject.ext.android["minSdkVersion"]
8 | targetSdkVersion rootProject.ext.android["targetSdkVersion"]
9 | versionCode rootProject.ext.android["versionCode"]
10 | versionName rootProject.ext.android["versionName"]
11 |
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 |
14 | javaCompileOptions {
15 | annotationProcessorOptions {
16 | arguments = [AROUTER_MODULE_NAME: project.getName()]
17 | }
18 | }
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 |
28 | }
29 |
30 | dependencies {
31 | implementation fileTree(dir: 'libs', include: ['*.jar'])
32 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
33 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
34 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
35 | testImplementation rootProject.ext.dependencies["junit"]
36 |
37 |
38 | api project(':lib_opensource')
39 | annotationProcessor rootProject.ext.dependencies["router-compiler"]
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/lib_common/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/lib_common/src/androidTest/java/com/senon/lib_common/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.senon.lib_common", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib_common/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
12 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/AppConfig.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common;
2 |
3 |
4 | /**
5 | * APP配置参数
6 | */
7 | public class AppConfig {
8 |
9 |
10 | public static final String BASE_URL = "https://www.wanandroid.com/";
11 |
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/ConstantArouter.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common;
2 |
3 | /**
4 | * 所有模块均依赖commonmoduel 所以路由跳转均写入本Constant方便调用
5 | * 常量类
6 | * 其中: 路由跳转命名统一用:path+模块名+Activity名
7 | */
8 | public class ConstantArouter {
9 |
10 | /**
11 | * App 模块
12 | */
13 | public static final String PATH_APP_TESTACTIVITY = "/app/TestActivity";
14 |
15 |
16 | /**
17 | * home 主页
18 | */
19 | public static final String PATH_HOME_MAINACTIVITY = "/home/MainActivity";
20 |
21 |
22 | /**
23 | * life 知识体系
24 | */
25 | public static final String PATH_LIFE_KNOWLEDGESYSTEMACTIVITY = "/life/KnowledgeSystemActivity";
26 |
27 | /**
28 | * common
29 | */
30 | public static final String PATH_COMMON_REGISTERACTIVITY = "/lib_common/CommonRegisterActivity";
31 | public static final String PATH_COMMON_WEBVIEWCTIVITY = "/lib_common/CommonWebviewActivity";
32 | public static final String PATH_MODELREQUESTACTIVITY = "/lib_common/ModelRequestActivity";
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/ConstantLoginArouter.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * 存储各个主模块首页的路由地址:判断是哪个模块登录的
8 | * 当然也可以不用单独从ConstantArouter分离出这些主页地址,看个人喜好
9 | */
10 | public class ConstantLoginArouter {
11 |
12 | public static Map activityRouterMap = new HashMap<>();
13 |
14 | //app主页
15 | public static final String PATH_APP_MAINACTIVITY = "/app/AppMainActivity";
16 |
17 | //one主页
18 | public static final String PATH_ONE_MAINACTIVITY = "/one/OneMainActivity";
19 | //two首页
20 | public static final String PATH_TWO_MAINACTIVITY = "/two/TwoMainActivity";
21 |
22 | //登录 注册
23 | public static final String PATH_COMMON_LOGINACTIVITY = "/lib_common/LoginActivity";
24 |
25 | static {
26 | activityRouterMap.put(getActivityName(PATH_COMMON_LOGINACTIVITY), PATH_COMMON_LOGINACTIVITY);
27 |
28 | activityRouterMap.put(getActivityName(PATH_APP_MAINACTIVITY), PATH_APP_MAINACTIVITY);
29 | activityRouterMap.put(getActivityName(PATH_ONE_MAINACTIVITY), PATH_ONE_MAINACTIVITY);
30 | activityRouterMap.put(getActivityName(PATH_TWO_MAINACTIVITY), PATH_TWO_MAINACTIVITY);
31 | }
32 |
33 | private static String getActivityName(String routerUrl) {
34 | int pos = routerUrl.lastIndexOf("/");
35 | return routerUrl.substring(pos + 1);
36 | }
37 |
38 | public static String getCurRouter(String activityName) {
39 | return activityRouterMap.get(activityName);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/adapter/CommonAdapter.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.adapter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import java.util.List;
9 |
10 | /**
11 | * 做为listview 万能适配器
12 | * @param
13 | */
14 | public abstract class CommonAdapter extends BaseAdapter {
15 | protected LayoutInflater mInflater;
16 | protected Context mContext;
17 | protected List mDatas;
18 | protected final int mItemLayoutId;
19 |
20 | public CommonAdapter(Context context, List mDatas, int itemLayoutId) {
21 | mInflater = LayoutInflater.from(context);
22 | this.mContext = context;
23 | this.mDatas = mDatas;
24 | this.mItemLayoutId = itemLayoutId;
25 | }
26 |
27 | @Override
28 | public int getCount() {
29 | return mDatas.size();
30 | }
31 |
32 | @Override
33 | public T getItem(int position) {
34 | return mDatas.get(position);
35 | }
36 |
37 |
38 | @Override
39 | public long getItemId(int position) {
40 | return position;
41 | }
42 |
43 | @Override
44 | public View getView(int position, View convertView, ViewGroup parent) {
45 | final CommonHolder viewHolder = getViewHolder(position, convertView, parent);
46 | convert(viewHolder, getItem(position),position);
47 | return viewHolder.getConvertView();
48 |
49 | }
50 |
51 | public abstract void convert(CommonHolder helper, T item, int position);
52 |
53 | private CommonHolder getViewHolder(int position, View convertView, ViewGroup parent) {
54 | return CommonHolder.get(mContext, convertView, parent, mItemLayoutId, position);
55 | }
56 | }
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/adapter/RecycleHolder.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.adapter;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Bitmap;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.text.Spannable;
7 | import android.text.SpannableString;
8 | import android.text.SpannableStringBuilder;
9 | import android.text.style.AbsoluteSizeSpan;
10 | import android.text.style.ForegroundColorSpan;
11 | import android.util.SparseArray;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.widget.Checkable;
15 | import android.widget.ImageView;
16 | import android.widget.ProgressBar;
17 | import android.widget.TextView;
18 |
19 | import com.bumptech.glide.Glide;
20 |
21 | /**
22 | * recyclerview 万能适配器的 ViewHolder
23 | */
24 | public class RecycleHolder extends RecyclerView.ViewHolder {
25 |
26 | /**
27 | * 用于存储当前item当中的View
28 | */
29 | private SparseArray mViews;
30 |
31 | public RecycleHolder(View itemView) {
32 | super(itemView);
33 | mViews = new SparseArray();
34 | }
35 |
36 | public T findView(int ViewId) {
37 | View view = mViews.get(ViewId);
38 | //集合中没有,则从item当中获取,并存入集合当中
39 | if (view == null) {
40 | view = itemView.findViewById(ViewId);
41 | mViews.put(ViewId, view);
42 | }
43 | return (T) view;
44 | }
45 |
46 | public RecycleHolder setOnClickListener(int viewId, View.OnClickListener listener) {
47 | View view = findView(viewId);
48 | view.setOnClickListener(listener);
49 | return this;
50 | }
51 |
52 | public RecycleHolder setOnClickListener(int viewId, int viewId2 , View.OnClickListener listener) {
53 | View view = findView(viewId);
54 | view.setOnClickListener(listener);
55 |
56 | View view2 = findView(viewId2);
57 | view2.setOnClickListener(listener);
58 | return this;
59 | }
60 |
61 | public RecycleHolder setOnLongClickListener(int viewId, View.OnLongClickListener listener) {
62 | View view = findView(viewId);
63 | view.setOnLongClickListener(listener);
64 | return this;
65 | }
66 |
67 | public RecycleHolder setOnLongClickListener(int viewId, int viewId2, View.OnLongClickListener listener) {
68 | View view = findView(viewId);
69 | view.setOnLongClickListener(listener);
70 |
71 | View view2 = findView(viewId2);
72 | view2.setOnLongClickListener(listener);
73 | return this;
74 | }
75 |
76 | public RecycleHolder setText(int viewId, String text) {
77 | TextView tv = findView(viewId);
78 | tv.setText(text);
79 | return this;
80 | }
81 |
82 | public RecycleHolder setText(int viewId, SpannableStringBuilder text) {
83 | TextView tv = findView(viewId);
84 | tv.setText(text);
85 | return this;
86 | }
87 |
88 | public RecycleHolder setMaxLine(int viewId, int lineCount) {
89 | TextView tv = findView(viewId);
90 | tv.setMaxLines(lineCount);
91 | return this;
92 | }
93 |
94 | public RecycleHolder setPadding(int viewId, int left, int top, int right, int bottom) {
95 | View tv = findView(viewId);
96 | tv.setPadding(left, top, right, bottom);
97 | return this;
98 | }
99 |
100 | public RecycleHolder setAppendTextColor(int viewId, CharSequence str, int resColorId, int resDimen) {
101 | TextView tv = findView(viewId);
102 | SpannableString spannableString = new SpannableString(str);
103 | spannableString.setSpan(new ForegroundColorSpan(tv.getContext().getResources().getColor(resColorId)), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
104 | spannableString.setSpan(new AbsoluteSizeSpan((int) tv.getContext().getResources().getDimension(resDimen)), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
105 | tv.append(spannableString);
106 | return this;
107 | }
108 |
109 | public RecycleHolder setSelected(int viewId, boolean selected) {
110 | View tv = findView(viewId);
111 | tv.setSelected(selected);
112 | return this;
113 | }
114 |
115 | public RecycleHolder setEnabled(int viewId, boolean enabled) {
116 | View tv = findView(viewId);
117 | tv.setEnabled(enabled);
118 | return this;
119 | }
120 | public RecycleHolder setEnabled_imgView(int viewId, boolean enabled) {
121 | ImageView tv = findView(viewId);
122 | tv.setEnabled(enabled);
123 | return this;
124 | }
125 | public RecycleHolder setText(int viewId, int text) {
126 | TextView tv = findView(viewId);
127 | tv.setText(text);
128 | return this;
129 | }
130 |
131 | public RecycleHolder setChecked(int viewId, boolean checked) {
132 | Checkable view = findView(viewId);
133 | view.setChecked(checked);
134 | return this;
135 | }
136 |
137 | public RecycleHolder setTextColor(int viewId, int colorResId) {
138 | TextView tv = findView(viewId);
139 | tv.setTextColor(tv.getContext().getResources().getColor(colorResId));
140 | return this;
141 | }
142 |
143 | public RecycleHolder setImageResource(int viewId, int ImageId) {
144 | ImageView image = findView(viewId);
145 | image.setImageResource(ImageId);
146 | return this;
147 | }
148 |
149 | public RecycleHolder setLayoutParams(int viewId, ViewGroup.LayoutParams para) {
150 | View view = findView(viewId);
151 | view.setLayoutParams(para);
152 | return this;
153 | }
154 |
155 |
156 | public RecycleHolder setImageBitmap(int viewId, Bitmap bitmap) {
157 | ImageView image = findView(viewId);
158 | image.setImageBitmap(bitmap);
159 | return this;
160 | }
161 |
162 | public RecycleHolder setGlideImage(int viewId, String url, int placehodlerImg, Activity activity){
163 | ImageView image = findView(viewId);
164 | Glide.with(activity)
165 | .load(url)
166 | .error(placehodlerImg)
167 | .placeholder(placehodlerImg)
168 | .into(image);
169 | return this;
170 | }
171 |
172 | public RecycleHolder setImageNet(int viewId, String url) {
173 | ImageView image = findView(viewId);
174 | //使用你所用的网络框架等
175 | return this;
176 | }
177 |
178 | public RecycleHolder setBackgroundColor(int viewId, int color) {
179 | View view = findView(viewId);
180 | view.setBackgroundColor(color);
181 | return this;
182 | }
183 |
184 | public RecycleHolder setBackgroundRes(int viewId, int backgroundRes) {
185 | View view = findView(viewId);
186 | view.setBackgroundResource(backgroundRes);
187 | return this;
188 | }
189 |
190 | public RecycleHolder setVisible(int viewId, boolean visible) {
191 | View image = findView(viewId);
192 | image.setVisibility(visible ? View.VISIBLE : View.GONE);
193 | //使用你所用的网络框架等
194 | return this;
195 | }
196 |
197 | public RecycleHolder setVisible_invisible(int viewId, boolean visible) {
198 | View image = findView(viewId);
199 | image.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
200 | //使用你所用的网络框架等
201 | return this;
202 | }
203 |
204 | public RecycleHolder setProgesss(int viewId, int percent) {
205 | ProgressBar progressBar = findView(viewId);
206 | progressBar.setProgress(percent);
207 | return this;
208 | }
209 |
210 | public boolean getVisible(int viewId) {
211 | View view = findView(viewId);
212 | return view.getVisibility() == View.VISIBLE;
213 | }
214 |
215 |
216 | }
217 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/adapter/RecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * 做为recyclerview 万能适配器
13 | * @param
14 | */
15 | public abstract class RecyclerAdapter extends RecyclerView.Adapter {
16 |
17 | private Context mContext;
18 | private List mDatas;
19 | private int mLayoutId;
20 | private LayoutInflater mInflater;
21 |
22 | private OnItemClickListener onItemClickListener;
23 |
24 | public RecyclerAdapter(Context mContext, List mDatas, int mLayoutId) {
25 | this.mContext = mContext;
26 | this.mDatas = mDatas;
27 | this.mLayoutId = mLayoutId;
28 | mInflater = LayoutInflater.from(mContext);
29 | }
30 |
31 | @Override
32 | public RecycleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
33 | return new RecycleHolder(mInflater.inflate(mLayoutId, parent, false));
34 | }
35 |
36 | @Override
37 | public void onBindViewHolder(final RecycleHolder holder, int position) {
38 | convert(holder, mDatas.get(position), position);
39 | if (onItemClickListener != null) {
40 | //设置背景
41 | holder.itemView.setOnClickListener(new View.OnClickListener() {
42 | @Override
43 | public void onClick(View v) {
44 | //注意,这里的position不要用上面参数中的position,会出现位置错乱\
45 | onItemClickListener.OnItemClickListener(holder.itemView, holder.getLayoutPosition());
46 | }
47 | });
48 | }
49 |
50 | }
51 |
52 | public abstract void convert(RecycleHolder holder, T data, int position);
53 |
54 | @Override
55 | public int getItemCount() {
56 | return mDatas.size();
57 | }
58 |
59 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
60 | this.onItemClickListener = onItemClickListener;
61 | }
62 |
63 | public interface OnItemClickListener {
64 | void OnItemClickListener(View view, int position);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/api/BaseApi.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.api;
2 |
3 | import com.senon.lib_common.base.BaseResponse;
4 | import com.senon.lib_common.bean.Chapter;
5 | import com.senon.lib_common.bean.Login;
6 |
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | import io.reactivex.Observable;
11 | import retrofit2.http.FieldMap;
12 | import retrofit2.http.FormUrlEncoded;
13 | import retrofit2.http.GET;
14 | import retrofit2.http.POST;
15 |
16 | /**
17 | * 网络请求接口
18 | */
19 | public interface BaseApi {
20 |
21 |
22 | //登录
23 | @POST("user/login")
24 | @FormUrlEncoded
25 | Observable> login(@FieldMap Map map);
26 | //登出
27 | @GET("user/logout/json")
28 | Observable logout();
29 | //注册
30 | @POST("user/register")
31 | @FormUrlEncoded
32 | Observable> register(@FieldMap Map map);
33 |
34 | //获取公众号文章
35 | @GET("wxarticle/chapters/json ")
36 | Observable>> getChapters();
37 | }
38 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 | import android.content.pm.ActivityInfo;
4 | import android.os.Bundle;
5 | import android.view.Window;
6 |
7 | import com.alibaba.android.arouter.launcher.ARouter;
8 | import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
9 |
10 | /**
11 | * 父类->基类->动态指定类型->泛型设计(通过泛型指定动态类型->由子类指定,父类只需要规定范围即可)
12 | */
13 | public abstract class BaseActivity> extends RxAppCompatActivity {
14 |
15 | //引用V层和P层
16 | private P presenter;
17 | private V view;
18 |
19 | public P getPresenter(){
20 | return presenter;
21 | }
22 |
23 | @Override
24 | protected void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | requestWindowFeature(Window.FEATURE_NO_TITLE);
27 | setContentView(getLayoutId());
28 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); // 禁止所有的activity横屏
29 | ARouter.getInstance().inject(this);
30 | if(presenter == null){
31 | presenter = createPresenter();
32 | }
33 | if(view == null){
34 | view = createView();
35 | }
36 | if(presenter != null && view != null){
37 | presenter.attachView(view);
38 | }
39 | init();
40 | }
41 |
42 | //由子类指定具体类型
43 | public abstract int getLayoutId();
44 | public abstract P createPresenter();
45 | public abstract V createView();
46 | public abstract void init();
47 |
48 | @Override
49 | protected void onDestroy() {
50 | super.onDestroy();
51 | if(presenter != null){
52 | presenter.detachView();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseAppDeletage.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 | import android.app.Application;
4 | import com.senon.lib_common.utils.ConstantUtils;
5 | import com.senon.lib_common.utils.LogUtils;
6 | import com.senon.lib_common.utils.PreferenceTool;
7 | import com.senon.lib_common.utils.ToastUtil;
8 | import me.jessyan.autosize.AutoSizeConfig;
9 | import me.jessyan.autosize.unit.Subunits;
10 |
11 | /**
12 | *
13 | */
14 | public class BaseAppDeletage {
15 |
16 | private Application mApplication;
17 |
18 | public BaseAppDeletage(Application application) {
19 | mApplication = application;
20 | }
21 |
22 | public void onCreate() {
23 | ConstantUtils.init(mApplication); //全局Utils
24 | initLog(); //Log日志
25 | PreferenceTool.init(mApplication); //Preference参数
26 | ToastUtil.init(mApplication); //吐司初始化
27 | initAutoSizeUnits(); //配置全局 布局适配单位mm
28 | }
29 |
30 | private void initLog() {
31 | LogUtils.setLogEnable(ConstantUtils.isAppDebug());
32 | }
33 |
34 | private void initAutoSizeUnits() {
35 | AutoSizeConfig.getInstance().getUnitsManager()
36 | //支持dp适配 默认true
37 | .setSupportDP(true)
38 | //支持sp适配 默认true
39 | .setSupportSP(true)
40 | // .setSupportSubunits(Subunits.MM)
41 | ;
42 | AutoSizeConfig.getInstance()
43 | //按照宽度适配 默认true
44 | .setBaseOnWidth(true)
45 | //是否让框架支持自定义 Fragment 的适配参数, 由于这个需求是比较少见的, 所以须要使用者手动开启
46 | //如果没有这个需求建议不开启
47 | .setCustomFragment(true);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseApplication.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 | import android.app.Application;
4 |
5 | /**
6 | * 要想使用BaseApplication,必须在组件中实现自己的Application,并且继承BaseApplication;
7 | * 组件模块中实现的Application必须在debug包中的AndroidManifest.xml中注册,否则无法使用;
8 | * 组件模块的Application需置于java/debug文件夹中,不得放于主代码;
9 | * 组件模块中获取Context的方法必须为:Util.getAPPContext(),不允许其他写法;
10 | */
11 | public class BaseApplication extends Application {
12 |
13 | @Override
14 | public void onCreate() {
15 | super.onCreate();
16 | BaseAppDeletage baseAppDeletage = new BaseAppDeletage(this);
17 | baseAppDeletage.onCreate();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseEvent.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 | /**
4 | * 自定义eventbus发送实体
5 | */
6 | public class BaseEvent {
7 |
8 | /**
9 | * -1:退出登录时通知Mainactivity finish
10 | * 0:登录成功 刷新所有主界面数据列表
11 | * 1:退出成功 。。。
12 | *
13 | *
14 | *
15 | *
16 | *
17 | *
18 | */
19 | private int code;
20 | private String msg;
21 | private T data;
22 | private boolean isCollect;
23 | private int id;
24 | private boolean ingored;
25 |
26 |
27 | public int getCode() {
28 | return code;
29 | }
30 |
31 | public void setCode(int code) {
32 | this.code = code;
33 | }
34 |
35 | public String getMsg() {
36 | return msg;
37 | }
38 |
39 | public void setMsg(String msg) {
40 | this.msg = msg;
41 | }
42 |
43 | public T getData() {
44 | return data;
45 | }
46 |
47 | public void setData(T data) {
48 | this.data = data;
49 | }
50 |
51 | public boolean isCollect() {
52 | return isCollect;
53 | }
54 |
55 | public void setCollect(boolean collect) {
56 | isCollect = collect;
57 | }
58 |
59 | public int getId() {
60 | return id;
61 | }
62 |
63 | public void setId(int id) {
64 | this.id = id;
65 | }
66 |
67 | public boolean isIngored() {
68 | return ingored;
69 | }
70 |
71 | public void setIngored(boolean ingored) {
72 | this.ingored = ingored;
73 | }
74 |
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.trello.rxlifecycle2.components.support.RxFragment;
10 |
11 | /**
12 | * 父类->基类->动态指定类型->泛型设计(通过泛型指定动态类型->由子类指定,父类只需要规定范围即可)
13 | */
14 | public abstract class BaseFragment> extends RxFragment {
15 |
16 | //引用V层和P层
17 | private P presenter;
18 | private V view;
19 | public Context mContext;
20 |
21 | public P getPresenter() {
22 | return presenter;
23 | }
24 |
25 | @Override
26 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
27 | View view = inflater.inflate(getLayoutId(), container, false);
28 | mContext = getActivity();
29 | if (presenter == null) {
30 | presenter = createPresenter();
31 | }
32 | if (this.view == null) {
33 | this.view = createView();
34 | }
35 | if (presenter != null && view != null) {
36 | presenter.attachView(this.view);
37 | }
38 | init();
39 | return view;
40 | }
41 |
42 | //由子类指定具体类型
43 | public abstract int getLayoutId();
44 | public abstract P createPresenter();
45 | public abstract V createView();
46 | public abstract void init();
47 |
48 | @Override
49 | public void onDestroyView() {
50 | super.onDestroyView();
51 | if (presenter != null) {
52 | presenter.detachView();
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseLazyFragment.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.senon.lib_common.utils.LogUtils;
11 | import com.trello.rxlifecycle2.components.support.RxFragment;
12 |
13 | /**
14 | * https://juejin.im/post/5adcb0e36fb9a07aa7673fbc
15 | * BaseLazyFragment 单fragment懒加载
16 | *
17 | * * 生命周期执行的方法 如下:
18 | * 第一次生成页面-->可见
19 | * setUserVisibleHint: ----->false
20 | * setUserVisibleHint: ----->true
21 | * onCreateView: -----> onCreateView
22 | * onStart: -----> onStart
23 | * onFragmentFirst: 首次可见
24 | * onFragmentFirst: -----> 子fragment进行初始化操作
25 | * onResume: -----> onResume
26 | *
27 | * 可见-->第一次隐藏:
28 | * onPause: -----> onPause
29 | * onFragmentInVisible: 不可见
30 | *
31 | * 未销毁且不可见-->重新可见:
32 | * onStart: -----> onStart
33 | * onFragmentVisble: 可见
34 | * onFragmentVisble: -----> 子fragment每次可见时的操作
35 | * onResume: -----> onResume
36 | *
37 | * 可见-->销毁:
38 | * onPause: -----> onPause
39 | * onFragmentInVisible: 不可见
40 | * onDestroyView: -----> onDestroyView
41 | *
42 | * 我们可以更具以上生命周期来操作不同的业务逻辑,
43 | * 请务必运行此module demo,观看打印日志来自定义逻辑。
44 | */
45 | public abstract class BaseLazyFragment> extends RxFragment {
46 | //引用V层和P层
47 | private P presenter;
48 | private V view;
49 | public Context mContext;
50 |
51 | private View rootView;
52 | private boolean mIsFirstVisible = true;/*当前Fragment是否首次可见,默认是首次可见**/
53 | private boolean isViewCreated = false;/*当前Fragment的View是否已经创建**/
54 | private boolean currentVisibleState = false;/*当前Fragment的可见状态,一种当前可见,一种当前不可见**/
55 |
56 | public P getPresenter() {
57 | return presenter;
58 | }
59 |
60 | @Nullable
61 | @Override
62 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
63 | LogUtils.e("-----> onCreateView");
64 | if(rootView == null){
65 | rootView = inflater.inflate(getLayoutId(), container, false);
66 | mContext = getActivity();
67 | if (presenter == null) {
68 | presenter = createPresenter();
69 | }
70 | if (this.view == null) {
71 | this.view = createView();
72 | }
73 | if (presenter != null && view != null) {
74 | presenter.attachView(this.view);
75 | }
76 | init(rootView);
77 | }
78 | isViewCreated=true;//在onCreateView执行完毕,将isViewCreated改为true;
79 | return rootView;
80 | }
81 |
82 | //由子类指定具体类型
83 | public abstract int getLayoutId();
84 | public abstract P createPresenter();
85 | public abstract V createView();
86 | public abstract void init(View rootView);
87 |
88 | @Override
89 | public void setUserVisibleHint(boolean isVisibleToUser) {
90 | super.setUserVisibleHint(isVisibleToUser);
91 | LogUtils.e("----->"+isVisibleToUser);
92 | if (isViewCreated) {
93 | //Fragment可见且状态不是可见(从一个Fragment切换到另外一个Fragment,后一个设置状态为可见)
94 | if (isVisibleToUser && !currentVisibleState) {
95 | disPatchFragment(true);
96 | } else if (!isVisibleToUser && currentVisibleState) {
97 | //Fragment不可见且状态是可见(从一个Fragment切换到另外一个Fragment,前一个更改状态为不可见)
98 | disPatchFragment(false);
99 | }
100 | }
101 | }
102 |
103 | @Override
104 | public void onStart() {
105 | super.onStart();
106 | LogUtils.e("-----> onStart");
107 | //isHidden()是Fragment是否处于隐藏状态和isVisible()有区别
108 | //getUserVisibleHint(),Fragement是否可见
109 | if(!isHidden()&& getUserVisibleHint()){//如果Fragment没有隐藏且可见
110 | //执行分发的方法,三种结果对应自Fragment的三个回调,对应的操作,Fragment首次加载,可见,不可见
111 | disPatchFragment(true);
112 | }
113 | }
114 |
115 | @Override
116 | public void onResume() {
117 | super.onResume();
118 | LogUtils.e("-----> onResume");
119 | if(!mIsFirstVisible){
120 | //表示点击home键又返回操作,设置可见状态为ture
121 | if(!isHidden()&& !getUserVisibleHint() && currentVisibleState){
122 | disPatchFragment(true);
123 | }
124 | }
125 | }
126 |
127 | @Override
128 | public void onPause() {
129 | super.onPause();
130 | LogUtils.e("-----> onPause");
131 | //表示点击home键,原来可见的Fragment要走该方法,更改Fragment的状态为不可见
132 | if(!isHidden()&& getUserVisibleHint()){
133 | disPatchFragment(false);
134 | }
135 | }
136 |
137 | @Override
138 | public void onDestroyView() {
139 | super.onDestroyView();
140 | LogUtils.e("-----> onDestroyView");
141 | //当 View 被销毁的时候我们需要重新设置 isViewCreated mIsFirstVisible 的状态
142 | isViewCreated = false;
143 | mIsFirstVisible = true;
144 |
145 | if (presenter != null) {
146 | presenter.detachView();
147 | }
148 | }
149 |
150 |
151 | /**
152 | * @param visible Fragment当前是否可见,然后调用相关方法
153 | */
154 | public void disPatchFragment(boolean visible){
155 | currentVisibleState=visible;
156 | if(visible){//Fragment可见
157 | if(mIsFirstVisible){//可见又是第一次
158 | mIsFirstVisible=false;//改变首次可见的状态
159 | onFragmentFirst();
160 | }else{//可见但不是第一次
161 | onFragmentVisble();
162 | }
163 | }else {//不可见
164 | onFragmentInVisible();
165 | }
166 | }
167 |
168 | //Fragemnet首次可见的方法
169 | public void onFragmentFirst(){
170 | LogUtils.e("首次可见");
171 | }
172 | //Fragemnet可见的方法
173 | public void onFragmentVisble(){//子Fragment调用次方法,执行可见操作
174 | LogUtils.e("可见");
175 | }
176 | //Fragemnet不可见的方法
177 | public void onFragmentInVisible(){
178 | LogUtils.e("不可见");
179 | }
180 |
181 | }
182 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseModelCallBack.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 |
4 | public interface BaseModelCallBack {
5 |
6 | void onNext(T t);
7 |
8 | void onError(Throwable e);
9 |
10 | //数据库读取进度
11 | // void onProgress(int total,int current,float progress);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseNestingLazyFragment.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v4.app.FragmentManager;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import com.senon.lib_common.utils.LogUtils;
14 | import com.trello.rxlifecycle2.components.support.RxFragment;
15 |
16 | import java.util.List;
17 |
18 | /**
19 | * https://juejin.im/post/5adcb0e36fb9a07aa7673fbc
20 | *
21 | * BaseNestingLazyFragment fragment嵌套fragment的懒加载父类
22 | */
23 | public abstract class BaseNestingLazyFragment> extends RxFragment {
24 | //引用V层和P层
25 | private P presenter;
26 | private V view;
27 | public Context mContext;
28 |
29 | private View rootView;
30 | private boolean mIsFirstVisible = true;/*当前Fragment是否首次可见,默认是首次可见**/
31 | private boolean isViewCreated = false;/*当前Fragment的View是否已经创建**/
32 | private boolean currentVisibleState = false;/*当前Fragment的可见状态,一种当前可见,一种当前不可见**/
33 |
34 | public P getPresenter() {
35 | return presenter;
36 | }
37 |
38 | @Nullable
39 | @Override
40 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
41 | LogUtils.e("-----> onCreateView");
42 | if (rootView == null) {
43 | rootView = inflater.inflate(getLayoutId(), container, false);
44 | mContext = getActivity();
45 | if (presenter == null) {
46 | presenter = createPresenter();
47 | }
48 | if (this.view == null) {
49 | this.view = createView();
50 | }
51 | if (presenter != null && view != null) {
52 | presenter.attachView(this.view);
53 | }
54 | init(rootView);
55 | }
56 | isViewCreated = true;//在onCreateView执行完毕,将isViewCreated改为true;
57 | return rootView;
58 | }
59 |
60 | //由子类指定具体类型
61 | public abstract int getLayoutId();
62 |
63 | public abstract P createPresenter();
64 |
65 | public abstract V createView();
66 |
67 | public abstract void init(View rootView);
68 |
69 | @Override
70 | public void setUserVisibleHint(boolean isVisibleToUser) {
71 | super.setUserVisibleHint(isVisibleToUser);
72 | LogUtils.e("----->" + isVisibleToUser);
73 | if (isViewCreated) {
74 | //Fragment可见且状态不是可见(从一个Fragment切换到另外一个Fragment,后一个设置状态为可见)
75 | if (isVisibleToUser && !currentVisibleState) {
76 | disPatchFragment(true);
77 | } else if (!isVisibleToUser && currentVisibleState) {
78 | //Fragment不可见且状态是可见(从一个Fragment切换到另外一个Fragment,前一个更改状态为不可见)
79 | disPatchFragment(false);
80 | }
81 | }
82 | }
83 |
84 | @Override
85 | public void onStart() {
86 | super.onStart();
87 | LogUtils.e("-----> onStart");
88 | //isHidden()是Fragment是否处于隐藏状态和isVisible()有区别
89 | //getUserVisibleHint(),Fragement是否可见
90 | if (!isHidden() && getUserVisibleHint()) {//如果Fragment没有隐藏且可见
91 | //执行分发的方法,三种结果对应自Fragment的三个回调,对应的操作,Fragment首次加载,可见,不可见
92 | disPatchFragment(true);
93 | }
94 |
95 | }
96 |
97 | @Override
98 | public void onResume() {
99 | super.onResume();
100 | LogUtils.e("-----> onResume");
101 | if (!mIsFirstVisible) {
102 | //表示点击home键又返回操作,设置可见状态为ture
103 | if (!isHidden() && !getUserVisibleHint() && currentVisibleState) {
104 | disPatchFragment(true);
105 | }
106 | }
107 | }
108 |
109 | @Override
110 | public void onPause() {
111 | super.onPause();
112 | LogUtils.e("-----> onPause");
113 | //表示点击home键,原来可见的Fragment要走该方法,更改Fragment的状态为不可见
114 | if (!isHidden() && getUserVisibleHint()) {
115 | disPatchFragment(false);
116 | }
117 | }
118 |
119 | @Override
120 | public void onDestroyView() {
121 | super.onDestroyView();
122 | LogUtils.e("-----> onDestroyView");
123 | //当 View 被销毁的时候我们需要重新设置 isViewCreated mIsFirstVisible 的状态
124 | isViewCreated = false;
125 | mIsFirstVisible = true;
126 |
127 | if (presenter != null) {
128 | presenter.detachView();
129 | }
130 |
131 | }
132 |
133 |
134 | /**
135 | * @param visible Fragment当前是否可见,然后调用相关方法
136 | */
137 | public void disPatchFragment(boolean visible) {
138 | String aa = getClass().getSimpleName();
139 | //如果父Fragment不可见,则不向下分发给子Fragment
140 | if (visible && isParentFragmentVsible()) return;
141 |
142 | // 如果当前的 Fragment 要分发的状态与 currentVisibleState 相同(都为false)我们就没有必要去做分发了。
143 | if (currentVisibleState == visible) return;
144 |
145 | currentVisibleState = visible;
146 | if (visible) {//Fragment可见
147 | if (mIsFirstVisible) {//可见又是第一次
148 | mIsFirstVisible = false;//改变首次可见的状态
149 | onFragmentFirst();
150 | }//可见但不是第一次
151 | onFragmentVisble();
152 | //可见状态的时候内层 fragment 生命周期晚于外层 所以在 onFragmentResume 后分发
153 | dispatchChildFragmentVisibleState(true);
154 | } else {//不可见
155 | onFragmentInVisible();
156 | dispatchChildFragmentVisibleState(false);
157 | }
158 | }
159 |
160 |
161 | /**
162 | * 重新分发给子Fragment
163 | *
164 | * @param visible
165 | */
166 | private void dispatchChildFragmentVisibleState(boolean visible) {
167 | FragmentManager childFragmentManager = getChildFragmentManager();
168 | @SuppressLint("RestrictedApi") List fragments = childFragmentManager.getFragments();
169 | if (fragments != null) {
170 | if (!fragments.isEmpty()) {
171 | for (Fragment child : fragments) {
172 | if (child instanceof BaseNestingLazyFragment && !child.isHidden() && child.getUserVisibleHint()) {
173 | ((BaseNestingLazyFragment) child).disPatchFragment(visible);
174 | }
175 | }
176 | }
177 | }
178 |
179 | }
180 |
181 | //Fragemnet首次可见的方法
182 | public void onFragmentFirst() {
183 | LogUtils.e("首次可见");
184 | }
185 | //Fragemnet可见的方法
186 | public void onFragmentVisble() {//子Fragment调用次方法,执行可见操作
187 | LogUtils.e("可见");
188 | }
189 | //Fragemnet不可见的方法
190 | public void onFragmentInVisible() {
191 | LogUtils.e("不可见");
192 | }
193 |
194 | /**
195 | * 判断多层嵌套的父Fragment是否显示
196 | */
197 | private boolean isParentFragmentVsible() {
198 | BaseNestingLazyFragment fragment = (BaseNestingLazyFragment) getParentFragment();
199 | return fragment != null && !fragment.getCurrentVisibleState();
200 | }
201 |
202 | private boolean getCurrentVisibleState() {
203 | return currentVisibleState;
204 | }
205 |
206 | }
207 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BasePresenter.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 |
4 | /**
5 | * BasePresenter
6 | */
7 | public abstract class BasePresenter{
8 |
9 | private V mView;
10 |
11 | public V getView(){
12 | return mView;
13 | }
14 |
15 | public void attachView(V v){
16 | mView = v;
17 | }
18 |
19 | public void detachView(){
20 | mView = null;
21 | }
22 |
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseResponse.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | /**
6 | * BaseResponse
7 | */
8 | public class BaseResponse {
9 |
10 | @SerializedName("errorMsg")
11 | private String msg;
12 | @SerializedName("errorCode")
13 | private int code;
14 | private T data;
15 |
16 |
17 |
18 | public String getMsg() {
19 | return msg;
20 | }
21 |
22 | public int getCode() {
23 | return code;
24 | }
25 |
26 | public T getData() {
27 | return data;
28 | }
29 |
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/base/BaseViewImp.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.base;
2 |
3 | /**
4 | * View 父类接口
5 | */
6 | public interface BaseViewImp {
7 | }
8 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/bean/Chapter.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.bean;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * 公众号实体
7 | */
8 | public class Chapter {
9 |
10 | /**
11 | * children : []
12 | * courseId : 13
13 | * id : 434
14 | * name : Android达摩院
15 | * order : 190013
16 | * parentChapterId : 407
17 | * userControlSetTop : false
18 | * visible : 1
19 | */
20 |
21 | private int courseId;
22 | private int id;
23 | private String name;
24 | private int order;
25 | private int parentChapterId;
26 | private boolean userControlSetTop;
27 | private int visible;
28 | private List> children;
29 |
30 | public int getCourseId() {
31 | return courseId;
32 | }
33 |
34 | public void setCourseId(int courseId) {
35 | this.courseId = courseId;
36 | }
37 |
38 | public int getId() {
39 | return id;
40 | }
41 |
42 | public void setId(int id) {
43 | this.id = id;
44 | }
45 |
46 | public String getName() {
47 | return name;
48 | }
49 |
50 | public void setName(String name) {
51 | this.name = name;
52 | }
53 |
54 | public int getOrder() {
55 | return order;
56 | }
57 |
58 | public void setOrder(int order) {
59 | this.order = order;
60 | }
61 |
62 | public int getParentChapterId() {
63 | return parentChapterId;
64 | }
65 |
66 | public void setParentChapterId(int parentChapterId) {
67 | this.parentChapterId = parentChapterId;
68 | }
69 |
70 | public boolean isUserControlSetTop() {
71 | return userControlSetTop;
72 | }
73 |
74 | public void setUserControlSetTop(boolean userControlSetTop) {
75 | this.userControlSetTop = userControlSetTop;
76 | }
77 |
78 | public int getVisible() {
79 | return visible;
80 | }
81 |
82 | public void setVisible(int visible) {
83 | this.visible = visible;
84 | }
85 |
86 | public List> getChildren() {
87 | return children;
88 | }
89 |
90 | public void setChildren(List> children) {
91 | this.children = children;
92 | }
93 |
94 | @Override
95 | public String toString() {
96 | return "Chapter{" +
97 | "courseId=" + courseId +
98 | ", id=" + id +
99 | ", name='" + name + '\'' +
100 | ", order=" + order +
101 | ", parentChapterId=" + parentChapterId +
102 | ", userControlSetTop=" + userControlSetTop +
103 | ", visible=" + visible +
104 | ", children=" + children +
105 | '}';
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/bean/Login.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.bean;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * 登录--实体
7 | */
8 | public class Login {
9 |
10 | /**
11 | * chapterTops : []
12 | * collectIds : [2683,2880,2875,2868,2831,2829,2807]
13 | * email :
14 | * icon :
15 | * id : 1864
16 | * password :
17 | * token :
18 | * type : 0
19 | * username : senonwx
20 | */
21 |
22 | public String email;
23 | public String icon;
24 | public int id;
25 | public String password;
26 | public String token;
27 | public int type;
28 | public String username;
29 | public List> chapterTops;
30 | public List collectIds;
31 |
32 | public Login() {
33 | }
34 |
35 | @Override
36 | public String toString() {
37 | return "Login{" +
38 | "email='" + email + '\'' +
39 | ", icon='" + icon + '\'' +
40 | ", id=" + id +
41 | ", password='" + password + '\'' +
42 | ", token='" + token + '\'' +
43 | ", type=" + type +
44 | ", username='" + username + '\'' +
45 | ", chapterTops=" + chapterTops +
46 | ", collectIds=" + collectIds +
47 | '}';
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/common/contract/LoginContract.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.common.contract;
2 |
3 |
4 | import com.senon.lib_common.base.BasePresenter;
5 | import com.senon.lib_common.base.BaseResponse;
6 | import com.senon.lib_common.base.BaseViewImp;
7 | import com.senon.lib_common.bean.Login;
8 |
9 | import java.util.HashMap;
10 |
11 | /**
12 | * LoginContract
13 | */
14 | public interface LoginContract {
15 |
16 | //方法命名以 请求方法+Result 命名
17 | interface View extends BaseViewImp {
18 |
19 | void getLoginResult(BaseResponse data);
20 |
21 | void getRegisterResult(BaseResponse data);
22 |
23 | }
24 |
25 | //方法命名以 get+方法 命名
26 | abstract class Presenter extends BasePresenter {
27 |
28 | public abstract void getLogin(HashMap map, boolean isDialog, boolean cancelable);
29 |
30 | public abstract void getRegister(HashMap map, boolean isDialog, boolean cancelable);
31 |
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/common/contract/ModelRequestContract.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.common.contract;
2 |
3 | import android.content.Context;
4 | import com.senon.lib_common.base.BasePresenter;
5 | import com.senon.lib_common.base.BaseResponse;
6 | import com.senon.lib_common.base.BaseViewImp;
7 | import com.senon.lib_common.bean.Chapter;
8 | import com.senon.lib_common.bean.Login;
9 | import com.senon.lib_common.base.BaseModelCallBack;
10 | import com.trello.rxlifecycle2.LifecycleTransformer;
11 |
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | /**
16 | * 统一管理 v p m接口
17 | */
18 | public interface ModelRequestContract {
19 |
20 | /**
21 | * View
22 | */
23 | interface View extends BaseViewImp {
24 |
25 | void getDataResult(BaseResponse> data);
26 |
27 | }
28 |
29 | /**
30 | * Presenter
31 | */
32 | abstract class Presenter extends BasePresenter {
33 |
34 | public abstract void getData(boolean isDialog, boolean cancelable);
35 |
36 | }
37 |
38 | /**
39 | * Model
40 | */
41 | interface Model{
42 | void getData(LifecycleTransformer>> transformer, Context context,
43 | boolean isDialog, boolean cancelable, BaseModelCallBack callBack);
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/common/model/ModelRequestMod.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.common.model;
2 |
3 | import android.content.Context;
4 | import com.senon.lib_common.base.BaseResponse;
5 | import com.senon.lib_common.bean.Chapter;
6 | import com.senon.lib_common.bean.Login;
7 | import com.senon.lib_common.common.contract.ModelRequestContract;
8 | import com.senon.lib_common.base.BaseModelCallBack;
9 | import com.senon.lib_common.net.ServerUtils;
10 | import com.senon.lib_common.net.callback.RequestCallback;
11 | import com.senon.lib_common.net.callback.RxErrorHandler;
12 | import com.senon.lib_common.utils.RetryWithDelay;
13 | import com.senon.lib_common.utils.RxUtils;
14 | import com.trello.rxlifecycle2.LifecycleTransformer;
15 |
16 | import java.util.List;
17 | import java.util.Map;
18 |
19 | /**
20 | * model层
21 | */
22 | public class ModelRequestMod implements ModelRequestContract.Model {
23 |
24 | @Override
25 | public void getData(LifecycleTransformer>> transformer, Context context,
26 | boolean isDialog, boolean cancelable, final BaseModelCallBack callBack){
27 | ServerUtils.getCommonApi().getChapters()
28 | .compose(transformer)
29 | .compose(RxUtils.>>getSchedulerTransformer())
30 | .subscribe(new RequestCallback>>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
31 | @Override
32 | public void onNext(BaseResponse> response) {
33 | super.onNext(response);
34 | callBack.onNext(response);
35 | }
36 | @Override
37 | public void onError(Throwable e) {
38 | super.onError(e);
39 | callBack.onError(e);
40 | }
41 | });
42 | }
43 |
44 |
45 | //数据库读取等操作
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/common/presenter/LoginPresenter.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.common.presenter;
2 |
3 | import android.content.Context;
4 |
5 | import com.senon.lib_common.base.BaseResponse;
6 | import com.senon.lib_common.bean.Login;
7 | import com.senon.lib_common.common.contract.LoginContract;
8 | import com.senon.lib_common.net.ServerUtils;
9 | import com.senon.lib_common.net.callback.RequestCallback;
10 | import com.senon.lib_common.net.callback.RxErrorHandler;
11 | import com.senon.lib_common.utils.RetryWithDelay;
12 | import com.senon.lib_common.utils.RxUtils;
13 | import com.senon.lib_common.utils.ToastUtil;
14 |
15 | import java.util.HashMap;
16 |
17 | /**
18 | * 登录 P
19 | */
20 | public class LoginPresenter extends LoginContract.Presenter {
21 |
22 | private Context context;
23 |
24 | public LoginPresenter(Context context) {
25 | this.context = context;
26 | }
27 |
28 | @Override
29 | public void getLogin(HashMap map, boolean isDialog, boolean cancelable) {
30 | ServerUtils.getCommonApi().login(map)
31 | .retryWhen(new RetryWithDelay(3,2))
32 | .compose(RxUtils.>bindToLifecycle(getView()))
33 | .compose(RxUtils.>getSchedulerTransformer())
34 | .subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
35 | @Override
36 | public void onNext(BaseResponse baseResponse) {
37 | super.onNext(baseResponse);
38 | if(baseResponse.getCode() == 0){
39 | getView().getLoginResult(baseResponse);
40 | }else{
41 | ToastUtil.initToast(baseResponse.getMsg());
42 | }
43 | }
44 | @Override
45 | public void onError(Throwable e) {
46 | super.onError(e);
47 | }
48 | });
49 | }
50 |
51 | @Override
52 | public void getRegister(HashMap map, boolean isDialog, boolean cancelable) {
53 | ServerUtils.getCommonApi().register(map)
54 | .retryWhen(new RetryWithDelay(3,2))
55 | .compose(RxUtils.>bindToLifecycle(getView()))
56 | .compose(RxUtils.>getSchedulerTransformer())
57 | .subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
58 | @Override
59 | public void onNext(BaseResponse baseResponse) {
60 | super.onNext(baseResponse);
61 | if(baseResponse.getCode() == 0){
62 | getView().getRegisterResult(baseResponse);
63 | }else{
64 | ToastUtil.initToast(baseResponse.getMsg());
65 | }
66 | }
67 | @Override
68 | public void onError(Throwable e) {
69 | super.onError(e);
70 | }
71 | });
72 | }
73 |
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/common/presenter/ModelRequestPresenter.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.common.presenter;
2 |
3 | import android.content.Context;
4 |
5 | import com.senon.lib_common.base.BaseResponse;
6 | import com.senon.lib_common.bean.Chapter;
7 | import com.senon.lib_common.bean.Login;
8 | import com.senon.lib_common.common.contract.ModelRequestContract;
9 | import com.senon.lib_common.common.model.ModelRequestMod;
10 | import com.senon.lib_common.base.BaseModelCallBack;
11 | import com.senon.lib_common.utils.RxUtils;
12 | import com.senon.lib_common.utils.ToastUtil;
13 |
14 | import java.util.HashMap;
15 | import java.util.List;
16 |
17 | /**
18 | * 结合model使用的 p层
19 | */
20 | public class ModelRequestPresenter extends ModelRequestContract.Presenter {
21 |
22 | private Context context;
23 | private ModelRequestMod model;
24 |
25 | public ModelRequestPresenter(Context context) {
26 | this.context = context;
27 | this.model = new ModelRequestMod();
28 | }
29 |
30 |
31 | @Override
32 | public void getData(boolean isDialog, boolean cancelable) {
33 | /**
34 | * 为什么rx绑定生命周期不放在model层,
35 | * 因为我们不希望m层拥有直接操作v层的权利 隔离v与m层
36 | * 只希望m层与p层交互
37 | */
38 | model.getData(RxUtils.>>bindToLifecycle(getView()), context, isDialog, cancelable,
39 | new BaseModelCallBack() {
40 | @Override
41 | public void onNext(Object o) {
42 | getView().getDataResult((BaseResponse>) o);
43 | }
44 |
45 | @Override
46 | public void onError(Throwable e) {
47 | ToastUtil.initToast(e.getMessage());
48 | }
49 | });
50 | }
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/common/ui/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.common.ui;
2 |
3 | import android.graphics.Paint;
4 | import android.view.View;
5 | import android.widget.EditText;
6 | import android.widget.TextView;
7 | import com.alibaba.android.arouter.facade.annotation.Autowired;
8 | import com.alibaba.android.arouter.facade.annotation.Route;
9 | import com.alibaba.android.arouter.launcher.ARouter;
10 | import com.senon.lib_common.utils.ComUtil;
11 | import com.senon.lib_common.ConstantArouter;
12 | import com.senon.lib_common.ConstantLoginArouter;
13 | import com.senon.lib_common.R;
14 | import com.senon.lib_common.base.BaseActivity;
15 | import com.senon.lib_common.base.BaseResponse;
16 | import com.senon.lib_common.bean.Login;
17 | import com.senon.lib_common.common.contract.LoginContract;
18 | import com.senon.lib_common.common.presenter.LoginPresenter;
19 | import com.senon.lib_common.utils.StatusBarUtils;
20 | import com.senon.lib_common.utils.ToastUtil;
21 |
22 | /**
23 | * 所有模块统一登录页面
24 | */
25 | @Route(path = ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)
26 | public class LoginActivity extends BaseActivity implements
27 | LoginContract.View {
28 |
29 | @Autowired
30 | String targetUrl;
31 | private EditText account_edt,password_edt;
32 | private TextView register_tv;
33 | //这是branch1中修改的
34 |
35 |
36 | @Override
37 | public int getLayoutId() {
38 | StatusBarUtils.with(this).init();
39 | return R.layout.common_activity_login;
40 | }
41 |
42 | @Override
43 | public LoginContract.Presenter createPresenter() {
44 | return new LoginPresenter(this);
45 | }
46 |
47 | @Override
48 | public LoginContract.View createView() {
49 | return this;
50 | }
51 |
52 | @Override
53 | public void init() {
54 | ComUtil.changeStatusBarTextColor(this,true);
55 |
56 | account_edt = findViewById(R.id.account_edt);
57 | password_edt = findViewById(R.id.password_edt);
58 | register_tv = findViewById(R.id.register_tv);
59 |
60 | account_edt.setSelection(account_edt.getText().toString().length());
61 | register_tv.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);
62 |
63 | }
64 |
65 | @Override
66 | public void getLoginResult(BaseResponse data) {
67 | //登录成功时
68 | //保存参数...
69 |
70 | if(targetUrl != null){
71 | //跳转到目标页
72 | ARouter.getInstance()
73 | .build(targetUrl)
74 | .withObject("data",data.getData())
75 | .navigation();
76 | }
77 |
78 | finish();
79 | }
80 |
81 | @Override
82 | public void getRegisterResult(BaseResponse data) {
83 | }
84 |
85 | public void onClick(View view) {
86 | int id = view.getId();
87 | if(id == R.id.login_btn){
88 | String account = account_edt.getText().toString();
89 | String password = password_edt.getText().toString();
90 | if (account.isEmpty()) {
91 | ToastUtil.initToast("请输入账号");
92 | return;
93 | }
94 | if (password.isEmpty()) {
95 | ToastUtil.initToast("请输入密码");
96 | return;
97 | }
98 | getPresenter().getLogin(ComUtil.getMd5Str(
99 | new String[]{"username", "password"},
100 | new String[]{account.trim(), password.trim()})
101 | , true, true);
102 | }else if(id == R.id.register_tv){
103 | //跳转到注册页 统一用arouter跳转,便于以后移动模块的改动
104 | ARouter.getInstance().build(ConstantArouter.PATH_COMMON_REGISTERACTIVITY)
105 | .withString("targetUrl",targetUrl)
106 | .navigation();
107 | }
108 | }
109 |
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/common/ui/ModelRequestActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.common.ui;
2 |
3 | import android.view.View;
4 | import android.widget.TextView;
5 | import com.alibaba.android.arouter.facade.annotation.Route;
6 | import com.senon.lib_common.ConstantArouter;
7 | import com.senon.lib_common.R;
8 | import com.senon.lib_common.base.BaseActivity;
9 | import com.senon.lib_common.base.BaseResponse;
10 | import com.senon.lib_common.bean.Chapter;
11 | import com.senon.lib_common.common.contract.ModelRequestContract;
12 | import com.senon.lib_common.common.presenter.ModelRequestPresenter;
13 | import com.senon.lib_common.utils.ComUtil;
14 | import com.senon.lib_common.utils.StatusBarUtils;
15 |
16 | import java.util.List;
17 |
18 | /**
19 | * 结合model层请求数据
20 | */
21 | @Route(path = ConstantArouter.PATH_MODELREQUESTACTIVITY)
22 | public class ModelRequestActivity extends BaseActivity implements
23 | ModelRequestContract.View {
24 |
25 | private TextView tv;
26 |
27 | @Override
28 | public int getLayoutId() {
29 | StatusBarUtils.with(this).init();
30 | return R.layout.common_activity_modelrequest;
31 | }
32 |
33 | @Override
34 | public ModelRequestContract.Presenter createPresenter() {
35 | return new ModelRequestPresenter(this);
36 | }
37 |
38 | @Override
39 | public ModelRequestContract.View createView() {
40 | return this;
41 | }
42 |
43 | @Override
44 | public void init() {
45 | ComUtil.changeStatusBarTextColor(this,true);
46 |
47 | tv = findViewById(R.id.tv);
48 |
49 | }
50 |
51 | public void onClick(View view){
52 | getPresenter().getData(true,true);
53 | }
54 |
55 | @Override
56 | public void getDataResult(BaseResponse> data) {
57 | tv.setText(data.getData().toString());
58 | }
59 |
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/common/ui/RegisterActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.common.ui;
2 |
3 | import android.graphics.Paint;
4 | import android.view.View;
5 | import android.widget.EditText;
6 | import android.widget.TextView;
7 | import com.alibaba.android.arouter.facade.annotation.Autowired;
8 | import com.alibaba.android.arouter.facade.annotation.Route;
9 | import com.alibaba.android.arouter.launcher.ARouter;
10 | import com.senon.lib_common.utils.ComUtil;
11 | import com.senon.lib_common.ConstantArouter;
12 | import com.senon.lib_common.ConstantLoginArouter;
13 | import com.senon.lib_common.R;
14 | import com.senon.lib_common.base.BaseActivity;
15 | import com.senon.lib_common.base.BaseResponse;
16 | import com.senon.lib_common.bean.Login;
17 | import com.senon.lib_common.common.contract.LoginContract;
18 | import com.senon.lib_common.common.presenter.LoginPresenter;
19 | import com.senon.lib_common.utils.StatusBarUtils;
20 | import com.senon.lib_common.utils.ToastUtil;
21 |
22 | /**
23 | * 所有模块统一注册页面
24 | */
25 | @Route(path = ConstantArouter.PATH_COMMON_REGISTERACTIVITY)
26 | public class RegisterActivity extends BaseActivity implements
27 | LoginContract.View {
28 |
29 | @Autowired
30 | String targetUrl;
31 | private EditText account_edt,password_edt,password_re_edt;
32 | private TextView login_tv;
33 |
34 | @Override
35 | public int getLayoutId() {
36 | StatusBarUtils.with(this).init();
37 | return R.layout.common_activity_register;
38 | }
39 |
40 | @Override
41 | public LoginContract.Presenter createPresenter() {
42 | return new LoginPresenter(this);
43 | }
44 |
45 | @Override
46 | public LoginContract.View createView() {
47 | return this;
48 | }
49 |
50 | @Override
51 | public void init() {
52 | ComUtil.changeStatusBarTextColor(this,true);
53 |
54 | if (targetUrl == null) {
55 | //默认跳转到MainActivity
56 | targetUrl = ConstantLoginArouter.PATH_APP_MAINACTIVITY;
57 | }
58 | account_edt = findViewById(R.id.account_edt);
59 | password_edt = findViewById(R.id.password_edt);
60 | password_re_edt = findViewById(R.id.password_re_edt);
61 | login_tv = findViewById(R.id.login_tv);
62 |
63 | login_tv.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);
64 | }
65 |
66 | @Override
67 | public void getLoginResult(BaseResponse data) {
68 | }
69 |
70 | @Override
71 | public void getRegisterResult(BaseResponse data) {
72 | //登录成功时
73 | //保存参数...
74 |
75 | if(targetUrl != null){
76 | //跳转到目标页
77 | ARouter.getInstance()
78 | .build(targetUrl)
79 | .withString("msg","注册成功")
80 | .navigation();
81 | }
82 |
83 | finish();
84 | }
85 |
86 | public void onClick(View view) {
87 | int id = view.getId();
88 | if(id == R.id.register_btn){
89 | String account = account_edt.getText().toString();
90 | String password = password_edt.getText().toString();
91 | String repassword = password_re_edt.getText().toString();
92 | if (account.isEmpty()) {
93 | ToastUtil.initToast("请输入账号");
94 | return;
95 | }
96 | if (password.isEmpty()) {
97 | ToastUtil.initToast("请输入密码");
98 | return;
99 | }
100 | if (repassword.isEmpty()) {
101 | ToastUtil.initToast("请输入确认密码");
102 | return;
103 | }
104 | if (!password.equals(repassword)) {
105 | ToastUtil.initToast("确认密码与密码不同");
106 | return;
107 | }
108 | getPresenter().getRegister(ComUtil.getMd5Str(
109 | new String[]{"username", "password", "repassword"},
110 | new String[]{account.trim(), password.trim(),repassword.trim()})
111 | , true, true);
112 | }else if(id == R.id.login_tv){
113 | finish();
114 | }
115 |
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/net/RequestInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.net;
2 |
3 | import org.json.JSONObject;
4 |
5 | import java.io.IOException;
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | import okhttp3.Interceptor;
10 | import okhttp3.Request;
11 | import okhttp3.Response;
12 |
13 |
14 | /**
15 | * 网络统一拦截
16 | */
17 | public class RequestInterceptor implements Interceptor {
18 |
19 | private final int DEVICE_TYPE = 1; // 设备类型
20 |
21 | private RequestInterceptor() {
22 | }
23 |
24 | private static RequestInterceptor instance;
25 |
26 | public static RequestInterceptor getInstance() {
27 | if (instance == null) {
28 | synchronized (RequestInterceptor.class) {
29 | if (instance == null) {
30 | instance = new RequestInterceptor();
31 | }
32 | }
33 | }
34 | return instance;
35 | }
36 |
37 | @Override
38 | public Response intercept(Chain chain) throws IOException {
39 | Request original = chain.request();
40 | Request.Builder requestBuilder = original.newBuilder()
41 | .header("data", fetchHeaderInfo())
42 | .method(original.method(), original.body());
43 | return chain.proceed(requestBuilder.build());
44 | }
45 |
46 | private String fetchHeaderInfo() {
47 | // String deviceCode = MD5Utils.GetMD5Code(MobileInfo.phoneOnlyCode(context));
48 |
49 |
50 | Map map = new HashMap<>();
51 | // map.put("DeviceType", String.valueOf(DEVICE_TYPE));
52 | // map.put("DeviceToken", deviceCode);
53 | // map.put("APPVersion", APP_VERSION_NAME);
54 | // map.put("RegistrationID", jpushID);
55 | // map.put("Authorization", token);
56 | JSONObject json = new JSONObject(map);
57 | return json.toString();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/net/ServerUtils.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.net;
2 |
3 | import com.senon.lib_common.AppConfig;
4 | import com.senon.lib_common.utils.ComUtil;
5 | import com.senon.lib_common.api.BaseApi;
6 | import com.senon.lib_common.utils.ConstantUtils;
7 | import java.io.IOException;
8 | import java.security.cert.CertificateException;
9 | import java.util.concurrent.TimeUnit;
10 | import javax.net.ssl.SSLContext;
11 | import javax.net.ssl.SSLSocketFactory;
12 | import javax.net.ssl.TrustManager;
13 | import javax.net.ssl.X509TrustManager;
14 | import okhttp3.CacheControl;
15 | import okhttp3.Interceptor;
16 | import okhttp3.OkHttpClient;
17 | import okhttp3.Request;
18 | import okhttp3.Response;
19 | import okhttp3.logging.HttpLoggingInterceptor;
20 | import retrofit2.Retrofit;
21 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
22 | import retrofit2.converter.gson.GsonConverterFactory;
23 | import retrofit2.converter.scalars.ScalarsConverterFactory;
24 |
25 | /**
26 | * 网络请求 工具
27 | */
28 | public class ServerUtils {
29 | private static final int TIME_OUT = 10 * 1000;//链接超时时间
30 | private static BaseApi mBaseApi;
31 |
32 | public static BaseApi getCommonApi() {
33 | try {
34 | if (mBaseApi == null) {
35 | synchronized (ServerUtils.class) {
36 | if (mBaseApi == null) {
37 | mBaseApi = createService(BaseApi.class, AppConfig.BASE_URL);
38 | }
39 | }
40 | }
41 | } catch (Exception e) {
42 | e.printStackTrace();
43 | }
44 | return mBaseApi;
45 | }
46 |
47 | private static S createService(Class serviceClass, String url) throws Exception {
48 | Retrofit.Builder builder =
49 | new Retrofit.Builder()
50 | .baseUrl(url)
51 | .client(httpClient.build())
52 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
53 | .addConverterFactory(ScalarsConverterFactory.create())
54 | .addConverterFactory(GsonConverterFactory.create());
55 | Retrofit retrofit = builder.build();
56 | return retrofit.create(serviceClass);
57 | }
58 |
59 | private static Interceptor cacheInterceptor = new Interceptor() {
60 | @Override
61 | public Response intercept(Chain chain) throws IOException {
62 | Request request = chain.request();
63 | if (!ComUtil.isNetworkConnected()) {
64 | request = request.newBuilder()
65 | .cacheControl(CacheControl.FORCE_CACHE)
66 | .build();
67 | }
68 | Response response = chain.proceed(request);
69 | if (ComUtil.isNetworkConnected()) {
70 | int maxAge = 0;
71 | // 有网络时, 不缓存, 最大保存时长为0
72 | response.newBuilder()
73 | .header("Cache-Control", "public, max-age=" + maxAge)
74 | .removeHeader("Pragma")
75 | .build();
76 | } else {
77 | // 无网络时,设置超时为1周
78 | int maxStale = 60 * 60 * 24 * 7;
79 | response.newBuilder()
80 | .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
81 | .removeHeader("Pragma")
82 | .build();
83 | }
84 | return response;
85 | }
86 | };
87 |
88 | private static OkHttpClient.Builder httpClient =
89 | new OkHttpClient.Builder()
90 | //设置超时
91 | .readTimeout(TIME_OUT, TimeUnit.SECONDS)
92 | .writeTimeout(TIME_OUT, TimeUnit.SECONDS)
93 | .connectTimeout(TIME_OUT, TimeUnit.SECONDS)
94 | // .addInterceptor(RequestInterceptor.getInstance())//网络请求 统一拦截
95 | .addInterceptor(getLogInterceptor())
96 | .sslSocketFactory(getSSLSocketFactory())
97 | //设置缓存
98 | .addNetworkInterceptor(cacheInterceptor)
99 | .addInterceptor(cacheInterceptor)
100 | .hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
101 |
102 |
103 | private static HttpLoggingInterceptor getLogInterceptor() {
104 | HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
105 | if (ConstantUtils.isAppDebug()) {
106 | loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
107 | } else {
108 | loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
109 | }
110 | return loggingInterceptor;
111 | }
112 |
113 | /**
114 | * 不验证证书
115 | *
116 | * @return
117 | * @throws Exception
118 | */
119 | private static SSLSocketFactory getSSLSocketFactory() {
120 | //创建一个不验证证书链的证书信任管理器。
121 | final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
122 | @Override
123 | public void checkClientTrusted(
124 | java.security.cert.X509Certificate[] chain,
125 | String authType) throws CertificateException {
126 | }
127 |
128 | @Override
129 | public void checkServerTrusted(
130 | java.security.cert.X509Certificate[] chain,
131 | String authType) throws CertificateException {
132 | }
133 |
134 | @Override
135 | public java.security.cert.X509Certificate[] getAcceptedIssuers() {
136 | return new java.security.cert.X509Certificate[0];
137 | }
138 | }};
139 |
140 | final SSLContext sslContext;
141 | try {
142 | sslContext = SSLContext.getInstance("TLS");
143 | sslContext.init(null, trustAllCerts,
144 | new java.security.SecureRandom());
145 | return sslContext
146 | .getSocketFactory();
147 | } catch (Exception e) {
148 | e.printStackTrace();
149 | }
150 | return null;
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/net/callback/ErrorListener.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.net.callback;
2 |
3 |
4 |
5 | public interface ErrorListener {
6 | void handleError(Throwable e);
7 | }
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/net/callback/RequestCallback.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.net.callback;
2 |
3 | import android.content.Context;
4 | import com.senon.lib_common.net.progress.ProgressCancelListener;
5 | import com.senon.lib_common.net.progress.ProgressDialogHandler;
6 | import io.reactivex.Observer;
7 | import io.reactivex.annotations.NonNull;
8 | import io.reactivex.disposables.Disposable;
9 |
10 |
11 | /**
12 | * RxJava 自定义回调
13 | */
14 | public abstract class RequestCallback implements Observer,ProgressCancelListener {
15 |
16 | private ErrorListener errorListener;
17 | private Disposable mDisposable;
18 | private Context mContext;
19 | private boolean cancelable = false;//该dialog如果开启 则可以设置是否能够返回键取消请求
20 | private ProgressDialogHandler mProgressDialogHandler;//默认为null 即不开启dialog
21 |
22 | public RequestCallback(Context context,ErrorListener errorListener) {
23 | this(context,errorListener,false);
24 | }
25 |
26 | /**
27 | * 传这个构造默认开启dialog
28 | * @param cancelable 该dialog如果开启 则可以设置是否能够返回键取消请求
29 | */
30 | public RequestCallback(Context context, ErrorListener errorListener, boolean cancelable) {
31 | this(context,errorListener,true,cancelable);
32 | }
33 |
34 | public RequestCallback(Context context, ErrorListener errorListener, boolean showDialog, boolean cancelable) {
35 | this.mContext = context;
36 | this.errorListener = errorListener;
37 | this.cancelable = cancelable;
38 | if(showDialog){
39 | this.mProgressDialogHandler = new ProgressDialogHandler(context, this, cancelable);
40 | }
41 | }
42 |
43 | private void showProgressDialog() {
44 | if (mProgressDialogHandler != null) {
45 | mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG).sendToTarget();
46 | }
47 | }
48 |
49 | private void dismissProgressDialog() {
50 | if (mProgressDialogHandler != null) {
51 | mProgressDialogHandler.obtainMessage(ProgressDialogHandler.DISMISS_PROGRESS_DIALOG).sendToTarget();
52 | mProgressDialogHandler = null;
53 | }
54 | }
55 |
56 | @Override
57 | public void onSubscribe(@NonNull Disposable d) {
58 | this.mDisposable = d;
59 | showProgressDialog();
60 |
61 | }
62 |
63 | @Override
64 | public void onNext(@NonNull T t) {
65 |
66 | }
67 |
68 | @Override
69 | public void onError(@NonNull Throwable e) {
70 | e.printStackTrace();
71 | dismissProgressDialog();
72 | onCancelProgress();
73 |
74 | if (errorListener != null) {
75 | errorListener.handleError(e);
76 | }
77 | }
78 |
79 | @Override
80 | public void onComplete() {
81 | dismissProgressDialog();
82 | onCancelProgress();
83 | }
84 |
85 | @Override
86 | public void onCancelProgress() {
87 | //如果处于订阅状态,则取消订阅
88 | if (!mDisposable.isDisposed()) {
89 | mDisposable.dispose();
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/net/callback/RxErrorHandler.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.net.callback;
2 |
3 |
4 | import com.senon.lib_common.utils.LogUtils;
5 | import com.senon.lib_common.utils.ToastUtil;
6 |
7 | /**
8 | * 做为网络请求异常监听
9 | * 可以在回调中做统一 处理方法,比如:收到服务器响应码为201 未登录 此时可以做直接跳转到登录注册页
10 | */
11 | public class RxErrorHandler implements ErrorListener {
12 |
13 | private volatile static RxErrorHandler rxErrorHandler;
14 |
15 | private RxErrorHandler() {
16 | }
17 |
18 | public static RxErrorHandler getInstance() {
19 | if (rxErrorHandler == null) {
20 | synchronized (RxErrorHandler.class) {
21 | if (rxErrorHandler == null) {
22 | rxErrorHandler = new RxErrorHandler();
23 | }
24 | }
25 | }
26 | return rxErrorHandler;
27 | }
28 |
29 | @Override
30 | public void handleError(Throwable throwable) {
31 | String errorString = throwable.toString();
32 | LogUtils.e("网络错误信息为 ========>>>" + throwable.toString());
33 | //返回的错误为空
34 | if (errorString == null) {
35 | ToastUtil.initToast("网络数据异常,请重试");
36 |
37 | } else {
38 | //请求超时
39 | if (errorString.contains("TimeoutException") || errorString.contains("SocketTimeoutException")) {
40 | ToastUtil.initToast("网络请求超时,请重试");
41 | }
42 | //能识别的请求异常,忽略不提示
43 | if (errorString.contains("SSLException")) {
44 |
45 | }
46 | //403、404等服务错误
47 | if (errorString.contains("ServiceConfigurationError") || errorString.contains("AuthenticatorException")) {
48 | ToastUtil.initToast("网络数据异常,请重试");
49 | }
50 | //网络未连接
51 | if (errorString.contains("NetworkErrorException") || errorString.contains("NoConnectionPendingException") || errorString.contains("UnknownHostException")) {
52 | ToastUtil.initToast("您的网络不给力,请检查网络设置");
53 | }
54 | //连接不到服务器
55 | if (errorString.contains("ConnectException")) {
56 | ToastUtil.initToast("网络连接失败");
57 | }
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/net/progress/ProgressCancelListener.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.net.progress;
2 |
3 | /**
4 | * 取消请求监听
5 | */
6 | public interface ProgressCancelListener {
7 | void onCancelProgress();
8 | }
9 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/net/progress/ProgressDialogHandler.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.net.progress;
2 |
3 | import android.content.Context;
4 | import android.content.DialogInterface;
5 | import android.os.Handler;
6 | import android.os.Message;
7 |
8 | import cn.pedant.SweetAlert.SweetAlertDialog;
9 |
10 | /**
11 | * Dialog的进度控制
12 | */
13 | public class ProgressDialogHandler extends Handler {
14 | public static final int SHOW_PROGRESS_DIALOG = 1;
15 | public static final int DISMISS_PROGRESS_DIALOG = 2;
16 |
17 | private SweetAlertDialog sad;
18 | private Context context;
19 | private boolean cancelable;
20 | private ProgressCancelListener mProgressCancelListener;
21 |
22 | public ProgressDialogHandler(Context context, ProgressCancelListener mProgressCancelListener, boolean cancelable) {
23 | super();
24 | this.context = context;
25 | this.mProgressCancelListener = mProgressCancelListener;
26 | this.cancelable = cancelable;
27 | }
28 |
29 | private void initProgressDialog() {
30 | if (sad == null) {
31 | sad = new SweetAlertDialog(context);
32 | sad.changeAlertType(SweetAlertDialog.PROGRESS_TYPE);
33 | sad.setTitleText("正在加载...");
34 | sad.setCancelable(cancelable);
35 |
36 | if (cancelable) {
37 | sad.setOnCancelListener(new DialogInterface.OnCancelListener() {
38 | @Override
39 | public void onCancel(DialogInterface dialogInterface) {
40 | mProgressCancelListener.onCancelProgress();
41 | }
42 | });
43 | }
44 |
45 | if (!sad.isShowing()) {
46 | sad.show();
47 | }
48 | }
49 | }
50 |
51 | private void dismissProgressDialog() {
52 | if (sad != null) {
53 | sad.dismiss();
54 | sad = null;
55 | }
56 | }
57 |
58 | @Override
59 | public void handleMessage(Message msg) {
60 | switch (msg.what) {
61 | case SHOW_PROGRESS_DIALOG:
62 | initProgressDialog();
63 | break;
64 | case DISMISS_PROGRESS_DIALOG:
65 | dismissProgressDialog();
66 | break;
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/ActivityCollector.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 | import android.app.Activity;
4 |
5 | import java.util.HashSet;
6 | import java.util.Set;
7 |
8 | /**
9 | * 一键退出App
10 | */
11 |
12 | public class ActivityCollector {
13 |
14 | private static ActivityCollector activityCollector;
15 |
16 | public synchronized static ActivityCollector getInstance() {
17 | if (activityCollector == null) {
18 | activityCollector = new ActivityCollector();
19 | }
20 | return activityCollector;
21 | }
22 |
23 | private Set allActivities;
24 |
25 | public void addActivity(Activity act) {
26 | if (allActivities == null) {
27 | allActivities = new HashSet<>();
28 | }
29 | allActivities.add(act);
30 | }
31 |
32 | public void removeActivity(Activity act) {
33 | if (allActivities != null) {
34 | allActivities.remove(act);
35 | }
36 | }
37 |
38 | public void exitApp() {
39 | if (allActivities != null) {
40 | synchronized (allActivities) {
41 | for (Activity act : allActivities) {
42 | act.finish();
43 | }
44 | }
45 | }
46 | android.os.Process.killProcess(android.os.Process.myPid());
47 | System.exit(0);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/ComUtil.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.net.ConnectivityManager;
6 | import android.os.Build;
7 | import android.util.DisplayMetrics;
8 | import android.view.View;
9 | import java.text.SimpleDateFormat;
10 | import java.util.HashMap;
11 | import java.util.Iterator;
12 | import java.util.Map;
13 | import java.util.regex.Matcher;
14 | import java.util.regex.Pattern;
15 |
16 | /**
17 | * CommonUtils
18 | */
19 | public class ComUtil {
20 |
21 | /**
22 | * 改变状态栏字体颜色
23 | * @param context
24 | * @param isBlack true黑色 false白色
25 | */
26 | public static void changeStatusBarTextColor(Context context,boolean isBlack) {
27 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
28 | if (isBlack) {
29 | //设置状态栏黑色字体
30 | ((Activity)context).getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
31 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
32 | } else {
33 | //恢复状态栏白色字体
34 | ((Activity)context).getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
35 |
36 | }
37 | }
38 | }
39 |
40 |
41 | public static boolean isNumeric(String str) {
42 | Pattern pattern = Pattern.compile("^1[3|4|5|7|8|9][0-9]{9}$");
43 | Matcher isNum = pattern.matcher(str);
44 | if (!isNum.matches()) {
45 | return false;
46 | }
47 | return true;
48 | }
49 |
50 | public static boolean isChinese(String str) {
51 | Pattern pattern = Pattern.compile("^[\\u4E00-\\u9FA5]+$");
52 | Matcher isNum = pattern.matcher(str);
53 | if (!isNum.matches()) {
54 | return false;
55 | }
56 | return true;
57 | }
58 |
59 | //long型时间转换为字符串时间类型
60 | public static String longToString(Object longTime, String timeFormat) {
61 | SimpleDateFormat formatter = new SimpleDateFormat(timeFormat == null ? "yyyy-MM-dd" : timeFormat);
62 | long time = 0;
63 | if (longTime instanceof Integer || longTime instanceof Long) {
64 | return formatter.format(longTime);
65 | } else if (longTime instanceof String) {
66 | return formatter.format(Long.valueOf((String) longTime));
67 | }
68 | return "时间获取错误";
69 | }
70 |
71 | //检查是否有可用网络
72 | public static boolean isNetworkConnected() {
73 | ConnectivityManager connectivityManager = (ConnectivityManager) ConstantUtils.getAPPContext().
74 | getSystemService(Context.CONNECTIVITY_SERVICE);
75 | assert connectivityManager != null;
76 | return connectivityManager.getActiveNetworkInfo() != null;
77 | }
78 |
79 | // 屏幕宽度(像素)
80 | public static int getScreenWidth(Context context) {
81 | DisplayMetrics metric = new DisplayMetrics();
82 | ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metric);
83 | return metric.widthPixels;
84 | }
85 |
86 | public static int getScreenHeight(Context context) {
87 | DisplayMetrics metric = new DisplayMetrics();
88 | ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metric);
89 | return metric.heightPixels;
90 | }
91 |
92 | public static String getMd5Str(HashMap map) {
93 | StringBuffer sb = new StringBuffer();
94 | Iterator iterator = map.entrySet().iterator();
95 | while (iterator.hasNext()) {
96 | Map.Entry entry = (Map.Entry) iterator.next();
97 | sb.append(entry.getValue().toString());
98 | }
99 | return MD5Utils.getMd5(sb.toString() );
100 | }
101 |
102 | public static HashMap getMd5Str(String[] keyArray, String[] valueArray) {
103 | HashMap map = new HashMap<>();
104 | StringBuffer sb = new StringBuffer();
105 | if (keyArray.length != valueArray.length) {
106 | ToastUtil.initToast("key value长度不对应");
107 | } else {
108 | for (int i = 0; i < keyArray.length; i++) {
109 | map.put(keyArray[i], valueArray[i]);
110 | }
111 | for (int i = 0; i < valueArray.length; i++) {
112 | sb.append(valueArray[i]);
113 | }
114 | map.put("secret", MD5Utils.getMd5(sb.toString()));
115 | return map;
116 | }
117 | return null;
118 | }
119 |
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/ConstantUtils.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 | import android.content.Context;
4 | import android.content.pm.ApplicationInfo;
5 | import android.content.pm.PackageManager;
6 |
7 | /**
8 | * 基础常量工具类
9 | * 获取工程ApplicationContext对象时强制使用 如下getAPPContext()方法获取
10 | */
11 | public class ConstantUtils {
12 | private static Context context;
13 | /**
14 | * 初始化工具类
15 | * @param context 上下文
16 | */
17 | public static void init(Context context) {
18 | ConstantUtils.context = context.getApplicationContext();
19 | }
20 |
21 | /**
22 | * 获取ApplicationContext
23 | * @return ApplicationContext
24 | */
25 | public static Context getAPPContext() {
26 | if (context != null) return context;
27 | throw new NullPointerException("u should init first");
28 | }
29 |
30 | /**
31 | * 判断App是否是Debug版本
32 | * @return {@code true}: 是
{@code false}: 否
33 | */
34 | public static boolean isAppDebug() {
35 | String packageName = context.getPackageName();
36 | if (packageName == null || packageName.trim().length() == 0)
37 | return false;
38 | try {
39 | PackageManager pm = context.getPackageManager();
40 | ApplicationInfo ai = pm.getApplicationInfo(context.getPackageName(), 0);
41 | return ai != null && (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
42 | } catch (PackageManager.NameNotFoundException e) {
43 | e.printStackTrace();
44 | return false;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/JsonServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 | import android.content.Context;
4 | import com.alibaba.android.arouter.facade.annotation.Route;
5 | import com.alibaba.android.arouter.facade.service.SerializationService;
6 | import com.google.gson.Gson;
7 | import java.lang.reflect.Type;
8 |
9 |
10 | // 如果需要传递自定义对象,新建一个类(并非自定义对象类),然后实现 SerializationService,
11 | // 并使用@Route注解标注(方便用户自行选择序列化方式),例如:
12 | @Route(path = "/service/json")
13 | public class JsonServiceImpl implements SerializationService {
14 |
15 | private Gson mGson;
16 |
17 | @Override
18 | public void init(Context context) {
19 | mGson = new Gson();
20 |
21 | }
22 |
23 | @Override
24 | public T json2Object(String text, Class clazz) {
25 | checkJson();
26 | return mGson.fromJson(text, clazz);
27 | }
28 |
29 | @Override
30 | public String object2Json(Object instance) {
31 | checkJson();
32 | return mGson.toJson(instance);
33 | }
34 |
35 | @Override
36 | public T parseObject(String input, Type clazz) {
37 | checkJson();
38 | return mGson.fromJson(input, clazz);
39 | }
40 |
41 | public void checkJson() {
42 | if (mGson == null) {
43 | mGson = new Gson();
44 | }
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/LogUtils.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 | import android.util.Log;
4 | import java.util.Locale;
5 |
6 | /**
7 | * 打印log日志工具类
8 | */
9 | public class LogUtils {
10 | private static boolean LOG = true;
11 | private static boolean LOGV = true;
12 | private static boolean LOGD = true;
13 | private static boolean LOGI = true;
14 | private static boolean LOGW = true;
15 | private static boolean LOGE = true;
16 |
17 | public static void setLogEnable(boolean enable) {
18 | LOG = enable;
19 | }
20 |
21 | public static void v(String mess) {
22 | if (LOG && LOGV) {
23 | Log.v(getTag(), buildMessage(mess));
24 | }
25 | }
26 |
27 | public static void d(String mess) {
28 | if (LOG && LOGD) {
29 | Log.d(getTag(), buildMessage(mess));
30 | }
31 | }
32 |
33 | public static void i(String mess) {
34 | if (LOG && LOGI) {
35 | Log.i(getTag(), buildMessage(mess));
36 | }
37 | }
38 |
39 | public static void w(String mess) {
40 | if (LOG && LOGW) {
41 | Log.w(getTag(), buildMessage(mess));
42 | }
43 | }
44 |
45 | public static void e(String mess) {
46 | if (LOG && LOGE) {
47 | log(getTag(), buildMessage(mess));
48 | }
49 | }
50 |
51 | public static void log(String tag, String msg){
52 | if(msg.length() > 4000) {
53 | for(int i=0;i clazz = trace[i].getClass();
69 | if (!clazz.equals(LogUtils.class)) {
70 | callingClass = trace[i].getClassName();
71 | callingClass = callingClass.substring(callingClass
72 | .lastIndexOf('.') + 1);
73 | break;
74 | }
75 | }
76 | return callingClass;
77 | }
78 |
79 | private static String buildMessage(String msg) {
80 | StackTraceElement[] trace = new Throwable().fillInStackTrace()
81 | .getStackTrace();
82 | String caller = "";
83 | for (int i = 2; i < trace.length; i++) {
84 | Class> clazz = trace[i].getClass();
85 | if (!clazz.equals(LogUtils.class)) {
86 | caller = trace[i].getMethodName();
87 | break;
88 | }
89 | }
90 | return String.format(Locale.US, "[%d] %s: %s", Thread.currentThread()
91 | .getId(), caller, msg);
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/MD5Utils.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 | import java.security.MessageDigest;
4 | import java.security.NoSuchAlgorithmException;
5 |
6 | /**
7 | * MD5工具
8 | */
9 | public class MD5Utils {
10 | //静态方法,便于作为工具类
11 | public static String getMd5(String plainText) {
12 | try {
13 | MessageDigest md = MessageDigest.getInstance("MD5");
14 | md.update(plainText.getBytes());
15 | byte b[] = md.digest();
16 | int i;
17 | StringBuffer buf = new StringBuffer("");
18 | for (int offset = 0; offset < b.length; offset++) {
19 | i = b[offset];
20 | if (i < 0)
21 | i += 256;
22 | if (i < 16)
23 | buf.append("0");
24 | buf.append(Integer.toHexString(i));
25 | }
26 | //32位加密
27 | return buf.toString();
28 | // 16位的加密
29 | //return buf.toString().substring(8, 24);
30 | } catch (NoSuchAlgorithmException e) {
31 | e.printStackTrace();
32 | return null;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/PreferenceTool.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import com.senon.lib_opensource.BuildConfig;
6 | import java.util.Map;
7 |
8 | /**
9 | * 共享参数工具类
10 | */
11 | public class PreferenceTool {
12 |
13 | private static final String PREF_NAME = BuildConfig.APPLICATION_ID + "_preferences";
14 | private static SharedPreferences.Editor editor;
15 | private static SharedPreferences pref;
16 |
17 |
18 | public static void init(Context context) {
19 | pref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
20 | editor = pref.edit();
21 | }
22 |
23 | public static void clear() {
24 | if (editor == null) return;
25 | editor.clear();
26 | }
27 |
28 | public static void commit() {
29 | if (editor == null) return;
30 | editor.commit();
31 | }
32 |
33 | public static void apply() {
34 | if (editor == null) return;
35 | editor.apply();
36 | }
37 |
38 | public static boolean contains(String key) {
39 | return pref != null && pref.contains(key);
40 | }
41 |
42 | public static float getFloat(String key, float defValue) {
43 | return pref != null ? pref.getFloat(key, defValue) : defValue;
44 | }
45 |
46 | public static int getInt(String key, int defValue) {
47 | return pref != null ? pref.getInt(key, defValue) : defValue;
48 | }
49 |
50 | public static long getLong(String key, long defValue) {
51 | return pref != null ? pref.getLong(key, defValue) : defValue;
52 | }
53 |
54 | public static String getString(String key) {
55 | return pref != null ? pref.getString(key, "") : "";
56 | }
57 |
58 | public static String getString(String key, String defValue) {
59 | return pref != null ? pref.getString(key, defValue) : defValue;
60 | }
61 |
62 | public static boolean getBoolean(String key, boolean defValue) {
63 | return pref != null ? pref.getBoolean(key, defValue) : defValue;
64 | }
65 |
66 | public static Map getAll() {
67 | return pref != null ? pref.getAll() : null;
68 | }
69 |
70 |
71 |
72 | public static void putFloat(String key, float value) {
73 | if (editor == null) return;
74 | editor.putFloat(key, value);
75 | }
76 |
77 | public static void putInt(String key, int value) {
78 | if (editor == null) return;
79 | editor.putInt(key, value);
80 | }
81 |
82 | public static void putLong(String key, long value) {
83 | if (editor == null) return;
84 | editor.putLong(key, value);
85 | }
86 |
87 | public static void putString(String key, String value) {
88 | if (editor == null) return;
89 | editor.putString(key, value);
90 | }
91 |
92 | public static void putBoolean(String key, boolean value) {
93 | if (editor == null) return;
94 | editor.putBoolean(key, value);
95 | }
96 |
97 | public static void remove(String key) {
98 | if (editor == null) return;
99 | editor.remove(key);
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/RetryWithDelay.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 |
4 | import java.util.concurrent.TimeUnit;
5 | import io.reactivex.Observable;
6 | import io.reactivex.ObservableSource;
7 | import io.reactivex.annotations.NonNull;
8 | import io.reactivex.functions.Function;
9 |
10 | /**
11 | * 使用rxjava 网络重试
12 | */
13 | public class RetryWithDelay implements Function, ObservableSource>> {
14 |
15 | private final int maxRetries;
16 | private final int retryDelaySecond;
17 | private int retryCount;
18 |
19 | public RetryWithDelay(int maxRetries, int retryDelaySecond) {
20 | this.maxRetries = maxRetries;
21 | this.retryDelaySecond = retryDelaySecond;
22 | }
23 |
24 | @Override
25 | public ObservableSource> apply(@NonNull Observable throwableObservable) throws Exception {
26 | return throwableObservable
27 | .flatMap(new Function>() {
28 | @Override
29 | public ObservableSource> apply(@NonNull Throwable throwable) throws Exception {
30 | if (++retryCount <= maxRetries) {
31 | // When this Observable calls onNext, the original Observable will be retried (i.e. re-subscribed).
32 | LogUtils.d("get error, it will try after " + retryDelaySecond
33 | + " second, retry count " + retryCount);
34 | return Observable.timer(retryDelaySecond,
35 | TimeUnit.SECONDS);
36 | }
37 | // Max retries hit. Just pass the error along.
38 | return Observable.error(throwable);
39 | }
40 | });
41 | }
42 | }
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/RxUtils.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 | import com.senon.lib_common.base.BaseViewImp;
4 | import com.trello.rxlifecycle2.LifecycleTransformer;
5 | import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
6 | import com.trello.rxlifecycle2.components.support.RxFragment;
7 |
8 | import io.reactivex.Observable;
9 | import io.reactivex.ObservableSource;
10 | import io.reactivex.ObservableTransformer;
11 | import io.reactivex.android.schedulers.AndroidSchedulers;
12 | import io.reactivex.annotations.NonNull;
13 | import io.reactivex.schedulers.Schedulers;
14 |
15 | /**
16 | * 在presenter中使用生命周期管理,防止内存泄漏
17 | */
18 | public class RxUtils {
19 |
20 | public static LifecycleTransformer bindToLifecycle(BaseViewImp view) {
21 | if (view instanceof RxAppCompatActivity) {
22 | return ((RxAppCompatActivity) view).bindToLifecycle();
23 | } else if (view instanceof RxFragment) {
24 | return ((RxFragment) view).bindToLifecycle();
25 | } else {
26 | throw new IllegalArgumentException("view isn't activity or fragment");
27 | }
28 | }
29 |
30 | public static ObservableTransformer getSchedulerTransformer(){
31 | return new ObservableTransformer() {
32 | @Override
33 | public ObservableSource apply(@NonNull Observable upstream) {
34 | return upstream
35 | .subscribeOn(Schedulers.io())
36 | .unsubscribeOn(Schedulers.io())
37 | .observeOn(AndroidSchedulers.mainThread());
38 | }
39 | };
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/lib_common/src/main/java/com/senon/lib_common/utils/ToastUtil.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 | import android.support.annotation.NonNull;
8 | import android.support.v4.app.FragmentActivity;
9 | import android.view.Gravity;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.widget.TextView;
13 | import android.widget.Toast;
14 |
15 | import com.senon.lib_common.R;
16 |
17 |
18 | /**
19 | * Toast工具类
20 | */
21 | public class ToastUtil {
22 |
23 | /**
24 | * 可以在多线程里运行的toast
25 | */
26 | private static volatile Toast mToast;
27 | private static final Object lock = new Object();
28 | private static Context context;
29 | private static TextView toastTv;
30 |
31 | public static void init(Context con){
32 | context = con;
33 | }
34 |
35 | public static void initToast(String msg) {
36 | initToast(msg, context, true);
37 | }
38 |
39 | public static void initToast(int resId, Context context) {
40 | if (context instanceof Activity || context instanceof FragmentActivity)
41 | context = context.getApplicationContext();
42 | initToast(context.getString(resId), context, true);
43 | }
44 |
45 | public static void initToast(String msg, Context context, boolean isSingleton) {
46 | if (context instanceof Activity || context instanceof FragmentActivity)
47 | context = context.getApplicationContext();
48 | if (mToast != null && isSingleton) {
49 | toastTv.setText(msg);
50 | } else {
51 | synchronized (lock) {
52 | // mToast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
53 | mToast = showToast(context,msg,Toast.LENGTH_SHORT);
54 | }
55 | }
56 | mToast.setGravity(Gravity.CENTER, 0, 0);//默认显示位置
57 | mToast.show();
58 | }
59 | //可以设置toast的位置
60 | public static void setGravity(int gravity, int xOffset, int yOffset) {
61 | mToast.setGravity(gravity, xOffset, yOffset);
62 | }
63 | //可以自定义toast的view
64 | public void setView(View view) {
65 | mToast.setView(view);
66 | }
67 |
68 |
69 | /**
70 | 当你在线程中使用toast时,请使用这个方法(可以控制显示多长时间)
71 | */
72 | public static void showInThread(@NonNull final Context context, final String msg, final int length) {
73 | new Thread() {
74 | @Override
75 | public void run() {
76 | Looper.prepare();//先移除
77 | Toast.makeText(context, msg, length).show();
78 | Looper.loop();// 进入loop中的循环,查看消息队列
79 | }
80 | }.start();
81 | }
82 |
83 | /**
84 | * 以下全部代码为一个整体,可以控制显示时间的Toast
85 | */
86 | private static Handler mHandler = null;
87 | private static int duration = 0;
88 | private static int currDuration = 0;
89 | private static final int DEFAULT = 2000;
90 |
91 | public static void showByDuration(Context context, String msg, int duration) {
92 | duration = duration;
93 | currDuration = DEFAULT;
94 | // mToast = Toast.makeText(context, msg, Toast.LENGTH_LONG);
95 | mToast = showToast(context,msg,Toast.LENGTH_LONG);
96 | mHandler = new Handler(context.getMainLooper());
97 | mHandler.post(mToastThread);
98 | }
99 |
100 | private static Runnable mToastThread = new Runnable() {
101 | public void run() {
102 | mToast.show();
103 | mHandler.postDelayed(mToastThread, DEFAULT);// 每隔2秒显示一次
104 | if (duration != 0) {
105 | if (currDuration <= duration) {
106 | currDuration += DEFAULT;
107 | } else {
108 | cancel();
109 | }
110 | }
111 | }
112 | };
113 |
114 | private static void cancel() {
115 | mHandler.removeCallbacks(mToastThread);// 先把显示线程删除
116 | mToast.cancel();// 把最后一个线程的显示效果cancel掉,就一了百了了
117 | currDuration = DEFAULT;
118 | }
119 |
120 |
121 | private static Toast showToast(Context context, String msg, int duration) {
122 | if (null != context) {
123 | if (mToast == null) {
124 | mToast = new Toast(context);
125 | LayoutInflater inflater = LayoutInflater.from(context);
126 | View layout = inflater.inflate(R.layout.common_toast_layout, null);
127 | toastTv = layout.findViewById(R.id.message);
128 | toastTv.setText(msg);
129 | mToast.setDuration(duration);
130 | mToast.setView(layout);
131 | }else {
132 | toastTv.setText(msg);
133 | }
134 | }
135 | return mToast;
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/lib_common/src/main/res/drawable/common_ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/lib_common/src/main/res/drawable/common_toast_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/lib_common/src/main/res/layout/common_activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
23 |
24 |
39 |
40 |
51 |
52 |
63 |
64 |
--------------------------------------------------------------------------------
/lib_common/src/main/res/layout/common_activity_modelrequest.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
23 |
24 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/lib_common/src/main/res/layout/common_activity_register.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
23 |
24 |
39 |
40 |
55 |
56 |
67 |
68 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/lib_common/src/main/res/layout/common_toast_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
24 |
25 |
--------------------------------------------------------------------------------
/lib_common/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #2BBBE6
7 | #00ffffff
8 |
9 |
10 | #414040
11 | #55bfb9b9
12 | #ffffff
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/lib_common/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | lib_common
3 |
4 |
--------------------------------------------------------------------------------
/lib_common/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lib_common/src/test/java/com/senon/lib_common/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_common;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/lib_opensource/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/lib_opensource/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion rootProject.ext.android["compileSdkVersion"]
5 |
6 | defaultConfig {
7 | minSdkVersion rootProject.ext.android["minSdkVersion"]
8 | targetSdkVersion rootProject.ext.android["targetSdkVersion"]
9 | versionCode rootProject.ext.android["versionCode"]
10 | versionName rootProject.ext.android["versionName"]
11 |
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 |
14 | // 每个模块都需要导入
15 | javaCompileOptions {
16 | annotationProcessorOptions {
17 | arguments = [ AROUTER_MODULE_NAME : project.getName() ]
18 | }
19 | }
20 | }
21 |
22 | buildTypes {
23 | release {
24 | minifyEnabled false
25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
26 | }
27 | }
28 |
29 | }
30 |
31 | dependencies {
32 | implementation fileTree(dir: 'libs', include: ['*.jar'])
33 | testImplementation rootProject.ext.dependencies["junit"]
34 |
35 | api rootProject.ext.dependencies["support-v4"]
36 | api rootProject.ext.dependencies["appcompat-v7"]
37 | api rootProject.ext.dependencies["design"]
38 | api rootProject.ext.dependencies["recyclerview-v7"]
39 | api rootProject.ext.dependencies["cardview-v7"]
40 |
41 | api rootProject.ext.dependencies["rxandroid"]
42 | api rootProject.ext.dependencies["retrofit"]
43 | api rootProject.ext.dependencies["rxlifecycle"]
44 | api rootProject.ext.dependencies["rxlifecycle-components"]
45 | api rootProject.ext.dependencies["adapter-rxjava"]
46 | api rootProject.ext.dependencies["retrofit-converter"]
47 | api rootProject.ext.dependencies["retrofit-converter-gson"]
48 | api rootProject.ext.dependencies["gson"]
49 |
50 | api rootProject.ext.dependencies["okhttp3"]
51 | api rootProject.ext.dependencies["okhttp3-logging-interceptor"]
52 |
53 | api rootProject.ext.dependencies["router"]
54 |
55 | api rootProject.ext.dependencies["sweetalert"]
56 | api rootProject.ext.dependencies["autosize"]
57 |
58 | api rootProject.ext.dependencies["glide"]
59 | api rootProject.ext.dependencies["eventbus"]
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/lib_opensource/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/lib_opensource/src/androidTest/java/com/senon/lib_opensource/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_opensource;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.senon.lib_opensource", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib_opensource/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/lib_opensource/src/test/java/com/senon/lib_opensource/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.lib_opensource;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/module_one/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/module_one/build.gradle:
--------------------------------------------------------------------------------
1 | if (isBuildModule.toBoolean()) {
2 | apply plugin: 'com.android.application'
3 | } else {
4 | apply plugin: 'com.android.library'
5 | }
6 |
7 | android {
8 | compileSdkVersion rootProject.ext.android["compileSdkVersion"]
9 |
10 | resourcePrefix "one_"
11 |
12 | sourceSets {
13 | main {
14 | if (isBuildModule.toBoolean()) {
15 | manifest.srcFile 'src/main/debug/AndroidManifest.xml'
16 | } else {
17 | manifest.srcFile 'src/main/release/AndroidManifest.xml'
18 | java {
19 | //全部Module一起编译的时候剔除debug目录
20 | exclude '**/**/debug/**'
21 | }
22 | }
23 | }
24 | }
25 |
26 | defaultConfig {
27 | if (isBuildModule.toBoolean()) {
28 | applicationId "com.senon.module_one"
29 | }
30 | minSdkVersion rootProject.ext.android["minSdkVersion"]
31 | targetSdkVersion rootProject.ext.android["targetSdkVersion"]
32 | versionCode rootProject.ext.android["versionCode"]
33 | versionName rootProject.ext.android["versionName"]
34 |
35 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
36 | javaCompileOptions {
37 | annotationProcessorOptions {
38 | arguments = [AROUTER_MODULE_NAME: project.getName()]
39 | }
40 | }
41 | }
42 |
43 | buildTypes {
44 | release {
45 | minifyEnabled false
46 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
47 | }
48 | }
49 |
50 | }
51 |
52 | dependencies {
53 | implementation fileTree(dir: 'libs', include: ['*.jar'])
54 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
55 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
56 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
57 | testImplementation rootProject.ext.dependencies["junit"]
58 |
59 | api project(':lib_common')
60 | annotationProcessor rootProject.ext.dependencies["router-compiler"]
61 |
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/module_one/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/module_one/src/androidTest/java/com/senon/module_one/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_one;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.senon.module_one", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/module_one/src/main/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/module_one/src/main/java/com/senon/module_one/App_One.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_one;
2 |
3 | import com.alibaba.android.arouter.launcher.ARouter;
4 | import com.senon.lib_common.base.BaseApplication;
5 | import com.senon.lib_common.utils.ConstantUtils;
6 |
7 | /**
8 | * one debug Application
9 | */
10 | public class App_One extends BaseApplication {
11 | @Override
12 | public void onCreate() {
13 | super.onCreate();
14 |
15 | initARouter();
16 | }
17 |
18 | private void initARouter() {
19 | if (ConstantUtils.isAppDebug()) {
20 | //开启InstantRun之后,一定要在ARouter.init之前调用openDebug
21 | ARouter.openDebug();
22 | ARouter.openLog();
23 | }
24 | ARouter.init(this);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/module_one/src/main/java/com/senon/module_one/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_one;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.widget.TextView;
6 |
7 | import com.alibaba.android.arouter.facade.annotation.Autowired;
8 | import com.alibaba.android.arouter.facade.annotation.Route;
9 | import com.alibaba.android.arouter.launcher.ARouter;
10 | import com.senon.lib_common.ConstantLoginArouter;
11 | import com.senon.lib_common.bean.Login;
12 | import com.senon.lib_common.utils.ComUtil;
13 | import com.senon.lib_common.utils.StatusBarUtils;
14 |
15 | /**
16 | * one 模块主页面
17 | */
18 | @Route(path = ConstantLoginArouter.PATH_ONE_MAINACTIVITY)
19 | public class MainActivity extends AppCompatActivity {
20 |
21 | @Autowired
22 | Login data;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | StatusBarUtils.with(this).init();//沉浸式
28 | setContentView(R.layout.one_activity_main);
29 | ComUtil.changeStatusBarTextColor(this,true);
30 |
31 | ARouter.getInstance().inject(this);
32 |
33 | if(data == null){
34 | ((TextView)findViewById(R.id.main_tv)).setText("这是one模块 主页面MainActivity"+"\n没有携带参数: ");
35 | }else{
36 | ((TextView)findViewById(R.id.main_tv)).setText("这是one模块 主页面MainActivity"+"\n携带参数: "+data.toString());
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/module_one/src/main/java/com/senon/module_one/TestActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_one;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.View;
6 |
7 | import com.alibaba.android.arouter.facade.annotation.Route;
8 | import com.alibaba.android.arouter.launcher.ARouter;
9 | import com.senon.lib_common.ConstantArouter;
10 | import com.senon.lib_common.ConstantLoginArouter;
11 | import com.senon.lib_common.utils.StatusBarUtils;
12 |
13 | /**
14 | * one test页面
15 | */
16 | public class TestActivity extends AppCompatActivity {
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | StatusBarUtils.with(this).init();
22 | setContentView(R.layout.one_activity_test);
23 |
24 | }
25 |
26 | public void toA(View view){
27 | ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)//指定跳到那个页面
28 | .withString("targetUrl", ConstantLoginArouter.PATH_ONE_MAINACTIVITY)//传入目标页面路由地址 可以在指定页面跳入到目标页面
29 | .navigation();
30 |
31 | }
32 |
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/module_one/src/main/release/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/module_one/src/main/res/drawable/one_ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/module_one/src/main/res/layout/one_activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/module_one/src/main/res/layout/one_activity_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/module_one/src/main/res/mipmap-xhdpi/one_ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/module_one/src/main/res/mipmap-xhdpi/one_ic_launcher.png
--------------------------------------------------------------------------------
/module_one/src/main/res/mipmap-xhdpi/one_ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/module_one/src/main/res/mipmap-xhdpi/one_ic_launcher_round.png
--------------------------------------------------------------------------------
/module_one/src/main/res/mipmap-xxhdpi/one_ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/module_one/src/main/res/mipmap-xxhdpi/one_ic_launcher.png
--------------------------------------------------------------------------------
/module_one/src/main/res/mipmap-xxhdpi/one_ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/module_one/src/main/res/mipmap-xxhdpi/one_ic_launcher_round.png
--------------------------------------------------------------------------------
/module_one/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/module_one/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | module_one
3 |
4 |
--------------------------------------------------------------------------------
/module_one/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/module_one/src/test/java/com/senon/module_one/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_one;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/module_two/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/module_two/build.gradle:
--------------------------------------------------------------------------------
1 | if (isBuildModule.toBoolean()) {
2 | apply plugin: 'com.android.application'
3 | } else {
4 | apply plugin: 'com.android.library'
5 | }
6 |
7 | android {
8 | compileSdkVersion rootProject.ext.android["compileSdkVersion"]
9 |
10 | resourcePrefix "two_"
11 |
12 | sourceSets {
13 | main {
14 | if (isBuildModule.toBoolean()) {
15 | manifest.srcFile 'src/main/debug/AndroidManifest.xml'
16 | } else {
17 | manifest.srcFile 'src/main/release/AndroidManifest.xml'
18 | java {
19 | //全部Module一起编译的时候剔除debug目录
20 | exclude '**/**/debug/**'
21 | }
22 | }
23 | }
24 | }
25 |
26 | defaultConfig {
27 | if (isBuildModule.toBoolean()) {
28 | applicationId "com.senon.module_one"
29 | }
30 | minSdkVersion rootProject.ext.android["minSdkVersion"]
31 | targetSdkVersion rootProject.ext.android["targetSdkVersion"]
32 | versionCode rootProject.ext.android["versionCode"]
33 | versionName rootProject.ext.android["versionName"]
34 |
35 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
36 | javaCompileOptions {
37 | annotationProcessorOptions {
38 | arguments = [AROUTER_MODULE_NAME: project.getName()]
39 | }
40 | }
41 |
42 | }
43 |
44 | buildTypes {
45 | release {
46 | minifyEnabled false
47 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
48 | }
49 | }
50 |
51 | }
52 |
53 | dependencies {
54 | implementation fileTree(dir: 'libs', include: ['*.jar'])
55 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
56 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
57 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
58 | testImplementation rootProject.ext.dependencies["junit"]
59 |
60 | api project(':lib_common')
61 | annotationProcessor rootProject.ext.dependencies["router-compiler"]
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/module_two/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/module_two/src/androidTest/java/com/senon/module_two/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_two;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.senon.module_two", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/module_two/src/main/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/module_two/src/main/java/com/senon/module_two/App_Two.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_two;
2 |
3 | import com.alibaba.android.arouter.launcher.ARouter;
4 | import com.senon.lib_common.base.BaseApplication;
5 | import com.senon.lib_common.utils.ConstantUtils;
6 |
7 | /**
8 | * two debug Application
9 | */
10 | public class App_Two extends BaseApplication {
11 | @Override
12 | public void onCreate() {
13 | super.onCreate();
14 |
15 | initARouter();
16 | }
17 |
18 | private void initARouter() {
19 | if (ConstantUtils.isAppDebug()) {
20 | //开启InstantRun之后,一定要在ARouter.init之前调用openDebug
21 | ARouter.openDebug();
22 | ARouter.openLog();
23 | }
24 | ARouter.init(this);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/module_two/src/main/java/com/senon/module_two/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_two;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.widget.TextView;
6 | import com.alibaba.android.arouter.facade.annotation.Autowired;
7 | import com.alibaba.android.arouter.facade.annotation.Route;
8 | import com.alibaba.android.arouter.launcher.ARouter;
9 | import com.senon.lib_common.ConstantLoginArouter;
10 | import com.senon.lib_common.bean.Login;
11 | import com.senon.lib_common.utils.ComUtil;
12 | import com.senon.lib_common.utils.StatusBarUtils;
13 |
14 | /**
15 | * two 模块主页面
16 | */
17 | @Route(path = ConstantLoginArouter.PATH_TWO_MAINACTIVITY)
18 | public class MainActivity extends AppCompatActivity {
19 |
20 | @Autowired
21 | Login data;
22 |
23 | @Override
24 | protected void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | StatusBarUtils.with(this).init();//沉浸式
27 | setContentView(R.layout.two_activity_main);
28 | ComUtil.changeStatusBarTextColor(this,true);
29 |
30 | ARouter.getInstance().inject(this);
31 |
32 | if(data == null){
33 | ((TextView)findViewById(R.id.main_tv)).setText("这是two模块 主页面MainActivity"+"\n没有携带参数: ");
34 | }else{
35 | ((TextView)findViewById(R.id.main_tv)).setText("这是two模块 主页面MainActivity"+"\n携带参数: "+data.toString());
36 | }
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/module_two/src/main/java/com/senon/module_two/TestActivity.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_two;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.View;
6 |
7 | import com.alibaba.android.arouter.launcher.ARouter;
8 | import com.senon.lib_common.ConstantLoginArouter;
9 | import com.senon.lib_common.utils.StatusBarUtils;
10 |
11 | /**
12 | * one test页面
13 | */
14 | public class TestActivity extends AppCompatActivity {
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | StatusBarUtils.with(this).init();
20 | setContentView(R.layout.two_activity_test);
21 |
22 | }
23 |
24 | public void toA(View view){
25 | ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)//指定跳到那个页面
26 | .withString("targetUrl", ConstantLoginArouter.PATH_TWO_MAINACTIVITY)//传入目标页面路由地址 可以在指定页面跳入到目标页面
27 | .navigation();
28 |
29 | }
30 |
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/module_two/src/main/release/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/module_two/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/module_two/src/main/res/layout/two_activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/module_two/src/main/res/layout/two_activity_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/module_two/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/module_two/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/module_two/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/module_two/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/module_two/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/module_two/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/module_two/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senonwx/ModularApp/2e028761a531d0c3ed76dc4dc21c1bdc177c8e0d/module_two/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/module_two/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/module_two/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | module_two
3 |
4 |
--------------------------------------------------------------------------------
/module_two/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/module_two/src/test/java/com/senon/module_two/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.senon.module_two;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':lib_opensource', ':lib_common', ':module_one', ':module_two'
2 |
--------------------------------------------------------------------------------