手写一个安卓组件化框架

首先说一下原理和主要步骤:

组件化的核心就是通过配置Gradle,使子APP可以在独立应用和Library之间自由切换,然后主APP依赖子APP和公共的Library,子APP依赖公共Library。

在主APP初始化的时候,通过反射获取子APP的Application实例,初始化子APP,将主APP的Application传递给子APP使用。将然后子APP暴露接口给公共的Library,主APP通过调用公共Library中接口方法实现与子APP进行交互。

具体步骤:

创建一个主APP,一个library,若干个子APP
在这里插入图片描述

  1. 主APP和子APP作为一个统一的APP,需要有相同的配置,所以在gradle.properties文件中定义配置信息。
    在这里插入图片描述
  2. 改变主APP的Gradle配置信息
    在这里插入图片描述
    3.改变公共Library的Gradle配置信息,和主APP相同。

4.在所有子APP分别创建一个新的manifest文件,当子APP处于Library状态时将读取这个manifest文件

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

5.配置所有子APP的Gradle配置信息

//根据自定义的boolean值切换application和library状态
if (childOneRunAlone.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

android {
    //统一配置参数
    compileSdkVersion compile_sdk_version.toInteger()
    defaultConfig {
    //根据状态判断是否需要设置applicationId
        if(childOneRunAlone.toBoolean()){
        applicationId "com.happyplay.childone"
        }
         //统一配置参数
        minSdkVersion min_sdk_version.toInteger()
         //统一配置参数
        targetSdkVersion target_sdk_version.toInteger()
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    sourceSets {
        main {
            // 独立运行与集成调试时使用不同的 AndroidManifest.xml 文件
            if (childOneRunAlone.toBoolean()) {
            //正常的manifest文件路径
                manifest.srcFile 'src/main/AndroidManifest.xml'
            } else {
            //后来创建的新的manifest路径
                manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation project(':baselibrary')
}

6.让主APP依赖所有子APP和公共Library,让所有子APP都依赖公共Library。
到此为止,Gradle配置完成,可以在gradle.properties文件中修改自定义boolean值切换子APP状态。

7.在公共Library中定义初始化接口

public interface Initiative {
    void init(Application app);
}

8.在主APP和子APP中创建自定义Application类,并实现Library中的初始化接口。

9.在公共Library中新建类,创建String数组,将所有子APP的Application文件全类名存储起来。

public class ChildApplicationList {
    public static final String [] APPS={"com.happyplay.childone.MyApplication","com.happyplay.childtwo.MyApplication"};
}

10.在主APP初始化的时候,通过反射获取子APP的Application实例,并将自己的Application传给子APP使用。

//主APP自定义Application类,需要在清单文件中配置
public class MyApplication extends Application implements Initiative {
    @Override
    public void onCreate() {
        super.onCreate();
        init(this);
    }

    @Override
    public void init(Application app) {

        for (String className :ChildApplicationList.APPS) {
            try {
            //通过反射获取子APP的Application实例
                Class<?> clazz = Class.forName(className );
                Object o = clazz.newInstance();
                if(o instanceof Initiative){
                //将主APP的Application传给子APP
                    ((Initiative) o).init(this);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

11.在公共Library中定义子APP对外暴露的接口

public interface ChildOneService {
// 这里只是做一个简单的演示,弹一个吐司
    void showToast(Context context,String s);
}

12.在子APP中新建一个类实现这个接口

public class ChildOneServiceImpl implements ChildOneService {
    @Override
    public void showToast(Context context,String s) {
        Toast.makeText(context,s,Toast.LENGTH_SHORT).show();
    }
}

13.也在公共Library中新建一个类实现这个接口,方法体都为空即可,防止子APP被删除后报空指针异常。

public class EmptyChildOneService implements ChildOneService {
    @Override
    public void showToast(Context context, String s) {

    }
}

14.在公共Library中新建一个类,接收所有子APP的接口实现类。

public class ServiceFactory {
//子APP一的接口
    private ChildOneService childOneService;

    private static volatile ServiceFactory serviceFactory;
    
    private ServiceFactory() { }

    public static ServiceFactory getInstance() {
        if (serviceFactory == null) {
            synchronized (ServiceFactory.class) {
                if (serviceFactory == null) {
                    serviceFactory=new ServiceFactory();
                }
            }
        }
        return serviceFactory;
    }
  
        public ChildOneService getChildOneService () {
        //如果子APP一被删除,childOneService会为空,用EmptyChildOneService代替,防止异常。
            if(childOneService==null){
                childOneService=new EmptyChildOneService();
            }
            return childOneService;
        }

        public void setChildOneService (ChildOneService childOneService){
            this.childOneService = childOneService;
        }
    }

14.在子APP初始化的时候将接口实现类传递给公共Library。

public class MyApplication extends Application implements Initiative {
    private static Application application;

    public static Application getApplication() {
        return application;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        init(this);
    }

    @Override
    public void init(Application app) {
    //当子APP状态为library的时候,这里的Application是主APP传递过来的
    //当子APP状态为独立APP的时候,这里的Application是自己的。
        application = app;
       // 将暴露的接口传递给公共Library
        ServiceFactory.getInstance().setChildOneService(new ChildOneServiceImpl());
    }
}

15.在主APP中调用公共Library中的接口方法即可实现与子APP交互

 public void onClick(View view) {
        ServiceFactory.getInstance().getChildOneService().showToast(getApplicationContext(),"弹吧");
    }

到此为止,模块化开发框架搭建完成,个人感觉和MVP的设计思想很相似。主APP和子APP通过公共Library进行交互,而不是直接持有对方,达到了解耦的目的。这样一人开发一个模块,互不干扰,是大型项目必备的策略。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值