美文网首页kotlin
Android--Groovy语法、组件化架构简析

Android--Groovy语法、组件化架构简析

作者: aruba | 来源:发表于2021-11-21 20:00 被阅读0次

    组件化就是将我们的APP拆分成很多个模块,每个模块可以单独运行,以便于开发维护和测试,组件化中必不可少的是Gradle的配置,Gradle中使用的是Groovy语言,Groovy也是JVM语言的一种,如果你熟悉kotlin,那么学习Groovy将更容易,这也得益于kotlin结合了各大语言的优点,引入了很多最新、最流行的概念

    一、Groovy简单上手

    在AS中新建一个module,并在生成的Gradle中练习Groovy的基础语法

    1.定义变量

    Groovy中变量的定义需使用def关键字,而且不需要强制指定类型

    task testGroovy() {
        def i = 1
        println(i)
    }
    
    2.定义类

    Groovy兼容Java,定义类就和Java一样了,类中成员变量会隐式生成get/set方法,最后观察打印方法的调用,在Groovy中方法调用可以省略"()"

    task testGroovy() {
        Project p = new Project("groovy", "1.0.0", "jvm")
        // 打印版本号
        println p.version
    }
    
    class Project {
        String name
        String version
        String group
    
        Project(String name, String version, String group) {
            this.name = name
            this.version = version
            this.group = group
        }
    }
    
    3.字符串

    Groovy有三种定义字符串的方式

    • 单引号
    task testGroovy2() {
        def s = 'hello'
        println s
    }
    
    • 双引号,和kotlin一样,可以使用$符取变量值
    task testGroovy2() {
        def s1 = 'hello'
    
        def s2 = "$s1 groovy"
        println s2
    }
    
    • 三个单引号,可以换行
    task testGroovy3() {
        def s = '''hello
        groovy
        is
        simple
        '''
        println s
    }
    
    4.集合
    • list

    定义list时使用 "[ ]"

    task testGroovy4() {
        def list = ['one', 'two', 'three']
        println list[1]
    }
    

    使用 "<<" 添加一个元素

    task testGroovy4() {
        def list = ['one', 'two', 'three']
        list << 'four'
        println list[3]
    }
    
    • map

    map使用 ":" 隔开,区别key和value

    task testGroovy5() {
        def map = ['one': 1, 'two': 2, 'three': 3]
        map << ['four': 4]
        println map['four']
        println map.four
    }
    
    5.闭包

    熟悉kotlin的话,理解起来就简单了,在使用上就是lambda表达式表示的变量,也就是函数类型变量

    task testGroovy6() {
        def print1 = { message ->
            println "$message end"
        }
        
        print1 "hello"
    }
    

    二、Gradle

    Gradle主要分为两个基本概念:项目(Project)与任务(Task),可以用线程和方法的关系来理解,一个项目可以包含多个任务,并且可以手动配置多个任务的调用链

    1.Project

    build.gradle文件在构建时相当于一个Project,又称为组件,常用的方法有:apply、dependencies、repositories、task
    Project自带属性为:group、name、version
    还可以使用ext、gradle.properties来定义属性

    2.Task

    任务是最小的工作单元,可以定义任务依赖于其他任务,调用序列和执行条件。常用方法有dependsOn、doFirst、doLast
    如下面例子,执行doTwo任务时,会先执行doOne任务

    task doOne() {
        println "doOne"
    }
    
    task doTwo() {
        dependsOn doOne
        println "doTwo"
    }
    

    结果:


    doFrist、doLast则可以指定任务中代码块的执行顺序:

    task doOne() {
        println "doOne"
    }
    
    task doTwo() {
        dependsOn doOne
        println "doTwo"
        doLast {
            println "doLast"
        }
        doFirst {
            println "doFirst"
        }
    }
    

    结果:


    三、组件化

    随着app的迭代,业务越来越繁重,为了让业务可以分层,组件化出现了,经过基础组件的支撑,业务层组件可以单独运行,以便于新功能的开发于测试


    1.新建业务module_a

    业务module是可以单独运行的,所以它的gradle使用的是com.android.application插件


    将创建项目时的默认的app module作为Application,最后完整的app还是得通过该module来编译,但此时并不能将module_a引入到app module中,找不到module_a
    2.修改业务module_a的gradle配置

    如果需要module_a能够被引入,需要使用com.android.library插件,但是它不能和com.android.application插件同时使用,怎么办呢?答案是使用变量动态配置gradle

    def isModule = true
    if (isModule) {
        apply plugin: 'com.android.library'
    } else {
        apply plugin: 'com.android.application'
    }
    apply plugin: 'kotlin-android'
    

    manifest文件也是需要两份,一份作为application的,一份作为library的



    src/main/AndroidManifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.aruba.libmodule_a">
    
        <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.ARouterApplication">
            <activity
                android:name=".ModuleAActivity"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    src/main/manifest/AndroidManifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.aruba.libmodule_a">
    
        <application>
            <activity android:name=".ModuleAActivity" />
        </application>
    
    </manifest>
    

    在gradle中为他们配置,根据变量加载不同的manifest文件:

    android {
        compileSdk 31
    
        defaultConfig {
            if (!isModule) {// application才有id
                applicationId "com.aruba.libmodule_a"
            }
            minSdk 21
            targetSdk 31
            versionCode 1
            versionName "1.0"
    
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }
    
        // 根据变量配置不同manifest
        sourceSets {
            main {
                if (isModule) {
                    manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
                } else {
                    manifest.srcFile 'src/main/AndroidManifest.xml'
                }
            }
        }
    }
    
    3.依赖基础组件实现module_a组件跳转到app组件

    现在我们可以在app module主界面中跳转到module_a的Activity了

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
        }
    
        fun toModule(view: android.view.View) {
            startActivity(Intent(this, ModuleAActivity::class.java))
        }
    
    }
    

    但是moudle_a的Activity并不能跳转到MainActivity,因为module_a并没有引入app组件


    解决方法:

    3.1 在基础base组件中缓存各个Activity的类,利用缓存获取需要跳转的类
    object ActivityCache {
        val ActivityClzByName: MutableMap<String, Class<out Activity>> = mutableMapOf()
    }
    
    3.2 然后在module_a中依赖该base组件
    3.3 最后在Application中将所有Activity的类放入缓存
    class App : Application() {
        override fun onCreate() {
            super.onCreate()
            ActivityCache.ActivityClzByName["main"] = MainActivity::class.java
            ActivityCache.ActivityClzByName["module_a"] = ModuleAActivity::class.java
        }
    }
    
    3.4 在ModuleAActivity中利用缓存map跳转
    class ModuleAActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_module_aactivity)
        }
    
        fun toMain(view: android.view.View) {
            startActivity(Intent(this, ActivityCache.ActivityClzByName["main"]))
        }
    }
    

    最后效果:


    4.单独运行moudle_a

    改下moudle_a中gradle的变量值,就可以单独运行moudle_a了



    麻烦的是每次使用需要手动改变变量,下篇将利用ARouter来实现组件化

    相关文章

      网友评论

        本文标题:Android--Groovy语法、组件化架构简析

        本文链接:https://www.haomeiwen.com/subject/lazdtrtx.html