组件化以及apt

本文详细介绍了Android应用的组件化开发,包括组件化的意义、环境自动部署配置、组件与库的区别以及如何在不同环境下切换。通过Gradle配置实现测试和正式环境的隔离,确保组件可以独立运行或集成到app壳中。此外,文章还探讨了组件间交互的多种方式,如EventBus、广播、隐士意图和类加载。最后提到了APT技术在生成代码和项目部署中的作用,以及ARouter的原理。
摘要由CSDN通过智能技术生成

转载自享学Derry

1.什么是组件化,为什么需要组件化

组件化意义逻辑图:
 
 
组件化后,所有的 module 都平起平坐,有人说 app module 在组件化中是个壳子,这也是为什么成为app壳工程的原因

 

2.集成环境/组件环境自动部署配置

Gradle 中的 Groovy 其实属于糖果语法,就是弱类型语法,我们来测试下 2.3 :我们在项目的开发过程中,一定要去优化我们的gradle 文件,例如:把公用的内容抽取 2.4 :项目的开发过程中,关于一切与“正式环境 测试环境 相关的应该用 Gradle 进行配置
 
 
Phone Module Android Library 区别、切换 :
 
 
 
组件化开发规范: order order 前缀( src 类 和 res 资源) personal personal 前缀( src 类 和 res 资源)
app 可不改,让它默认
 
组件化开发的临时代码,集成化打包时动态隔离
 
// 配置资源路径,方便测试环境,打包不集成到正式环境 
sourceSets { 
    main {
        if (!isRelease) { // 如果是组件化模式,需要单独运行时 
            manifest.srcFile 'src/main/debug/AndroidManifest.xml'
         } else { 
            // 集成化模式,整个项目打包apk 
            manifest.srcFile 'src/main/AndroidManifest.xml' 
            java {
                // release 时 debug 目录下文件不需要合并到主工程 
                exclude '**/debug/**' 
                } 
            } 
        } 
    }
注意事项: src/main/debug/AndroidManifest.xml 子模块包名/debug/测试代码.java

源码环节: app build.gradle:

 
apply plugin: 'com.android.application'

println("Derry ---> app Student hao 1") println "Derry ---> app Student hao 2"
// 完整的方式 def androidID = rootProject.ext.androidID

android {
    compileSdkVersion androidID.compileSdkVersion
    buildToolsVersion androidID.buildToolsVersion

    defaultConfig {
        applicationId appID.app
        minSdkVersion androidID.minSdkVersion
        targetSdkVersion androidID.targetSdkVersion
        versionCode androidID.versionCode
        versionName androidID.versionName

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        // 给Java代码暴漏,标记,正式环境 和 测试环境 的标记
        // 组件化 和 集成化 的时候需要
        buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
    }

    buildTypes {
        debug {
            buildConfigField("String", "debug", "\"${url.debug}\"")
        }
        release {
            buildConfigField("String", "release", "\"${url.release}\"")

            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-androidoptimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])

    // 300行
    /*implementation "androidx.appcompat:appcompat:1.2.0"
    implementation "androidx.constraintlayout:constraintlayout:2.0.1"
    implementation "com.google.android.material:material:1.1.0"
    implementation "androidx.vectordrawable:vectordrawable:1.1.0"
    implementation "androidx.navigation:navigation-fragment:2.2.2"
    implementation "androidx.navigation:navigation-ui:2.2.2"
    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"*/

    // 一行搞定 300 行
    dependenciesID.each { k, v -> implementation v }
 testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

    // 如果是集成化模式,做发布版本时。各个模块都不能独立运行了
    if (isRelease) {
        // 依附App壳
        implementation project(':login')
        implementation project(':register')
    } else {
        // 不需要做事情,组件环境,不需要依附App壳
    }
}

 

library build.gradle:


println "Derry ---> lib Student hao 2"

// 完整的方式 def androidID = rootProject.ext.androidID

android {
    compileSdkVersion androidID.compileSdkVersion
    buildToolsVersion androidID.buildToolsVersion

    defaultConfig {
        minSdkVersion androidID.minSdkVersion
        targetSdkVersion androidID.targetSdkVersion
        versionCode androidID.versionCode
        versionName androidID.versionName

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-androidoptimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])

    // 300 行
    /*implementation "androidx.appcompat:appcompat:1.2.0"
    implementation "androidx.constraintlayout:constraintlayout:2.0.1"
    implementation "com.google.android.material:material:1.1.0"
    implementation "androidx.vectordrawable:vectordrawable:1.1.0"
    implementation "androidx.navigation:navigation-fragment:2.2.2"
    implementation "androidx.navigation:navigation-ui:2.2.2"
    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"*/

    // 一行搞定 300 行
    dependenciesID.each { k, v -> implementation v }

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' }

 

