上一篇MonkeyLei:Android-模塊化、組件化、插件化、熱修復-組件化一下試試 我們大概嘗試了下一個Module的library與application切換。這也是為為后續的繼續做準備...今天我們就嘗試自己搭建一個組件化工程,并初步做一個頁面的跳轉(組件間的通信其中一個點),后續還會完善組件間相互通信的方式。
工程實踐完后,我會設置下Module的狀態(Library和Module直接做切換),然后單獨運行App或者Module,如果都沒問題,這才能保證組件之間無耦合!!!
工程走起!
1. 公共庫Module一般作為Library使用。而組件Module我們可以來回切換,但是我們新建Module的時候還是如下方式(保證有啟動的manifest配置):
2. 然后按照上一篇學到的知識,代碼配置下Module的Library和Application切換;然而為了方便統一管理App基礎信息,各個Module的版本信息,以及第三方依賴庫的版本信息等,我們項目根目錄下新建一個config.gradle,專門用來配置:
config.gradle
/**
* 全局統一配置
*/
ext {
/**
* module開關統一聲明在此處
* true:module作為application,可單獨打包為apk
* false:module作為library,可作為宿主application的組件
*/
isLoginModule = false
isPersonalModule = false
/**
* 版本統一管理
*/
versions = [
applicationId : "com.skl.zujianhua", // 應用ID
versionCode : 1, // 版本號
versionName : "1.0.0", // 版本名稱
compileSdkVersion : 28,
minSdkVersion : 15,
targetSdkVersion : 28,
buildToolsVersion : "29.0.0",
constraintlayoutVersion: "1.1.3",
runnerVersion : "1.0.2",
espressoVersion : "3.0.2",
junitVersion : "4.12",
appcompatVersion : "28.0.0",
arouterApiVersion : "1.5.0",
arouterCompilerVersion : "1.2.2",
]
dependencies = [
"appcompat" : "com.android.support:appcompat-v7:${versions["appcompatVersion"]}",
"constraintlayout": "com.android.support.constraint:constraint-layout:${versions["constraintlayoutVersion"]}",
"runner" : "com.android.support.test:runner:${versions["runnerVersion"]}",
"espresso_core" : "com.android.support.test.espresso:espresso-core:${versions["espressoVersion"]}",
"junit" : "junit:junit:${versions["junitVersion"]}",
// TODO MD等新增支持庫
// //注釋處理器
// "support_annotations" : "com.android.support:support-annotations:${versions["annotationsVersion"]}",
// "design" : "com.google.android.material:material:${versions["designVersion"]}",
// TODO 其他公共的依賴都可以配置到這里
// //方法數超過65535解決方法64K MultiDex分包方法
// "multidex" : "androidx.multidex:multidex:2.0.0",
//阿里路由
"arouter_api" : "com.alibaba:arouter-api:${versions["arouterApiVersion"]}",
"arouter_compiler": "com.alibaba:arouter-compiler:${versions["arouterCompilerVersion"]}",
// "arouter_annotation" : "com.alibaba:arouter-annotation:${versions["arouterAnnotationVersion"]}",
//
// //黃油刀
// "butterknife" : "com.jakewharton:butterknife:${versions["butterknifeVersion"]}",
// "butterknife_compiler": "com.jakewharton:butterknife-compiler:${versions["butterknifeVersion"]}"
]
}
2.1 根目錄下的build.gradle下添加config配置:
apply from: "config.gradle"
3. 此時我們不想每個Library/Application用到第三方庫(比如Butterknife、Arouter、MultiDex等)都去依賴,因此我們新建一個基礎模塊basemodule: - (Arouter實踐過了,所以就一并貼出來算了。不過我們的學習過程一般都是漸進式的,先實現基礎工程,模塊的構建,完事三方依賴都配置好,切換都測試成功了,然后再開始搞路由!)
重點看下build.gradle配置:
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
buildToolsVersion "29.0.0"
defaultConfig {
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 把implementation 用api代替,它是對外部公開的, 所有其他的module就不需要添加該依賴
api rootProject.ext.dependencies["appcompat"]
api rootProject.ext.dependencies["constraintlayout"]
api rootProject.ext.dependencies["junit"]
api rootProject.ext.dependencies["runner"]
api rootProject.ext.dependencies["espresso_core"]
// //注釋處理器,butterknife所必需
// api rootProject.ext.dependencies["support_annotations"]
//
// //MultiDex分包方法
// api rootProject.ext.dependencies["multidex"]
//
// //Material design
// api rootProject.ext.dependencies["design"]
//
// //黃油刀
// api rootProject.ext.dependencies["butterknife"]
// annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
//Arouter路由
annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
api rootProject.ext.dependencies["arouter_api"]
// api rootProject.ext.dependencies["arouter_annotation"]
}
4. 然后接著我們創建Appliaction模塊Login和Personal,這樣創建出來就直接配置上了,然后單獨可以運行啦,記得都依賴上basemodule - 后續的公共模塊都可以放到basemodule中去!
4.1 然后根據之前的知識配置下和Library的切換: - 參數都是根目錄/congig.gradle配置的,別忘記了
login/build.gradle
if (Boolean.valueOf(rootProject.ext.isLoginModule)) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
// TODO 雖然依賴了公共庫,但是有些配置還是要模塊內部自己配置
// apply plugin: 'com.jakewharton.butterknife'
android {
compileSdkVersion 28
buildToolsVersion "29.0.0"
defaultConfig {
// Application模式下設置applicationId
if (Boolean.valueOf(rootProject.ext.isLoginModule)) {
applicationId "com.skl.login"
}
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
if (Boolean.valueOf(rootProject.ext.isLoginModule)) {
manifest.srcFile 'src/main/AndroidManifest.xml'
} else {
// Library模式可以不用配置manifest文件
}
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 公共依賴庫
implementation project(path: ':basemodule')
// TODO 雖然依賴了公共庫,但是有些配置還是要模塊內部自己配置
// //黃油刀
// annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
//Arouter路由
annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
}
personal/build.gradle
if (Boolean.valueOf(rootProject.ext.isPersonalModule)) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
// TODO 雖然依賴了公共庫,但是有些配置還是要模塊內部自己配置
// apply plugin: 'com.jakewharton.butterknife'
android {
compileSdkVersion 28
buildToolsVersion "29.0.0"
defaultConfig {
// Application模式下設置applicationId
if (Boolean.valueOf(rootProject.ext.isLoginModule)) {
applicationId "com.skl.personal"
}
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
if (Boolean.valueOf(rootProject.ext.isPersonalModule)) { // apk
manifest.srcFile 'src/main/AndroidManifest.xml'
} else {
// Library模式可以不用配置manifest文件
}
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 公共依賴庫
implementation project(path: ':basemodule')
// TODO 雖然依賴了公共庫,但是有些配置還是要模塊內部自己配置
// //黃油刀
// annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
//Arouter路由
annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
}
5. 修改下app主模塊下的布局,做一個點擊按鈕事件,分別用來跳轉到login和personal頁面:
app/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="GoLogin"
android:text="跳轉到Login界面"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="GoPersonal"
android:text="跳轉到個人信息頁面"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
package com.skl.zujianhua;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.alibaba.android.arouter.launcher.ARouter;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 跳轉到登錄頁面
*
* @param view
*/
public void GoLogin(View view) {
// 跳轉方式1: 通過反射
// try {
// Class clazz = Class.forName("com.skl.login.LoginActivity");
// Intent intent = new Intent(this, clazz);
// startActivity(intent);
// // startActivityForResult(intent, 110);
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// }
// 跳轉方式2:每個頁面都注冊到base模塊,由base模塊提供跳轉服務
// CompomentsService.getiAppComponentHashMap(AppConfig.PAGE_TYPE.LOGIN).launch(this, null);
// 跳轉方式3:采用URI方式
// startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("activity://login")));
// 跳轉方式4:采用 Arouter
ARouter.getInstance().build("/hl/login")
// .withString("nothing", "Gone with the Wind")
// .withObject("author", Object)
.navigation(this, 110);
}
/**
* 跳轉到個人中心
*
* @param view
*/
public void GoPersonal(View view) {
// 跳轉方式4:采用 Arouter
ARouter.getInstance().build("/ppx/personal")
// .withString("nothing", "Gone with the Wind")
// .withObject("author", Object)
.navigation(this, 110);
}
}
5.1 上面分別列出了四種跳轉方式,首先反射的方式,這個要試試哈。記得頁面是需要配置到AndroidManifest.xml的喲。
5.2 先說跳轉方式3, URI的方式,這個需要配置待跳轉頁面的scheme、host、action、category信息,然后跳轉時根據scheme和host做路由:
login/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.skl.login">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".LoginActivity">
<!--跳轉方式3:提供URI方式-->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="activity" />
<data android:host="login" />
</intent-filter>
</activity>
</application>
</manifest>
然后 startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("activity://login")));就可以跳轉了啦.....
5.3 接著說跳轉方式4 ,ARouter的方式,github地址,上面配置方式都有啦:alibaba/ARouter
照著配置就行,不過要注意我們有basemodule,多個library,so,注意下面這個說明: - javaCompileOptions比較關鍵,不然你的路由就會報="http://www.baidu.com/link?url=SFoQYEc0VH3o8IZkDe1H0v2W30NKqGHpsDU24PfR5pLn_c7GdXgkmO8moxxq7YGDO8VFzM4u0FFIwpTv25xIgKeKXK3YTN6DS8bTFKQuthy">ARouter there's no route matched
雖然我們basemodule采用api的方式引入了arouter:
basemodule/build.gradle
//Arouter路由
annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
api rootProject.ext.dependencies["arouter_api"]
但是其他的Module需要使用的地方同樣需要添加如下配置:
login/build.gradle
personal/build.gradle
android {
compileSdkVersion 28
buildToolsVersion "29.0.0"
defaultConfig {
......
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
.....
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 公共依賴庫
implementation project(path: ':basemodule')
// TODO 雖然依賴了公共庫,但是有些配置還是要模塊內部自己配置
// //黃油刀
// annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
// Arouter路由
annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
}
5.3.1 然后我們的login,personal都配置上路由信息,方便路由跳轉(其他用法待深入) - 路由配置注意:不同module的路由路徑的一級命名不能相同。
login/ LoginActivity.java
package com.skl.login;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.alibaba.android.arouter.facade.annotation.Route;
@Route(path = "/hl/login")
public class LoginActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
}
/**
* 登錄 + 可以保存數據到本地(采用sharedpreferences的方式存儲)
* TODO 注意:這里為了模擬組件間的接口調用,采用其他方式
* @param view
*/
public void logining(View view) {
}
}
personal/PersonalActivity.java
package com.skl.personal;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.alibaba.android.arouter.facade.annotation.Route;
@Route(path = "/ppx/personal")
public class PersonalActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_personal);
}
/**
* 獲取登錄頁面個人信息并展示
* @param view
*/
public void getLoginInfo(View view) {
}
}
然后開始路由前,主模塊app下的MainApplication需要初始化路由組件 - 直接文檔添加過來稍加處理就行
// ARouter路由初始化
if (BuildConfig.DEBUG) { // These two lines must be written before init, otherwise these configurations will be invalid in the init process
ARouter.openLog(); // Print log
ARouter.openDebug(); // Turn on debugging mode (If you are running in InstantRun mode, you must turn on debug mode! Online version needs to be closed, otherwise there is a security risk)
}
ARouter.init(this); // As early as possible, it is recommended to initialize in the Application
5.3.2 此時就可以進行路由跳轉了呀
// 跳轉方式4:采用 Arouter
ARouter.getInstance().build("/hl/login")
// .withString("nothing", "Gone with the Wind")
// .withObject("author", Object)
.navigation(this, 110);
6. 最后跳轉方式2,這里采用下沉到base模塊的方式,各個組件注冊到base模塊的服務頁面,然后由各個模塊提供lunch方法。其他模塊使用的時候只需要調用base模塊的注冊的組件對應的lunch方法既可!這個就主要涉及到接口的使用了。
處理方式:6.1 定義IAppComponent接口
package com.skl.basemodule.common_interface;
import android.app.Application;
import android.content.Context;
/**
* 組件Application初始化時需要實現的接口
*/
public interface IAppComponent {
void initialize(Application app);
void launch(Context context, String extra);
}
6.2 此時就需要各個模塊添加Application類(basemodule純粹是一個library,不參與),然后統一由主Application去調用各個模塊的initialize方法(這個時候模塊Library要注意,如果不涉及到單獨運行,不用去配置application,不然運行報錯啦),如下:
6.3 主模塊此時由于不能直接與其他模塊產生耦合,所以采用反射的方式去初始化各個組件的Application:
實現之前先定義一個basemodule/AppConfig.java用來存儲組件信息: - 我采用的接口和其他人略有不同,主要是方便到時候根據枚舉進行頁面注冊,同時根據枚舉進行頁面跳轉,后面就知道了
package com.skl.basemodule;
import java.util.HashMap;
public class AppConfig {
public enum PAGE_TYPE {
LOGIN, PERSONAL
}
/**
* 組件集合
*/
public static HashMap<PAGE_TYPE, String> COMPONENTS = new HashMap<PAGE_TYPE, String>() {
{
// 登錄頁面
put(PAGE_TYPE.LOGIN, "com.skl.login.LoginApplication");
// 登錄頁面
put(PAGE_TYPE.PERSONAL, "com.skl.login.PersonalApplication");
}
};
}
app/src/main/xxxxx/MainApplication.java - MainApplication也實現組件通信的接口IAppComponent,其他頁面有可能也需要跳轉到主頁面
package com.skl.zujianhua;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import com.alibaba.android.arouter.launcher.ARouter;
import com.skl.basemodule.AppConfig;
import com.skl.basemodule.common_interface.IAppComponent;
import java.util.Map;
public class MainApplication extends Application implements IAppComponent {
@Override
public void onCreate() {
super.onCreate();
initialize(this);
}
@Override
public void initialize(Application app) {
// 遍歷所有的組件的Application類,依次用反射的方式實現組件初始化和注冊
for(Map.Entry<AppConfig.PAGE_TYPE, String> entry: AppConfig.COMPONENTS.entrySet())
{
try {
Class classz = Class.forName(entry.getValue());
Object object = classz.newInstance();
// 實例化后,調用各個組件的initialize方法(init會實現組件的注冊)
if (object instanceof IAppComponent) {
((IAppComponent) object).initialize(app);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// ARouter路由初始化
if (BuildConfig.DEBUG) { // These two lines must be written before init, otherwise these configurations will be invalid in the init process
ARouter.openLog(); // Print log
ARouter.openDebug(); // Turn on debugging mode (If you are running in InstantRun mode, you must turn on debug mode! Online version needs to be closed, otherwise there is a security risk)
}
ARouter.init(this); // As early as possible, it is recommended to initialize in the Application
}
@Override
public void launch(Context context, String extra) {
Intent intent = new Intent(context, MainActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
Bundle bundle = new Bundle();
if (null != extra && !extra.equals(""))
bundle.putString("extra_data", extra);
context.startActivity(intent, bundle);
} else {
if (null != extra && !extra.equals(""))
intent.putExtra("extra_data", extra);
context.startActivity(intent);
}
}
}
6.4 為了實現組件Application初始化,并且能全局存儲組件的信息,我們定一個組件服務類CompomentsService.java - 注冊組件時根據枚舉存儲組件信息,同時提供了獲取組件(類型就是通信接口IAppComponent )
package com.skl.basemodule;
import com.skl.basemodule.common_interface.IAppComponent;
import java.util.HashMap;
/**
* 組件初始化時都注冊到這個服務里面
*/
public class CompomentsService {
private static HashMap<AppConfig.PAGE_TYPE, IAppComponent> iAppComponentHashMap = new HashMap<>();
public static void setiAppComponentHashMap(AppConfig.PAGE_TYPE componentName, IAppComponent iAppComponent){
iAppComponentHashMap.put(componentName, iAppComponent);
}
public static IAppComponent getiAppComponentHashMap(AppConfig.PAGE_TYPE componentName){
if (iAppComponentHashMap.containsKey(componentName)){
return iAppComponentHashMap.get(componentName);
}
return null;
}
}
6.5 然后此時我們就可以把login、personal模塊初始化并注冊了:
login/ LoginApplication.java - 里面有注釋,相對好理解
package com.skl.login;
/**
* 單獨運行時需要的話可以配置到AndroidManifest,不需要就不要配置,不然運行報錯
*/
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import com.skl.basemodule.AppConfig;
import com.skl.basemodule.CompomentsService;
import com.skl.basemodule.common_interface.IAppComponent;
public class LoginApplication extends Application implements IAppComponent {
/**
* 單獨作為Application時會走該方法
*/
@Override
public void onCreate() {
super.onCreate();
// TODO 單獨運行時沒有需要可以不用調用
initialize(this);
}
/**
* App的Application注冊組件時會調用initialize方法!
*
* @param app
*/
@Override
public void initialize(Application app) {
// 注冊自己到組件服務
CompomentsService.setiAppComponentHashMap(AppConfig.PAGE_TYPE.LOGIN, this);
}
/**
* 啟動自己
*
* @param context
* @param extra
*/
@Override
public void launch(Context context, String extra) {
Intent intent = new Intent(context, LoginActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
Bundle bundle = new Bundle();
if (null != extra && !extra.equals(""))
bundle.putString("extra_data", extra);
context.startActivity(intent, bundle);
} else {
if (null != extra && !extra.equals(""))
intent.putExtra("extra_data", extra);
context.startActivity(intent);
}
}
}
personal/PersonalApplication.java
package com.skl.personal;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import com.skl.basemodule.AppConfig;
import com.skl.basemodule.CompomentsService;
import com.skl.basemodule.common_interface.IAppComponent;
/**
* 單獨運行時需要的話可以配置到AndroidManifest,不需要就不要配置,不然運行報錯
*/
public class PersonalApplication extends Application implements IAppComponent {
/**
* 單獨作為Application時會走該方法
*/
@Override
public void onCreate() {
super.onCreate();
// TODO 單獨運行時沒有需要可以不用調用
initialize(this);
}
/**
* App的Application注冊組件時會調用initialize方法!
*
* @param app
*/
@Override
public void initialize(Application app) {
// 注冊自己到組件服務
CompomentsService.setiAppComponentHashMap(AppConfig.PAGE_TYPE.PERSONAL, this);
}
/**
* 啟動自己
*
* @param context
* @param extra
*/
@Override
public void launch(Context context, String extra) {
Intent intent = new Intent(context, PersonalActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
Bundle bundle = new Bundle();
if (null != extra && !extra.equals(""))
bundle.putString("extra_data", extra);
context.startActivity(intent, bundle);
} else {
if (null != extra && !extra.equals(""))
intent.putExtra("extra_data", extra);
context.startActivity(intent);
}
}
}
7. 完事了我們就可以采用下沉到公共模塊的方式來實現頁面跳轉 - 枚舉方便我們清晰知道要跳轉到哪里。相比Arouter,還是不安逸。但是了解一下也好鴨.....
// 跳轉方式2:每個頁面都注冊到base模塊,由base模塊提供跳轉服務
CompomentsService.getiAppComponentHashMap(AppConfig.PAGE_TYPE.LOGIN).launch(this, null);
8. 大概一個組件化工程目前一天兩天的學習過程和實踐就是醬紫。。。還有很多我們可以去聯想和實踐的,比如頁面之間的相互通信,主動回調通知刷新等。以及Eventbus相關集成,如何集成的更好,其他的路由通信方式等等一堆問題!。。。。
組件化如果產生了耦合就尷尬了,這就是設計的魅力!
附上工程地址吧: https://gitee.com/heyclock/doc/tree/master/組件化
一些個參考:可以多像網友學習,但是還是要有自己的想法,哪怕改成自己順手都是可以的,可能會實踐的不好也沒關系,至少大的方向應該是對的了。。
https://blog.csdn.net/jiyidehao/article/details/85390370
https://blog.csdn.net/sziitjin/article/details/97761949
https://blog.csdn.net/hailong0529/article/details/89392064
https://blog.csdn.net/gaolei1201/article/details/77601027 - 如何跳轉頁面的方式