Android组件化

组件化

组件化的一般结构

在这里插入图片描述

业务组件层

业务组件层在创建Module时一般使用 Phone&Tablet 类型的,这个需要单独的去进行调试,这种类型的可以单独的进行调试,Phone&Tablet这种可以在 library 和 application之间进行转换。

功能组件层

功能组件层主要是将我们的一些基础组件进行封装,在创建Module时一般使用Android Library 这种类型,这种不能单独的进行调试。但是如果需要进行单独调试的话就可以创建 Phone&Tablet 类型的。不管是哪种类型的,在最终打包apk的时候都要将其转化为library。

基础组件层

实现基本功能,功能组件层需要依赖基础组件层,在这一层一般都是一些简单的功能,一般不需要进行单独的调试,所以一般都是Android Library这种类型的。

组件化的框架搭建

ext {
    android = [
            compileSdkVersion           : 31,
            buildToolsVersion           : 28,
            applicationId               :"com.example.moudle",
            minSdkVersion               :21,
            targetSdkVersion            :31,
            versionCode                 :1,
            versionName                 :"1.0",
            testInstrumentationRunner   :"androidx.test.runner.AndroidJUnitRunner"
    ]

    androidxDeps = [
            "appcompat": 'androidx.appcompat:appcompat:1.1.0',
            "material": 'com.google.android.material:material:1.1.0',
            "constaraintlayout": 'androidx.constraintlayout:constraintlayout:1.1.3',
    ]

    commonDeps = [
            "arouter_api"          : 'com.alibaba:arouter-api:1.5.1',
            "glide"                : 'com.github.bumptech.glide:glide:4.11.0'

    ]

    annotationDeps = [
            "arouter_compiler" : 'com.alibaba:arouter-compiler:1.5.1'
    ]

    retrofitDeps = [
            "retrofit"  : 'com.squareup.retrofit2:retrofit:2.9.0',
            "converter" : 'com.squareup.retrofit2:converter-gson:2.9.0',
            "rxjava"    : 'io.reactivex.rxjava2:rxjava:2.2.20',
            "rxandroid" : 'io.reactivex.rxjava2:rxandroid:2.1.1',
            "adapter"   : 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
    ]

    androidxLibs = androidxDeps.values()
    commonLibs = commonDeps.values()
    annotationLibs = annotationDeps.values()
    retrofitLibs = retrofitDeps.values()

}

android 是一些版本号的一些东西,中间是一些依赖库的导入,最后这四行是对前面的几个依赖库的封装。

在这个application中的gradle.properties这个文件中定义isDebug变量,如果这个值为true,则这个module可以单独的运行,就能够对这个模块单独的进行调试。如果为false,则这个module就是不能单独的运行,就只能依赖于app,它就相当于一个依赖库,只能依赖在这个app上面。

isDebug = false

这个isDebug是非常重要的一个变量,它控制了这个组件是否能够单独的运行。

在module下的build.gradle需要改变plugin

if (isDebug.toBoolean()) {
    apply plugin: 'com.android.application'   //需要单独调试的
} else {
    apply plugin: 'com.android.library'		 //不能单独运行,相当于一个依赖库,
}

还需要在buildTypes中定义以下代码:

sourceSets{
            main{
                if(isDebug.toBoolean()){
                    manifest.srcFile 'src/main/Debug/Androidmanifest.xml'
                }else{
                    manifest.srcFile 'src/main/AndroidManifest.xml'
                }
            }
}

解释一下,这里声明了manifest文件是使用的哪一种。DeBug版本使用的和app使用的是一样的,但是在依赖的版本使用的是只有一个四大组件的声明,没有application的一些声明。

debug版本的Manifest.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.module">

    <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.Moudle">
        <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>
    </application>

</manifest>

依赖库版本的Manifest.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.module">

    <application>
        <activity android:name=".MainActivity"/>
    </application>

</manifest>

还需要导入依赖库:

    api rootProject.ext.androidxLibs
    api rootProject.ext.commonLibs
    api rootProject.ext.annotationLibs

在这使用api导入依赖库。

在app中的build.gradle中导入所依赖的组件,就能够将组件进行依赖在这个app上面,使这个”空壳APP“组装成为一个真正的App。

implementation project(":module")

这样就大体将一个组件化的框架搭建起来了。

当要进行调试时,将isDebug改为true之后,一定要记得sync。