project build.gradle:

// 根目录下的build.gradle 引入 
apply from : 'derry.gradle'

 

derry.gradle 公共一份gradle:

// 糖果语法

// 扩展快 ext {

    // 正式环境 和 测试环境
    isRelease = true

    // 正式环境 和 测试环境 URL 配置
    url = [
            "debug"  : "https://192.188.22.99/debug",
            "release": "https://192.188.22.99/release"
    ]

    // 建立Map存储,  key 和 value  都是自定义的
    androidID = [
            compileSdkVersion: 30,
            buildToolsVersion: "30.0.1",

            applicationId    : "com.derry.derry",
            minSdkVersion    : 16,
            targetSdkVersion : 30,
            versionCode      : 1,
            versionName      : "1.0",
    ]

    // 建立Map存储,  key 和 value  都是自定义的
    appID = [
            app: "com.derry.derry",
            login: "com.derry.login",
            register: "com.derry.register"
    ]

    // 300
    // 300 行  MAP  key  value
    dependenciesID = [
            "appcompat"       : "androidx.appcompat:appcompat:1.2.0",
            "constraintlayout": 
            "androidx.constraintlayout:constraintlayout:2.0.1",
            "material"        : "com.google.android.material:material:1.1.0",
            "vectordrawable"  : "androidx.vectordrawable:vectordrawable:1.1.0",
            "fragment"        : "androidx.navigation:navigation-fragment:2.2.2",
            "ui"              : "androidx.navigation:navigation-ui:2.2.2",
            "extensions"      : "androidx.lifecycle:lifecycle-extensions:2.2.0",
    ]
}

 

app Java代码区域:

public class NetworkConfig {

    // 测试 服务器 地址
    public static final String DEBUG = "https://192.188.22.99/debug";

    // 正式 服务器 地址
    public static final String RELEAE = "https://192.188.22.99/release"; 
}

 

布局:

<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="进入Login模块"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:onClick="startLoginModel"
        />

 

MainActivity:

public class MainActivity extends AppCompatActivity {

    private final static String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Java中使用  Gradle 配置的 正式 测试 服务器地址
        // 以前
        // NetworkConfig.DEBUG

        String serverURL = BuildConfig.debug;
        Toast.makeText(this, "serverURL:" + serverURL, 
        Toast.LENGTH_SHORT).show();

        // Java代码也能使用  isRelease
        if (BuildConfig.isRelease) {
            Log.d(TAG, "onCreate: 当前是:集成化 线上环境,以app壳为主导运行的方式");
            Toast.makeText(this, "当前是:集成化 线上环境,以app壳为主导运行的方式",                                
            Toast.LENGTH_SHORT).show();
        } else {
            Log.d(TAG, "onCreate: 当前是:组件化 测试环境,所有的子模块都可以独立运行");
            Toast.makeText(this, "当前是:组件化 测试环境,所有的子模块都可以独立运行",         
            Toast.LENGTH_SHORT).show();
        }
    }

    // 从App壳 到 Login模块
    public void startLoginModel(View view) {
        startActivity(new Intent(MainActivity.this, Login_MainActivity.class));
    }
}

 

组件模块 login / register register build.gradle:

