Android 组件化方案 JIMU 体验

JIMU运行指南

项目地址 https://github.com/mqzhangw/JIMU

当时项目最初运行报错
java.lang.IllegalAccessError: tried to access method org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.

android studio 版本3.4.1中采用3.3版本的gradle 编译成功
#distributionUrl=https://services.gradle.org/distributions/gradle-5.1.1-all.zip
distributionUrl=https://services.gradle.org/distributions/gradle-3.3-all.zip

增加图片显示后app的运行效果
在这里插入图片描述

JIMU使用指南

JIMU有两个工程jimu-core和jimu-sample-project
jimu-core 是jimu 核心功能库,有路由支持、注解、gradle构建优化,分为以下模块router-annotation 、router-anno-compiler 、componentlib 、build-gradle

jimu-sample-project 演示jimu使用

app是主项目,负责集成众多组件,控制组件的生命周期
reader和share是我们拆分的两个组件
componentservice中定义了所有的组件提供的服务
basicres定义了全局通用的theme和color等公共资源
basiclib中是公共的基础库,一些第三方的库(okhttp等)也统一交给basiclib来引入

1、单独调试和发布

为了避免不同组件之间资源名重复,在每个组件的build.gradle中增加resourcePrefix “xxx_”,从而固定每个组件的资源前缀。

Android Studio中,是可以看到多个application工程的,随便点击一个都是可以独立运行的,并且可以根据配置引入其他需要依赖的组件。
这背后的工作都由com.dd.comgradle插件来默默完成。以下是单独运行时的启动页面

readercomponent
com.luojilab.reader/com.luojilab.reader.runalone.ReaderTestActivity

sharecomponent
com.luojilab.share/com.luojilab.share.BookShareEditActivity

app
com.luojilab.androidcomponent/com.luojilab.componentdemo.MainActivity

2、组件交互

在这里组件的交互专指组件之间的数据传输,在我们的方案中使用的是接口+实现的方式,组件之间完全面向接口编程。
在demo中我们让reader提供一个fragment给app使用来说明。首先reader组件在componentservice中定义自己的服务

public interface ReadBookService {
    Fragment getReadBookFragment();
}

然后在自己的组件工程中,提供具体的实现类ReadBookServiceImpl:

public class ReadBookServiceImpl implements ReadBookService {
    @Override
    public Fragment getReadBookFragment() {
        return new ReaderFragment();
    }
}

提供了具体的实现类之后,需要在组件加载的时候把实现类注册到Router中,具体的代码在ReaderAppLike中,ReaderAppLike相当于组件的application类,这里定义了onCreate和onStop两个生命周期方法,对应组件的加载和卸载。

public class ReaderAppLike implements IApplicationLike {
    Router router = Router.getInstance();
    @Override
    public void onCreate() {
        router.addService(ReadBookService.class.getSimpleName(), new ReadBookServiceImpl());
    }
    @Override
    public void onStop() {
        router.removeService(ReadBookService.class.getSimpleName());
    }
}

在app中如何使用如reader组件提供的ReaderFragment呢?注意此处app是看不到组件的任何实现类的,它只能看到componentservice中定义的ReadBookService,所以只能面向ReadBookService来编程。具体的实例代码如下:

Router router = Router.getInstance();
if (router.getService(ReadBookService.class.getSimpleName()) != null) {
    ReadBookService service = (ReadBookService) router.getService(ReadBookService.class.getSimpleName());
    fragment = service.getReadBookFragment();
    ft = getSupportFragmentManager().beginTransaction();
    ft.add(R.id.tab_content, fragment).commitAllowingStateLoss();
}

这里需要注意的是由于组件是可以动态加载和卸载的,因此在使用ReadBookService的需要进行判空处理。我们看到数据的传输是通过一个中央路由Router来实现的,这个Router的实现其实很简单,其本质就是一个HashMap,具体代码大家参见源码。

通过上面几个步骤就可以轻松实现组件之间的交互,由于是面向接口,所以组件之间是完全解耦的。至于如何让组件之间在编译阶段不不可见,是通过com.dd.comgradle实现的

3、UI跳转

页面(activity)的跳转也是通过一个中央路由UIRouter来实现。
master-arouter分支采用ARouter
Android路由框架ARouter
https://github.com/alibaba/ARouter

4、集成调试

android studio 当前项目配置默认可以集成调试
android studio Build → Generate Signed APK release版本正常生成

5、代码边界

至于依赖的组件是如何集成到host中的,其本质还是直接使用compile project(…)或者compile modulePackage:module@aar。那么为啥不直接在build.gradle中直接引入呢,而要经过com.dd.comgradle这个插件来进行诸多复杂的操作?
那就是组件之间的完全隔离,也可以称之为代码边界。如果我们直接compile组件,那么组件的所有实现类就完全暴露出来了,
使用方就可以直接引入实现类来编程,从而绕过了面向接口编程的约束。这样就完全失去了解耦的效果了,可谓前功尽弃。
那么如何解决这个问题呢?我们的解决方式还是从分析task入手,只有在assemble任务的时候才进行compile引入.具体的代码实现在jimu-core 中build-gradle

6、生命周期

在什么时机加载组件以及如何加载组件?目前com.dd.comgradle提供了两种方式,字节码插入和反射调用。
字节码插入模式是在dex生成之前,扫描所有的ApplicationLike类(其有一个共同的父类),然后通过javassist在主项目的Application.onCreate()中插入调用ApplicationLike.onCreate()的代码。这样就相当于每个组件在application启动的时候就加载起来了。
反射调用的方式是手动在Application.onCreate()中或者在其他合适的时机手动通过反射的方式来调用ApplicationLike.onCreate()。之所以提供这种方式原因有两个:对代码进行扫描和插入会增加编译的时间,特别在debug的时候会影响效率,并且这种模式对Instant Run支持不好;另一个原因是可以更灵活的控制加载或者卸载时机。
这两种模式的配置是通过配置com.dd.comgradle的Extension来实现的,下面是字节码插入的模式下的配置格式,添加applicationName的目的是加快定位Application的速度。

combuild {
    applicationName = 'com.mrzhang.component.application.AppApplication'
    isRegisterCompoAuto = true
}

demo中也给出了通过反射来加载和卸载组件的实例,在APP的首页有两个按钮,一个是加载分享组件,另一个是卸载分享组件,在运行时可以任意的点击按钮从而加载或卸载组件,具体效果大家可以运行demo查看。

参考:

Android彻底组件化方案实践
Android彻底组件化demo发布

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值