Android 组件化的应用 模块通信问题解决


组件之间AndroidManifest合并问题

由于 Android 项目在 Eclipse 和 AndroidStudio开发时 AndroidManifest.xml 文件的位置是不一样的,我们需要在build.gradle 中指定下 AndroidManifest.xml 的位置,AndroidStudio 才能读取到 AndroidManifest.xml,这样解决办法也就有了,我们可以为组件开发模式下的业务组件再创建一个 AndroidManifest.xml,然后根据isModule指定AndroidManifest.xml的文件路径,让业务组件在集成模式和组件模式下使用不同的AndroidManifest.xml,这样表单冲突的问题就可以规避了。
————————————————
 
 
2,如果组件模式下, 则需要重新设置 AndroidManifest.xml 文件,里面配置新的Application路径。比如Login组件单独运行 AndroidManifest 清单文件
 
if (!isModule.toBoolean()) {
    implementation project(':b-main')
    implementation project(':b-login')
    implementation project(':b-setting')
}
 
解决的问题
1.Application
需要看下applicatin的初始化
有自己的application。

代理的application的作用
 
LoginApplicationDelegate
/**
 * login组件全局应用配置
 * Created by chenran3 on 2017/12/6.
 */
@EFModuleAnnotation(moduleName = "b-login",delegateName = "com.cryallen.applogin.LoginApplicationDelegate")
public class LoginApplicationDelegate implements IApplicationDelegate {

    private static final String TAG = "LoginApplicationDelegate";


    @Override
    public void onCreate() {
        EFLog.d(TAG, "*------------------onCreate()---------------->");
    }

    @Override
    public void enterBackground() {
        EFLog.d(TAG, "*------------------enterBackground()---------------->");
    }

    @Override
    public void enterForeground() {
        EFLog.d(TAG, "*------------------enterForeground()---------------->");
    }

    @Override
    public void receiveRemoteNotification(Map<String, String> message) {
        EFLog.d(TAG, "receiveRemoteNotification msg = " + message);
    }

    @Override
    public void onTerminate() {
        EFLog.d(TAG, "*------------------onTerminate()---------------->");
    }

    @Override
    public void onConfigurationChanged(Configuration configuration) {
        EFLog.d(TAG, "*------------------onConfigurationChanged()---------------->");
    }

    @Override
    public void onLowMemory() {
        EFLog.d(TAG, "*------------------onLowMemory()---------------->");
    }

    @Override
    public void onTrimMemory(int var1) {
        EFLog.d(TAG, "*------------------onTrimMemory()---------------->");
    }
}
2.清单文件多个,解决app和单独module的配置
 
1)组件模式和集成模式的转换
 
Android Studio中的Module主要有两种属性,分别为:
 
1、application属性,可以独立运行的Android程序,也就是我们的APP;
 
apply plugin: ‘com.android.application’
1
2、library属性,不可以独立运行,一般是Android程序依赖的库文件;
 
apply plugin: ‘com.android.library’
————————————————
sourceSets {
    main {
        if (isModule.toBoolean()) {
            manifest.srcFile 'src/main/module/AndroidManifest.xml'
        } else {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            //集成开发模式下排除debug文件夹中的所有Java文件
            java {
                exclude 'debug/**'
            }
        }
    }
}
3.切换app和切换组件的变量????
目录中生成一个文件 gradle.properties,我们将使用这个文件的一个重要属性:在Android项目中的任何一个build.gradle文件中都可以把gradle.properties中的常量读取出来;那么我们在上面提到解决办法就有了实际行动的方法,首先我们在gradle.properties中定义一个常量值 isModule(是否是组件开发模式,true为是,false为否):
 
# 每次更改“isModule”的值后,需要点击 "Sync Project" 按钮
isModule=false
———————————————
实现原理:
asset目录下的json配置
/**
 *
 * 加载模块信息
 */