// apply plugin: 'com.android.application' 
if (isRelease) { // 如果是发布版本时,各个模块都不能独立运行
    apply plugin: 'com.android.library'  // 不能独立运行
} else {
    apply plugin: 'com.android.application' // 能够独立运行
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.1"

    defaultConfig {
        if (!isRelease) { // 如果是集成化模式,不能有applicationId
            applicationId appID.register // 组件化模式能独立运行才能有applicationId
        }
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-androidoptimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' }

 

login 区域: login build.gradle:


// apply plugin: 'com.android.application' 
if (isRelease) { // 如果是发布版本时,各个模块都不能独立运行
    apply plugin: 'com.android.library'  // 不能独立运行
} else {
    apply plugin: 'com.android.application' // 能够独立运行
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.1"

    defaultConfig {
        if (!isRelease) { // 如果是集成化模式,不能有applicationId
            applicationId appID.login // 组件化模式能独立运行才能有applicationId
        }
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-androidoptimize.txt'), 'proguard-rules.pro'
        }
    }

    // 配置资源路径,方便测试环境,打包不集成到正式环境
    sourceSets {
        main {
            if (!isRelease) {
                // 如果是组件化模式,需要单独运行时
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            } else {
                // 集成化模式,整个项目打包apk
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java {
                    // release 时 debug 目录下文件不需要合并到主工程
                    exclude '**/debug/**'
                }
            }
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' }

 

目的1:测试环境下,各个模块可以独立运行,运行时,应该展示测试环境的首页

 

目的2:正式环境下,各个模块都不能独立运行,需依附app壳,app壳到具体模块,应展示正试环境的首页

 

目的3:正式环境下,屏蔽debug的测试代码,减少APK体积

 

3.组件化中 子模块交互方式(非ARouter版)

 

3.1:方式一 使用 EventBus的方式,缺点是:EventBean维护成本太高,不好去管理:

3.2:方式二 使 用广播的方式,缺点是:不好管理,都统一发出去了

3.3:方式三 使用隐士意图方式,缺点是:在 AndroidManifest.xml里面配置xml写的太多了

3.4:方式四 使用类加载方式,缺点就是,容易写错包名 类名,缺点较少(尝试写写这种方式)

3.5:方式五 使用全局Map的方式,缺点是,要注册很多的对象

(我们尝试写写这种方式)

 /**
 * 路径对象(公共基础库中,所有子模块都可以调用)
 * 如:
 * path : ”order/Order_MainActivity”
 * clazz : Order_MainActivity.class
 */ public class PathBean {

    private String path; // person/Person_MainActivity
    private Class clazz; // Person_MainActivity.class

    public PathBean() {
    }

    public PathBean(String path, Class clazz) {
        this.path = path;
        this.clazz = clazz;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }
}
 /**
 * 全局路径记录器(根据子模块进行分组)
 * 组名:order,personal
 *       order=[{Order_MainActivity},{Order_MainActivity2}, {Order_MainActivity3}]
 */ 
public class RecordPathManager {

    /**
     * 先理解成 仓库
     * group: app,order,personal
     *
     * order:
     *      OrderMainActivity1
*      OrderMainActivity2
     *      OrderMainActivity3
     */
    private static Map<String, List<PathBean>> maps = new HashMap<>();

    /**
     * 将路径信息加入全局Map
     *
     * @param groupName 组名,如:"personal"
     * @param pathName  路劲名,如:"Personal_MainActivity"
     * @param clazz     类对象,如:Personal_MainActivity.class
     */
    public static void addGroupInfo(String groupName, String pathName, Class<?> clazz) {
        List<PathBean> list = maps.get(groupName);

        if (null == list) {
            list = new ArrayList<>();
            list.add(new PathBean(pathName, clazz));
            // 存入仓库
            maps.put(groupName, list);
        } else {
            // 存入仓库
            maps.put(groupName, list);
        }
        maps.put(groupName, list);
    }

    /**
     * 只需要告诉我,组名 ,路径名,  就能返回 "要跳转的Class"
     * @param groupName 组名
     * @param pathName 路径名
     * @return 跳转目标的class类对象
     */
    public static Class<?> startTargetActivity(String groupName, String pathName) {
        List<PathBean> list = maps.get(groupName);
        if (list == null) {
            Log.d(Config.TAG, "startTargetActivity 此组名得到的信息,并没有注册进来哦...");
            return null;
        }
        // 遍历 寻找 去匹配 “PathBean”对象
        for (PathBean pathBean : list) {
            if (pathName.equalsIgnoreCase(pathBean.getPath())) {
                return pathBean.getClazz();
            }
        }
        return null;
    }

    /**
     * 清理、回收
     */
    public static void recycleGroup() {
        maps.clear();
        maps = null;
        System.gc();
    }
}

 

方式一:类加载技术交互

try{
    Class targetClass = Class.forName("com.XX.XXX.XxActivity")
    Intent intent = new Intent(this,tagetClass);
    intent.putExtra();
    startActiviy(intent);
}catch(ClassNotFoundException){
    e.printStackTrace();
}

 

方式二:全局Map记录信息的方式交互:

public class Order_MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.order_activity_main);
    }

    public void jumpPersonal(View view) {
        // todo 方式一 类加载
        // 类加载跳转,可以成功。维护成本较高且容易出现人为失误
        try {
            Class targetClass = 
Class.forName("com.xiangxue.modular.Person_MainActivity");
            Intent intent = new Intent(this, targetClass);
            intent.putExtra("name", "simon");
            startActivity(intent);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        // todo 方式二 全局Map
        // Toast.makeText(this, "1", Toast.LENGTH_SHORT).show();
        Class<?> targetActivity = 
        RecordPathManager.startTargetActivity("personal", "Personal_MainActivity");
        startActivity(new Intent(this, targetActivity));
    }
}

 

组件化二:

组件化二的学习目录: 1.APT技术。 2.高级用法JavaPoet。 3.组件化项目部署,ARouter原理。

APT是什么? APT(Annotation Processing Tool) 是一种处理注释的工具,它对源代码文件进行检测找出 其中的Annotation,根据注解自动生成代码,如果想要自定义的注解处理器能够正常运行,必须要通过 APT工具来进行处理。 也可以这样理解,只有通过声明APT工具后,程序在编译期间自定义注解解释器 才能执行。 通俗理解:根据规则,帮我们生成代码、生成类文件

APT中用到的结构体思路

element组成的结构体 <html>
  <body>
    <div>. ....</ div >
  </ body >
</ html >
对于java源文件来说,它同样也是一种结构体语言 
package com.netease.apt;     // PackageElement 包元素/节点

public class Main{             // TypeElement 类元素/节点

           private int x;     // VariableElement 属性元素/节点

           private Main(){    // ExecuteableElement 方法元素/节点
           }

           private void print(String msg){}
}

 

APT中用到的重要元素

PackageElement
表示一个包程序元素。提供对有关包及其成员的信息的访问

ExecutableElement
表示某个类或接口的方法、构造方法或初始化程序(静态或实例)

TypeElement
表示一个类或接口程序元素。提供对有关类型及其成员的信息的访问

VariableElement
表示一个字段、enum 常量、方法或构造方法参数、局部变量或异常参数

 

APT中用到API

getEnclosedElements()   返回该元素直接包含的子元素 
getEnclosingElement()   返回包含该element的父element,与上一个方法相反 
getKind()               返回element的类型,判断是哪种element 
getModifiers()          获取修饰关键字,入public static final等关键字 
getSimpleName()         获取名字,不带包名 
getQualifiedName()      获取全名,如果是类的话,包含完整的包名路径 
getParameters()         获取方法的参数元素,每个元素是一个VariableElement 
getReturnType()         获取方法元素的返回值 
getConstantValue()      如果属性变量被final修饰,则可以使用该方法获取它的值

 

1.APT技术

APT全称: annotation process tool是一种处理注释的工具,它对源代码文件进行检测找出其 中的Annotation,使用Annotation进行额外的处理。

APT 编译的时候 ----------> 处理注解 --------> 生成代码----------> 编译完成

APT 传统方式 ---------------> 生成 java文件

APT JavaPoet方式 ---------> 生成Java文件

传统方式 那些 开源项目有用到?

答:看看EventBus源码就知道了 传统方式:优点(编程的流程写下去) 缺点(没有oop思想加入进来) https://github.com/greenrobot/EventBus
as 4.0.1 输出:https://blog.csdn.net/u011418943/article/details/106876898

JavaPoet是什么?

JavaPoet是square推出的开源java代码生成框架,提供Java Api生成.java源文件 这个 框架功能非常实用,也是我们习惯的Java面向对象OOP语法 可以很方便的使用它根据注解生成对应代码 通过这种自动化生成代码的方式, 可以让我们用更加简洁优雅的方式要替代繁琐冗杂的重复工作

项目主页及源码:https://github.com/square/javapoet

JavaPoet相关

类对象                              说明
MethodSpec           代表一个构造函数或方法声明 
TypeSpec             代表一个类,接口,或者枚举声明 
FieldSpec            代表一个成员变量,一个字段声明 
JavaFile             包含一个顶级类的Java文件 
ParameterSpec        用来创建参数
AnnotationSpec       用来创建注解
ClassName            用来包装一个类
TypeName             类型,如在添加返回值类型是使用 TypeName.VOID

$S 字符串,如:$S, ”hello”
$T 类、接口,如:$T, MainActivity

 

2.高级用法JavaPoet

JavaPoet到底是什么? 答:oop思想方式:优点(加入oop思想) 缺点(不习惯,倒序)

 

 

JavaPoet真的比传统方式好吗?

答:并不是这样的,如果复杂的代码生成,反而效率低下 发展趋势,oop思想,真正的掌握JavaPoet,

爱不释手
https://github.com/alibaba/ARouter https://github.com/JakeWharton/butterknife APT的学习,创建JavaLib,要监控到,编译期

// 构建 -------》 【编译时期. ....】 ------》打包 ----》安装
    // AS3.4.1 + Gradle 5.1.1 + auto-service:1.0-rc4
    compileOnly'com.google.auto.service:auto-service:1.0-rc4'
    annotationProcessor'com.google.auto.service:auto-service:1.0-rc4'

 

APT 依赖 注解

com.xiangxue.compiler.ARouterProcessor

 

JavaPoet的学习 模型1:静态 写死

package com.example.helloworld;

public final class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, JavaPoet!");
  }
}

 

