ARouter - Step by step完整代码上手(1)
1. ARouter干啥用?
ARouter是阿里开发的一个Android库,通过组件路由的方式帮助模块之间解耦依赖。
1.1 依赖如何产生
Android应用模块以activity和service为主,它们之间的调用以intent方式为主。虽然activity之间调用可以用过隐式依赖(AndroidManifest中声明intent-filter)的方式进行调用,这种方式主要是针对公共接口。应用内部的模块之间的依赖(通过显式intent调用)比公共接口数量要多很多。用intent需要知道package、class等信息,这样就产生了依赖关系。
1.2 带来的问题
第一,依赖可能会比较多,导致逻辑复杂,维护困难。尤其是规模比较大的复杂应用,模块之间的依赖数量会非常多,几十、几百都是可能的。
第二,一个应用的代码总是不停改动,就像人活着总是要新陈代谢一样。不可避免的要重构代码,修改报名、拆分(或合并)类等,这样被依赖方变了,依赖方也要相应的改变。
第三,实际工作中,不同的模块是由不同部门的团队维护的,比如账号管理模块、商品信息模块、推荐算法模块等,要把变更信息同步给不同团队,还要保证相关模块同时修改、上线,实际操作起来有难度。
这些问题对大型应用开发带来了不小的挑战,实际上会更加复杂,包括人员变动、业务调整等。
1.3 如何解决
- 给被依赖的模块设置一个字符串名称(例如: /activity/login),依赖方通过字符串名称调用。被依赖方无论怎么修改(字符串名称不变)都不影响调用,起到了解耦的作用。
- 需要有一个管理者(ARouter库)维护名称和模块(activity、service)之间的映射关系。
- 还提供了数据传递的方式,调用过程中传入和返回参数都可以支持。
- 调用过程中,通过拦截器模式,在调用过程中增加处理逻辑,更好的控制模块间依赖。
- 通过依赖注入和注解等方式,管理对应创建、方便代码实现。
2. 使用intent调用activity
1)MainActivity中有一个按钮,点击按钮通过intent调用OtherActivity。
2)这个主要是和使用ARouter做对比,一带而过直接看下一部分。
// MainActivity.java
package com.kaola.arouter_test;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = findViewById(R.id.btn_start);
btn.setOnClickListener((View v) -> {
Intent i = new Intent(MainActivity.this, OtherActivity.class);
startActivity(i);
});
findViewById(R.id.btn_finish).setOnClickListener((View v) -> {
finish();
});
}
}
<!--activity_main.xml-->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/tv_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Main activity!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_start"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_margin="20dp"
android:text="start"
app:layout_constraintTop_toBottomOf="@id/tv_main"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<Button
android:id="@+id/btn_finish"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_margin="20dp"
android:text="finish"
app:layout_constraintTop_toBottomOf="@id/btn_start"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
// OtherActivity.java
package com.kaola.arouter_test;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class OtherActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
Button btn = findViewById(R.id.btn_other);
btn.setOnClickListener((View v) -> {
finish();
});
}
}
<!--activity_other.xml-->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/tv_other"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Other activity!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_other"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_margin="20dp"
android:text="finish"
app:layout_constraintTop_toBottomOf="@id/tv_other"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<!--AndroidManifest.xml-->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.kaola.arouter_test">
<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/Theme.Arouter_test">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".OtherActivity" android:exported="true"/>
</application>
</manifest>
3. 通过ARoute调用activity
3.1 主要修改说明
1)在build.gradle中引入ARoute依赖。
2)自定义一个Application,用于初始化ARouter。
ARouter是一个基础服务的角色,所以需要在应用中尽早启动,才能为其他模块提供服务。而且生命周期要长久,在Application中初始化比较合适。
3)在AndroidManifest.xml中指定自定义的Application。
4)OtherActivity是被依赖方、被调用方:
4.1 )通过@Route注解指定path(名称):@Route(path=“/activity/other”),路径至少要2级。
4.2)在onCreate()中通过ARouter注入:ARouter.getInstance().inject(this)。
4.3)通过@Autowired注解(面熟吗?)引用传入的参数: @Autowired(name = “msg”)。
5)MainActivity是调用方:
5.1)通过ARouter调用OtherActivity
ARouter.getInstance().build(“/activity/other”) // OtherActivity中设置的路径名
.withString(“msg”, “Tesla price-off a…gain~”) // 传递给OtherActivity的参数
.navigation(); // 启动activity
3.2 build.gradle修改
android {
defaultConfig {
// 其他内容忽略
// arouter
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
}
dependencies {
// 其他不相干内容忽略
// arouter
implementation 'com.alibaba:arouter-api:1.5.2'
annotationProcessor 'com.alibaba:arouter-compiler:1.5.2'
}
3.3 自定义Application
package com.kaola.arouter_test;
import android.app.Application;
import com.alibaba.android.arouter.launcher.ARouter;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 初始化ARouter
ARouter.openLog();
ARouter.openDebug();
ARouter.init(this);
}
}
3.4 修改AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.kaola.arouter_test">
<application
android:name=".MyApplication" <--- 自定义的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/Theme.Arouter_test">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".OtherActivity" android:exported="true"/>
</application>
</manifest>
3.5 修改OtherActivity.java
package com.kaola.arouter_test;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
@Route(path="/activity/other") // 1. 通过@Route注解声明调用路径
public class OtherActivity extends AppCompatActivity {
@Autowired(name = "msg") // 2. 通过@Autowired注解,注入传入的变量
String message;
@Autowired(name = "price_off")
int off;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
ARouter.getInstance().inject(this); // 3. 把OtherActivity注入到ARoute框架中,让其他模块可以调用
Button btn = findViewById(R.id.btn_other);
btn.setOnClickListener((View v) -> {
finish();
});
TextView text = findViewById(R.id.tv_other);
text.setText("Other activity get: msg:" + message + ", by " + off);
}
}
3.6 修改MainActivity.java
package com.kaola.arouter_test;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
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);
Button btn = findViewById(R.id.btn_start);
btn.setOnClickListener((View v) -> {
// Intent i = new Intent(MainActivity.this, OtherActivity.class);
// startActivity(i);
// 上面是普通的intent方式调用,下面是通过ARouter来调用,不依赖任何报名、类名
ARouter.getInstance().build("/activity/other")
.withString("msg", "Tesla price-off a...gain~")
.withInt("price_off", 50000)
.navigation();
});
findViewById(R.id.btn_finish).setOnClickListener((View v) -> {
finish();
});
}
}
到这里我们了解了ARouter引入的背景、要解决的问题,对在实际开发中如何使用ARouter有了一个初步的认识。
后续文章中会说明ARouter的详细用法,以及关联的原理知识。
还没有评论,来说两句吧...