组件化开发之旅

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_15988951/article/details/89421106

在介绍如何实现组件化的开始前,先介绍一下组件化与插件化

插件 : 指的是单一功能的组件,或是抽出来的widget等,如支付模块,路由模块,定位模块等。

模块 :指的是独立的业务模块,如常见App中的首页模块,直播模块,商城模块等。

区别 :组件化更偏向于功能的封装,插件化偏向于业务的模块。

一、库工程和module的区别

先来简单介绍一下Android依赖库和Android Project的区别,即 application和library的区别

1、build.gradle中的首行的区别(即标识是否是依赖库或完整工厂)

apply plugin: 'com.android.application'
apply plugin: 'com.android.library'

2、build.gradle 中 applicationId 字段

android {
    ...
    defaultConfig {
        if (loginRunAlone.toBoolean()) {
            applicationId "com.onexzgj.module.login"
        }
         ...
       }
}
  • library 不需要 applicationID字段
  • project 需要ApplicationId

3、清单文件的区别

  • library 需要将本组件中4大组件的信息配置在清单文件中即可
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.onexzgj.module.login">

    <application
        android:theme="@style/AppTheme">
        <activity android:name="com.onexzgj.module.login.LoginActivity">
        </activity>
    </application>

</manifest>
  • project 需要配置完整application,权限、样式、4大组件等信息
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.onexzgj.module.login">

    <application
        android:name=".LoginApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity android:name="com.onexzgj.module.login.LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

二 、组件化需要解决的问题

1、统一管理项目开发环境,使用gradle

在project中将所有的使用到的配置进行集中配置,如何实现?

这里以按照我提交的上的示例为分析案例:

在根目录的gradle.properties中配置,相关的模块是否单独运行的配置,和相关的版本控制等信息包括是否组件进行集成调试的开关,如下所示:

//配置常量进行全局统一配置
compile_sdk_Version = 28
min_sdk_version= 21
target_sdk_version = 28
support_version=28.0.0

//module工程是否单独运行
liveRunAlone=false
loginRunAlone=false
forYouRunAlone=false

2、每一个组件都是一个完整的项目,所以组件也可以进行单独运行

改如何配置?
前面分析了library 和Project的区别,所以,想要让library单独运行,只需要将library中的几个特别注意的地方改为project即可

2.1 修改build.gradle的第一行

if (loginRunAlone.toBoolean()){
    apply plugin: 'com.android.application'
}else{
    apply plugin: 'com.android.library'
}

2.2 根据gradle.propertice配置是否需要applicationId字段

 defaultConfig {
        if (loginRunAlone.toBoolean()) {
            applicationId "com.onexzgj.module.login"
        }
        ...
}

只需要修改project下面的gradle.properties中的开关配置

3、实现组件之间的通信和数据传递,组件之间没有相互依赖,如何进行通信?

3.1 使用第三方的框架

  除了使用第三方的组件化通信框架以外,自己如何实现组件之间的通信

这里实现模块之间的通信,可以使用好多第三方的开源框架(ARouter),如果不知道如何使用,请点击这里。

3.2 自己实现组件之间的通信

这里简单介绍一下如何实现?因为篇幅较长,等后期更新一篇单独实现文章

4、模块之间可以集成调试

在主Module中,根据gradle.properties中的配置,动态的进行依赖module,然后将模块最为library依赖到主Module中。

    if (!liveRunAlone.toBoolean()) {
        api project(':live')
    }
    if (!loginRunAlone.toBoolean()) {
        api project(':login')
    }

5、组件上下文使用 application的传递使用

包括初始化appliction的使用。
在公共模块中定义如下接口

public interface IAppComponent {

    String[] compoment=new String[]{
        "com.onexzgj.module.live.LiveApp",
            "com.onexzgj.module.login.LoginApp"
    };

    void initlize(Application app);
}

在每个module中的App中都实现该接口,如下所示

public class LoginApp extends Application implements IAppComponent {

    private LoginApp instance;

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

    @Override
    public void initlize(Application app) {

        instance=this;

        ServiceFactory.getInstance().setIloginService(new LoginService());
    }
}

再来看看再BaseLibrary中的处理:

package com.onexzgj.onexlibrary;

import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.view.Gravity;

import com.onexzgj.onexlibrary.lib.IAppComponent;

/**
 * Created by OnexZgj on 2018/9/1.
 * <p>
 * 全局Application
 */

public class GlobalApplication extends Application  implements IAppComponent {
    protected static Context context;
    protected static Handler handler;
    protected static int mainThreadId;
    private static GlobalApplication mApp;

    public static synchronized GlobalApplication getInstance() {
        return mApp;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        mApp = this;
        handler = new Handler();




    /**
     * 初始化路由
     */
    private void intARouter() {
        // 这两行必须写在init之前,否则这些配置在init过程中将无效
        ARouter.openLog();     // 打印日志
        ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
        ARouter.init(this); // 尽可能早,推荐在Application中初始化
    }


    /**
     * 获取上下文对象
     *
     * @return context
     */
    public static Context getContext() {
        return context;
    }

 

    @Override
    public void initlize(Application app) {

        try {
            for (String com : compoment) {
                Class<?> clazz = Class.forName(com);
                Object o = clazz.newInstance();
                if (o instanceof IAppComponent){
                    ((IAppComponent)o).initlize(app);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

知道了以上信息后,接下来开启组件化之旅:
先来看看整体的模块和依赖关系:

image.png

各个module中的配置如下图所示

image.png

所有的module都依赖基础库(OnexLibrary) ,至于是否main工程要集成各个插件,则需要根据在gradle.properties 中配置的开关动态的编译

示例项目截图
video2gif_20190420_175448.gif

示例项目已经上传至GitHub:
https://github.com/OnexZgj/ComponentProject

猜你喜欢

转载自blog.csdn.net/qq_15988951/article/details/89421106