public void loadModule() {
    Context context = getApplicationContext();
    appDelegateList = new ArrayList();
    delegateNameList = new ArrayList();
    try {
        AssetManager assetManager = context.getResources().getAssets();
        String[] fileList = assetManager.list("");
        int fileLength = fileList.length;

        for(int i = 0; i < fileLength; ++i) {
            String fileName = fileList[i];
            if(fileName.startsWith(MODULE_PREFIX)) {
                //解析json配置文件
                ModuleInfo moduleInfo = parse(assetManager.open(fileName));
                if(moduleInfo == null){
                    continue;
                }
                moduleInfoList.add(moduleInfo);
                delegateNameList.add(moduleInfo.getPackageName());
                EFLog.d(TAG, "load Module: " + moduleInfo.getModuleName());
            }
        }
        appDelegateList.addAll(ModuleClassUtils.getObjectsWithClassName(context, IApplicationDelegate.class, delegateNameList));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
uploading.4e448015.gif转存失败重新上传取消
 
登入的解决办法:
业务组件自己的 Application 可以在组件开发模式下初始化一些数据,例如在组件开发模式下,A组件没有登录页面也没法登录,因此就无法获取到 Token,这样请求网络就无法成功,因此我们需要在A组件这个 APP 启动后就应该已经登录了,这时候组件自己的 Application 类就有了用武之地,我们在组件的 Application的 onCreate 方法中模拟一个登陆接口,在登陆成功后将数据保存到本地,这样就可以处理A组件中的数据业务了;另外我们也可以在组件Application中初始化一些第三方库。
————————————————
4)library依赖问题
 
在介绍这一节的时候,先说一个问题,在组件化工程模型图中,多媒体组件和Common组件都依赖了日志组件,而A业务组件有同时依赖了多媒体组件和Common组件,这时候就会有人问,你这样搞岂不是日志组件要被重复依赖了,而且Common组件也被每一个业务组件依赖了,这样不出问题吗?
 
其实大家完全没有必要担心这个问题,如果真有重复依赖的问题,在你编译打包的时候就会报错,如果你还是不相信的话可以反编译下最后打包出来的APP,看看里面的代码你就知道了。组件只是我们在代码开发阶段中为了方便叫的一个术语,在组件被打包进APP的时候是没有这个概念的,这些组件最后都会被打包成arr包,然后被app壳工程所依赖,在构建APP的过程中Gradle会自动将重复的arr包排除,APP中也就不会存在相同的代码了;
 
但是虽然组件是不会重复了,但是我们还是要考虑另一个情况,我们在build.gradle中compile的第三方库,例如AndroidSupport库经常会被一些开源的控件所依赖,而我们自己一定也会compile AndroidSupport库 ,这就会造成第三方包和我们自己的包存在重复加载,解决办法就是找出那个多出来的库,并将多出来的库给排除掉,而且Gradle也是支持这样做的,分别有两种方式:根据组件名排除或者根据包名排除,下面以排除support-v4库为例:
 
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile("com.jude:easyrecyclerview:$rootProject.easyRecyclerVersion") {
        exclude module: 'support-v4'//根据组件名排除
        exclude group: 'android.support.v4'//根据包名排除
    }
}
 
library重复依赖的问题算是都解决了,但是我们在开发项目的时候会依赖很多开源库,而这些库每个组件都需要用到,要是每个组件都去依赖一遍也是很麻烦的,尤其是给这些库升级的时候,为了方便我们统一管理第三方库,我们将给给整个工程提供统一的依赖第三方库的入口,前面介绍的Common库的作用之一就是统一依赖开源库,因为其他业务组件都依赖了Common库,所以这些业务组件也就间接依赖了Common所依赖的开源库。
 
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    //Android Support
    compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
    compile "com.android.support:design:$rootProject.supportLibraryVersion"
    compile "com.android.support:percent:$rootProject.supportLibraryVersion"
    //网络请求相关
    compile "com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion"
    compile "com.squareup.retrofit2:retrofit-mock:$rootProject.retrofitVersion"
    compile "com.github.franmontiel:PersistentCookieJar:$rootProject.cookieVersion"
    //稳定的
    compile "com.github.bumptech.glide:glide:$rootProject.glideVersion"
    compile "com.orhanobut:logger:$rootProject.loggerVersion"
    compile "org.greenrobot:eventbus:$rootProject.eventbusVersion"
    compile "com.google.code.gson:gson:$rootProject.gsonVersion"
    compile "com.github.chrisbanes:PhotoView:$rootProject.photoViewVersion"
 
    compile "com.jude:easyrecyclerview:$rootProject.easyRecyclerVersion"
    compile "com.github.GrenderG:Toasty:$rootProject.toastyVersion"
 
    //router
    compile "com.github.mzule.activityrouter:activityrouter:$rootProject.routerVersion"
}
————————————————
APT:
这一步我们需要先了解 APT这个概念,APT(Annotation Processing Tool)是一种处理注解的工具,
它对源代码文件进行检测找出其中的Annotation,使用Annotation进行额外的处理。 Annotation处理器在处理Annotation时可以根据源文件中的Annotation生成额外的源文件和其它的文件(文件具体内容由Annotation处理器的编写者决定),APT还会编译生成的源文件和原来的源文件,将它们一起生成class文件。在这里我们将在每一个业务组件的 build.gradle 都引入ActivityRouter 的 Annotation处理器,我们将会在声明组件和Url的时候使用,annotationProcessor是Android官方提供的Annotation处理器插件,代码如下:
 
 
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    annotationProcessor "com.github.mzule.activityrouter:compiler:$rootProject.annotationProcessor"
}
————————————————
4、组件化项目的工程类型
 
在组件化工程模型中主要有:app壳工程、业务组件和功能组件3种类型,而业务组件中的Main组件和功能组件中的Common组件比较特殊,下面将分别介绍。
 
1)app壳工程
 
app壳工程是从名称来解释就是一个空壳工程,没有任何的业务代码,也不能有Activity,但它又必须被单独划分成一个组件,而不能融合到其他组件中,是因为它有如下几点重要功能:
 
