【Andriod】组件化架构之实现组件可插拔

上一篇文章讲解了如何在云端配置项目的依赖:

【Android】自定义Gradle Plugin实现云端配置项目依赖

这篇文章讲解,当修改了项目的依赖(dependencies{…})代码,比如删除或者新增了SDK组件,如何保证项目正常编译运行不受影响,即实现组件可插拔。

例如,应用依赖了library1、library2、library3、…这些library都是可选的,即可以全都要,可以全不要或者只要其中一部分。现在通过本地gradle或者在云端插件的方式选择了应用需要依赖哪些library,如何达到不需要修改代码,即可感知到功能的变化。

新建Demo Project名为MavenRepoDemo,新增三个Library,分别为:

  • 1、commonlibrary
    基础library,用来动态加载library1和library2。
  • 2、library1
    可选的library
  • 3、library2
    可选的library

项目结构如下:
在这里插入图片描述
其中app module是用来展示功能的,通过插件依赖了commonlibrary,commonlibrary是基础library,library1和library2是可选的。

根目录中的aar_upload.gradle文件是用来上传library到maven仓库的脚本。

app module中build.gradle没有配置任何依赖:

apply plugin: 'com.android.application'
apply plugin: 'MyPlugin'
android {
    compileSdkVersion 29
    buildToolsVersion "29.0.1"

    defaultConfig {
        applicationId "com.devnn.mavenrepodemo"
        minSdkVersion 15
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

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

}

dependencies {
   //note: here is nothing
}

依赖是通过云端来完成的,具体内容参阅文章开头的链接。

app module中的MainActivity代码如下:

package com.devnn.mavenrepodemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

import com.devnn.commonlibrary.ILibrary;
import com.devnn.commonlibrary.LibraryLoader;

public class MainActivity extends AppCompatActivity {
    private TextView tvMessage;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvMessage = findViewById(R.id.main_text);
        ILibrary library1 = LibraryLoader.getLibrary1();
        ILibrary library2 = LibraryLoader.getLibrary2();
        if (library1 != null) {
            tvMessage.append("\n");
            tvMessage.append(library1.hello());
        }
        if (library2 != null) {
            tvMessage.append("\n");
            tvMessage.append(library2.hello());
        }
    }
}

当两个library加载成功后,运行显示:
在这里插入图片描述
其中Hello,World!是tvMessage控件默认的文本内容。

可以看到加载library是通过LibraryLoader来完成的。没有找到library时getLibraryX()方法返回null。

接下来讲解具体实现。

在commonlibrary中建立LibraryLoader.java类,用来加载其它的library。代码如下:

package com.devnn.commonlibrary;

import android.content.Context;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * create by nannan on 2020/6/23
 */
public class LibraryLoader {

    public static ILibrary getLibrary1() {
        ILibrary library = loadLibrary("com.devnn.library1.Library1");
        return library;
    }

    public static ILibrary getLibrary2() {
        ILibrary library = loadLibrary("com.devnn.library2.Library2");
        return library;
    }

    private static ILibrary loadLibrary(String path) {
        ILibrary library = null;
        try {
            Class mClass = Class.forName(path);
            Constructor constructor = mClass.getConstructor();
            library = (ILibrary) constructor.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return library;
    }
}

可以看到要加载的library存在与否并不影响应用编译和运行。

其实这里核心技术点就是动态加载class文件。

另外,新建ILbrary.java类,作为其它library共同的接口:

package com.devnn.commonlibrary;

/**
 * create by nannan on 2020/6/22
 */
public interface ILibrary {
    String hello();
}

只是简单输出一段文本。

在library1 module中新建Library1.java类,实现ILibrary接口:

package com.devnn.commonlibrary;

package com.devnn.library1;

import com.devnn.commonlibrary.ILibrary;

/**
 * create by nannan on 2020/6/10
 */
public class Library1 implements ILibrary {
    public String hello() {
        return "hello,I am Library1";
    }
}


在library2 module中新建Library2.java类,实现ILibrary接口:

package com.devnn.library2;

import com.devnn.commonlibrary.ILibrary;

/**
 * create by nannan on 2020/6/10
 */
public class Library2 implements ILibrary {
    public  String hello(){
        return "hello,I am Library2";
    }
}

整个Demo代码就这么多。

当在云端修改了要依赖的library,重新编译运行即可感知到功能的变化。

Demo Project源码:
https://github.com/devnns/MavenRepoDemo/tree/feathure/load_library_dynamic

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值