目录
书接上回Android组件化基础(一)——概述与基本配置-CSDN博客
组件化后,不同组件之间没有相互依赖,模块间的跳转就不能再通过 startActivity() 这种方式,比较常用的是阿里的 ARouter 路由框架,GitHub 的项目主页上对于使用方法介绍的已经很详细,这里我们就简单说说。
导入依赖
首先我们在根目录下的config.gradle文件添加依赖
libARouter = "com.alibaba:arouter-api:1.5.2"
libARouterCompiler = "com.alibaba:arouter-compiler:1.5.2"
完整代码
ext{
isRelease = true
androidId = [
compileSdk : 33,
minSdk : 24,
targetSdk : 33,
versionCode : 1,
versionName : "1.0"
]
appId = [
app : "com.example.componentdemo",
first : "com.example.module.first",
second : "com.example.module.second"
]
dependencies = [
"appcompat" : "androidx.appcompat:appcompat:1.4.1",
"material" : "com.google.android.material:material:1.5.0",
"constraintlayout" : "androidx.constraintlayout:constraintlayout:2.1.3",
]
libARouter = "com.alibaba:arouter-api:1.5.2"
libARouterCompiler = "com.alibaba:arouter-compiler:1.5.2"
}
修改基础组件下的build.gradle文件,在dependencies中添加如下依赖
api libARouter
内容补充
api
关键字: 当你使用 api
关键字声明依赖关系时,该依赖会对所有的模块可见,并会被传递到依赖该模块的其他模块。换句话说,如果 Module A 使用了 api
关键字引入 Module B,那么Module A 的依赖模块也能访问 Module B。
implementation
关键字: 当你使用 implementation
关键字声明依赖关系时,该依赖只对当前模块可见,并不会被传递到依赖该模块的其他模块。这样可以避免将不必要的依赖泄漏到其他模块中。
修改所有使用到路由跳转的组件的build.gradle文件
首先添加如下代码
javaCompileOptions {
annotationProcessorOptions {
// 当前模块名作为参数
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
因为 ARouter 是利用 APT 技术通过自动生成代码建立路由表从而支持模块间跳转的,因此模块中如果有 Activity/Fragment 需要加入路由表时,就需要为其加上注解,并由注解处理器扫描后才能被添加到路由表中,而建立路由表时需要用模块名作为参数,所以才需要用 javaCompileOptions -> annotationProcessorOptions 这种形式将模块名传递给注解处理器。
接下来导入依赖
annotationProcessor 'com.alibaba:arouter-compiler:1.5.2'
补充说明:
annotationProcessor
和api
是Gradle中的两种不同的依赖声明方式。
annotationProcessor: 用于声明注解处理器的依赖。注解处理器通常用于在编译时生成代码,例如在使用ARouter时,
libARouterCompiler
可能是一个用于生成路由映射表的注解处理器。因此,它通常不会直接影响到应用程序的运行时依赖。api: 用于声明在编译时和运行时都需要的依赖。当你使用
api
关键字引入依赖时,这个依赖将会被传递到依赖于你的库或应用程序中。这意味着,如果libARouterCompiler
是一个用于编译时生成代码的注解处理器,它不应该被声明为api
依赖,因为它只在编译时被使用,而不会直接影响到运行时的依赖。因此,你应该将
libARouterCompiler
声明为annotationProcessor
依赖,而不是api
依赖。
如果你的每个组件都需要使用
libARouterCompiler
进行编译时的注解处理,那么你需要将该依赖声明放在每个组件模块的 Gradle 文件中。但是请确保不要在基础组件将其声明为api
依赖。
以下是app包下的build.gradle文件示例
plugins {
id 'com.android.application'
}
def androidId = rootProject.ext.androidId
def appId = rootProject.ext.appId
def support = rootProject.ext.dependencies
android {
namespace 'com.example.componentdemo'
compileSdk androidId.compileSdk
defaultConfig {
applicationId appId.app
minSdk androidId.minSdk
targetSdk androidId.targetSdk
versionCode androidId.versionCode
versionName androidId.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
// 当前模块名作为参数
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
if (isRelease){
implementation project(":moduleCore:first")
implementation project(":moduleCore:second")
}
implementation project(":moduleBase:libBase")
annotationProcessor 'com.alibaba:arouter-compiler:1.5.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
本文还需要修改first和second包下的build.gradle文件
初始化ARouter的SDK
在app下即主工程的入口MainActivity的包新建一个类
package com.example.componentdemo;
import android.app.Application;
import com.alibaba.android.arouter.BuildConfig;
import com.alibaba.android.arouter.launcher.ARouter;
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG){
ARouter.openLog();
ARouter.openDebug();
}
ARouter.init(this);
}
}
然后修改AndroidMenifest文件的application内容,
android:name=".BaseApplication"
使用 ARouter 进行跳转
在活动中添加注解
设置跳转事件
(这是主活动的)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build("/first/FirstActivity").navigation();
}
});
textView2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build("/second/SecondActivity").navigation();
}
});
}
这是FirstActivity的
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
textView = (TextView) findViewById(R.id.first);
message = (TextView) findViewById(R.id.text1);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build("/second/SecondActivity").navigation();
}
});
}
如果发现活动无法跳转或是报错,可以尝试在根目录下的 gradle.properties文件添加改行代码
android.enableJetifier=true
android.enableJetifier=true
是一个Gradle属性,用于在构建过程中启用Jetifier。Jetifier是一个工具,用于将旧版的Android Support库依赖转换为适用于AndroidX的新版依赖,这样可以使项目能够与AndroidX兼容。启用Jetifier可以确保项目中的所有依赖都与AndroidX兼容,而不仅仅是直接依赖的库。
组件间的通信
携带参数跳转
跳转启动方:FirstActivity
ARouter.getInstance().build("/second/SecondActivity")
.withString("from","FirstActivity :")
.withString("key","Hello! Here is FirstActivity!")
.navigation();
参数接收方:SecondActivity
@Route(path = "/second/SecondActivity")
public class SecondActivity extends AppCompatActivity {
//为每一个参数声明一个字段,并使用@Autowired注解标记
@Autowired(name = "from")
public String from;
@Autowired(name = "key")
public String info;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
...
textView3 = (TextView) findViewById(R.id.info_from);
textView4 = (TextView) findViewById(R.id.info_key);
ARouter.getInstance().inject(this);//自动注入参数
textView3.setText(from);
textView4.setText(info);
...
}
...
}
效果
只传输数据不跳转
首先,在基础组件libBase包下新建一个接口InfoProvider,继承自
IProvider。当然,你也可以新建一个基础组件,新建完成之后记得在使用的组件下导入项目。这里为了方便,选择了前者。
public interface InfoProvider extends IProvider {
int getId();
String getInfo();
}
然后随便在一个组件中实现它,这里我选择在first组件下实现
@Route(path = "/first/MyInfoProvider")
public class MyInfoProvider implements InfoProvider {
@Override
public int getId() {
return 666;
}
@Override
public String getInfo() {
return "Hello World!";
}
@Override
public void init(Context context) {
}
}
然后可以随便选择一个组件去应用
ARouter.getInstance().inject(this);
Toast.makeText(this,"" + provider.getId() + " " + provider.getInfo(),Toast.LENGTH_LONG).show();
ARouter.getInstance().inject(this);
textView5 = (TextView) findViewById(R.id.info_id);
textView6 = (TextView) findViewById(R.id.info_info);
textView5.setText(provider.getId() + "");
textView6.setText(provider.getInfo());
另外, ARouter.getInstance().inject(this)不能为跳转参数和接口同时注入参数,意思是,接待参数跳转和接口不能同时写在一个活动里,至少我为了图方便写在同一个活动时频频报错,分开写时运行成功
本文参考博客:一步步搭建组件化项目&ARouter的使用-CSDN博客Android 组件化基础(一)—— 概述与基本配置_组件化在项目中的意义-CSDN博客