1、app壳工程中声明了我们Android应用的 Application,这个 Application 必须继承自 Common组件中的 BaseApplication(如果你无需实现自己的Application可以直接在表单声明BaseApplication),因为只有这样,在打包应用后才能让BaseApplication中的Context生效,当然你还可以在这个 Application中初始化我们工程中使用到的库文件,还可以在这里解决Android引用方法数不能超过 65535 的限制,对崩溃事件的捕获和发送也可以在这里声明。
 
2、app壳工程的 AndroidManifest.xml 是我Android应用的根表单,应用的名称、图标以及是否支持备份等等属性都是在这份表单中配置的,其他组件中的表单最终在集成开发模式下都被合并到这份 AndroidManifest.xml 中。
 
3、app壳工程的 build.gradle 是比较特殊的,app壳不管是在集成开发模式还是组件开发模式,它的属性始终都是:com.android.application,因为最终其他的组件都要被app壳工程所依赖,被打包进app壳工程中,这一点从组件化工程模型图中就能体现出来,所以app壳工程是不需要单独调试单独开发的。另外Android应用的打包签名,以及buildTypes和defaultConfig都需要在这里配置,而它的dependencies则需要根据isModule的值分别依赖不同的组件,在组件开发模式下app壳工程只需要依赖Common组件,或者为了防止报错也可以根据实际情况依赖其他功能组件,而在集成模式下app壳工程必须依赖所有在应用Application中声明的业务组件,并且不需要再依赖任何功能组件。
————————————————
2)功能组件和Common组件(公共依赖的库)
 
功能组件是为了支撑业务组件的某些功能而独立划分出来的组件,功能实质上跟项目中引入的第三方库是一样的,功能组件的特征如下:
 
1、功能组件的 AndroidManifest.xml 是一张空表,这张表中只有功能组件的包名;
 
2、功能组件不管是在集成开发模式下还是组件开发模式下属性始终是: com.android.library,所以功能组件是不需要读取 gradle.properties 中的 isModule 值的;另外功能组件的 build.gradle 也无需设置 buildTypes ,只需要 dependencies 这个功能组件需要的jar包和开源库。
 
 
manifest.xml重复权限问题
> Task :module_bracelet:processDebugManifest 
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml:50:5-69 Warning:
Element uses-permission#android.permission.FLASHLIGHT at AndroidManifest.xml:50:5-69 duplicated with element declared at AndroidManifest.xml:48:5-69
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml:23:9-27:56 Warning:
activity#com.tencent.bugly.beta.ui.BetaActivity@tools:name was tagged at AndroidManifest.xml:23 to replace other declarations but no other declaration present
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml:23:9-27:56 Warning:
activity#com.tencent.bugly.beta.ui.BetaActivity@tools:configChanges was tagged at AndroidManifest.xml:23 to replace other declarations but no other declaration present
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml:23:9-27:56 Warning:
activity#com.tencent.bugly.beta.ui.BetaActivity@tools:theme was tagged at AndroidManifest.xml:23 to replace other declarations but no other declaration present
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml:29:9-39:20 Warning:
provider#com.tencent.bugly.beta.utils.BuglyFileProvider@tools:name was tagged at AndroidManifest.xml:29 to replace other declarations but no other declaration present
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml:29:9-39:20 Warning:
provider#com.tencent.bugly.beta.utils.BuglyFileProvider@tools:authorities was tagged at AndroidManifest.xml:29 to replace other declarations but no other declaration present
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml:29:9-39:20 Warning:
provider#com.tencent.bugly.beta.utils.BuglyFileProvider@tools:exported was tagged at AndroidManifest.xml:29 to replace other declarations but no other declaration present
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml:29:9-39:20 Warning:
provider#com.tencent.bugly.beta.utils.BuglyFileProvider@tools:grantUriPermissions was tagged at AndroidManifest.xml:29 to replace other declarations but no other declaration present
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml Warning:
meta-data#android.support.FILE_PROVIDER_PATHS@tools:name was tagged at AndroidManifest.xml:0 to replace other declarations but no other declaration present
/Users/mac/android-bracelet/bracelet/module_bracelet/src/main/module/AndroidManifest.xml Warning:
meta-data#android.support.FILE_PROVIDER_PATHS@tools:resource was tagged at AndroidManifest.xml:0 to replace other declarations but no other declaration present

Android 中使用 fragment 提示error inflating class fragment

需要添加引用
<fragment
    android:id="@+id/frag_bracelet_debug"
    android:layout_width="match_parent"
    android:name="bracelet.yuedong.com.module_bracelet.fragment.BraceletFragment"
    android:layout_height="match_parent"></fragment>

需要解决provider的名字重复的问题
app和module切换的时候,R文件总是不一样,切换,每次自己弄?
 
 
组件生命周期的管理:
看到了你的frame里的代码实现
明白了,目前管理组件生命周期貌似只有这种方式,通过获取到绝对类名,反射调用。
 
———————————————
 
我自己的参考:
简单入门:非常好的入门
 
 
非常不错的
 
完美方案:demo不错
 
弘扬的demo
 
 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值