api和implementation导入依赖的区别

implementation 表示依赖,即 只依赖不打包进来。
api 表示打包,即 不仅依赖还打包进来,这样上层就不用重复依赖。
注意:这里的打包是便于理解,是指打包依赖关系而不是打包源代码,也就是说将依赖暴露给上层。

组件间的通信

在没有使用组件化开发之前,活动与活动之间是能够通过Intent去相互交流,但是使用了组件化之后,就不能够去使用Intent进行活动之间的交流,所以就需要引入ARouter去进行组件之间的通信。

ARouter

ARouter是用于进行组件之间的通信。支持模块间的路由、通信、解耦。它可以实现组件间的路由功能。路由是指从一个接口上收到数据包,根据数据路由包的目的地址进行定向并转发到另一个接口的过程。这里可以体现出路由跳转的特点,非常适合组件化解耦。

ARouter的配置

在defaultConfig中导入:

        javaCompileOptions{				//配置ARouter
            annotationProcessorOptions{
                arguments = [AROUTER_MODULE_NAME:project.getName()]
            }
        }

导入ARouter的注解器:

annotationProcessor rootProject.ext.annotationLibs

上面就是ARouter的一些简单配置,这需要在每一个模块下都需要配置,配置玩这些就能够使用ARouter了。

ARouter的使用

ARouter在使用之前需要先进行初始化操作,因为使用ARouter可能需要对每一个活动进行操作,所以我们需要在每一个模块之前进行初始化,所以就需要在Application层去进行初始化。所以在创造活动时就需要进行初始化ARouter。

import android.app.Application;

import com.alibaba.android.arouter.launcher.ARouter;

public class BaseApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        if (isDebug()) {
            ARouter.openLog();     	// 打印日志
            ARouter.openDebug();   	// 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
        }
        ARouter.init(this); 		// 尽可能早,推荐在Application中初始化ARouter

    }

    private boolean isDebug() {
        return BuildConfig.DEBUG;
    }
}

在这里BaseApplication继承了Application,重写了onCreate()方法,在这里重写了Application的方法,就需要在AndroidManifest.xml文件中进行声明Application的name,所以需要在Application中加上下面这句话:

android:name=".BaseApplication"

前面是所有的准备工作,现在就开始正式的使用ARouter了,如果需要在activity、service、fragment等等之间进行跳转,就需要使用@Route(path = “/xx/xx”),这里的path是一个跳转路径,/xx/xx是一个二级目录。

这里需要注意:同一个组件的一级目录可以相同,但是不同组建的一级目录不能相同。

app目录下的MainActivity:

@Route(path = "/app/MainActivity")
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.buttonMain);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ARouter.getInstance().build("/module/MainActivity2").navigation();

            }
        });
    }
}

module目录下的MainActivity2:

@Route(path = "/module/MainActivity2")
public class MainActivity2 extends AppCompatActivity {

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

由以上代码可知,在MainActivity中点击Button之后,就会跳转到MainActivity2活动中去。如果路径填写不正确,将会弹出Toast提醒。

ARouter.getInstance().destroy();

上面这行代码可以写在Application生命周期的onTerminate( )里面。上面这行代码是解绑释放资源的,有解绑,就需要有注入,因为这每一个活动都是添加在一个集合上面的,所以在每一个活动中需要添加:(ARouter相当于一个容器,只有向里面注入内容,才能够拿取里面的内容)

ARouter.getInstance().inject(this);

如果需要在Activity之前进行跳转的时候需要传递数据,就需要使用@Autowired()注解。

@Route(path = "/app/MainActivity")
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.buttonMain);
        ARouter.getInstance().inject(this);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ARouter.getInstance().build("/module/MainActivity2")
                        .withString("name", "android")
                        .withDouble("d", 10.1)
                        .navigation();

            }
        });
    }
}
@Route(path = "/module/MainActivity2")
public class MainActivity2 extends AppCompatActivity {

    @Autowired()
    String name;

    @Autowired(name = "d")
    double aDouble;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        ARouter.getInstance().inject(this);
        Log.d("TAG", "onCreate: " + name + " + " + aDouble);
    }
}

上面这两段代码还是之前跳转活动的代码,在这如果不在注解中写name参数,就需要将变量名写成和name值相等,但是我建议还是写上name参数,这样就避免了可能会发生的一些错误。(在传输数据时,必须将此活动进行注入ARouter)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值