模型2:动态变化

public class MainActivity$$$$$$$$$ARouter {
  public static Class findTargetClass(String path) {
    return path.equals("app/MainActivity") ? MainActivity.class : null;
  }
}

3.组件化项目部署,ARouter原理

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

### 回答1: Android组件是将一个大型的Android应用拆分为多个模块或组件,每个组件都是独立的可重用模块。这种架构有助于代码的模块、开发效率的提高和维护的便捷。 在组件架构中,同的组件之间需要进行通信和跳转。路由就是组件之间相互跳转的机制。在路由中,每个组件都可以注册自己路由,其他组件可以通过路由跳转到该组件。 Android中常用的路由框架有ARouter、RouterX和Fragmentation等。这些框架都提供了路由的基本功能,如路由注册、路由跳转、参数传递等。同时,这些框架还支持拦截器、注解、跨模块通信等高级功能,使得组件之间的通信更加方便和灵活。 总之,组件和路由是Android开发中的重要概念和技术,它们可以使得应用更加模块、可扩展和易于维护。 ### 回答2: Android组件是一种将一个大型的Android应用拆分成多个独立的组件,每个组件都可以独立开发、测试和维护的开发方式。而路由是组件开发中一个重要的技术,用于实现不同组件之间的通信和页面跳转。 在Android组件开发中,不同功能的模块或组件被拆分成独立的子模块,每个子模块可以独立编译、测试和发布。这样的好处是提高开发效率,降低代码耦合度,方便团队协作和模块复用。 而路由作为组件开发中的一个重要技术,用于实现不同组件之间的通信和页面跳转。它能够将各个组件间的依赖关系解耦,简组件间的调用和传递参数。通过路由,一个组件可以通过简单的接口调用来启动其他组件的页面,并可以传递参数,实现页面间的跳转和数据交互。 实现Android组件路由的方法有很多种,比较常见的有利用APT(Annotation Processing Tool)技术动态生成路由表,利用反射技术实现路由跳转,或者利用路由框架实现路由功能。通过使用这些方法,可以简组件间的调用和页面跳转的过程,提高开发效率和代码的可维护性。 总而言之,Android组件是一种将大型应用拆分成独立的组件进行开发的方式,而路由是实现组件之间通信和页面跳转的重要技术。组件开发和路由技术的应用可以提高开发效率,降低代码耦合度,并方便团队协作和模块复用。 ### 回答3: Android组件是一种软件开发的架构设计模式,它将一个大型的Android应用程序拆分成若干个独立的组件,每个组件都可以独立开发、测试和部署。这种组件的设计方式旨在提高应用程序的可维护性、可测试性和代码重用性。 在Android组件中,路由是一个非常重要的概念。路由用于管理和控制组件之间的通信和跳转。通过路由,不同的组件可以实现互相之间的跳转和数据传递,从而实现组件之间的解耦和灵活性。 Android组件中的路由通常通过路由表或者路由映射来实现。路由表是一个集中管理和维护路由信息的表格,它记录了组件之间的跳转路径和参数传递规则。当一个组件需要跳转到另一个组件时,它可以通过查询路由表来找到目标组件的路径和参数,从而实现跳转。 另外,路由还可以实现在不同组件之间传递数据。通过路由,可以将数据从一个组件传递给另一个组件,实现数据的共享和交互。这种方式可以避免组件之间直接依赖和耦合,提高代码的可维护性和可扩展性。 总之,Android组件中的路由是实现组件间通信和跳转的重要手段,它可以提高应用程序的可维护性、可测试性和代码重用性。通过良好的路由设计和管理,可以实现更加灵活、模块和可扩展的Android应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值