java 轻量级插件化框架_轻量级插件化框架——Small

7990714d10cb

photo-1441716844725-09cedc13a4e7.jpg

前言

世界那么大,组件那么小。Small,做最轻巧的跨平台插件化框架。 ——Galenlin

这是Small作者,林光亮老师,给Small一句概括。

今年6月份,我和同事Simon奔赴北京参加 GMTC全球移动技术大会2016。当时Galenlin给大家介绍了Small插件化框架,插件化加载dex、资源拆分、hook.....

回广州后,对Small做了几个实验性demo,不禁赞叹Small真的非常简洁,而且基本能满足 APP组件化需求。

Small完成什么使命?

组件化,既熟悉又陌生的词汇。通俗点说,就是把APP拆分成不同功能模块,形成独立组件,让宿主调用。

组件化不一定是插件化,组件化是一个更大的概念:把模块解耦,组件之间代码不依赖,宿主可以依赖组件;而插件化则具体到了技术点上,宿主通过 动态加载 来调用组件,宿主不依赖组件,达到 完全解耦 的目的。

Small插件化方案适用于将一个APK拆分为多个公共库插件、业务模块插件的场景。

框架对比

Android插件化框架有很多,相信Dynamic-load-apk、ACDD、DroidPlugin 如雷贯耳。

DyLA : Dynamic-load-apk @singwhatiwanna, 百度

DiLA : Direct-Load-apk @FinalLody

APF : Android-Plugin-Framework @limpoxe

ACDD : ACDD @bunnyblue

DyAPK : DynamicAPK @TediWang, 携程

DPG : DroidPlugin @cmzy, 360

功能

/

DyLA

DiLA

ACDD

DyAPK

DPG

APF

Small

加载非独立插件[1]

×

x

×

加载.so后缀插件

×

×

! [2]

×

×

×

Activity生命周期

Service动态注册

×

×

×

x [3]

资源分包共享[4]

×

×

! [5]

! [5]

×

! [6]

公共插件打包共享[7]

×

×

×

×

×

×

支持AppCompat[8]

×

×

×

×

×

×

支持本地网页组件

×

×

×

×

×

×

支持联调插件[9]

×

x

×

×

×

×

Small初体验

1.Create Project

假设宿主包名为com.example.mysmall

设置Application name为MySmall

修改Company Domain为mysmall.example.com

7990714d10cb

create project.png

2.配置build.gradle

对project/build.gradle修改如下:

buildscript {

repositories {

jcenter()

}

dependencies {

classpath 'com.android.tools.build:gradle:2.1.2'

classpath 'net.wequick.tools.build:gradle-small:1.0.0-beta3'

}

}

apply plugin: 'net.wequick.small'

small {

aarVersion = '1.1.0-beta1'

}

...

(com.android.tools.build:gradle用回你Android Studio支持的gradle插件版本)

aarVersion、net.wequick.tools.build:gradle-small版本号,可以参照Small官方sample的build.gradle。sample

3.新建Application

new SmallApp

public class SmallApp extends Application {

@Override

public void onCreate() {

super.onCreate();

Small.preSetUp(this);

Small.setBaseUri("http://example.com/");// 浏览器跳转url

Small.setUp(this, null);

// Small.setUp(this, new Small.OnCompleteListener(){...});

}

}

AndroidManifest.xml:

android:name=".SmallApp"

...

>

4.新建 插件Module

File->New->Module,选择Phone & Tablet Module:

Application Name: App.main

Module name: app.main

package name: com.example.mysmall.app.main

如果选择Android Library,app.*换成lib.*

7990714d10cb

new module app.main.png

Small要求插件module满足:

模块名形如:app.* , lib.* 或者web.*

包名包含:.app., .lib.或者.web.

Add an Activity to Mobile选择最简单的Empty Activity即可(其他也可以)。

除了默认MainActivity,顺手创建多个ActivityB吧。

5.配置UI route

新建assets/bundle.json:

{

"version": "1.0.0",

"bundles": [

{

"uri": "main",

"pkg": "com.example.mysmall.app.main",

"rules": {

"page2": ".ActivityB"

}

}

]

}

uri : 跳转Activity需要的uri

pkg : 插件模块包名

rules : 指定跳转的Activity

6.跳转到插件Activity

@Override

public void onClick(View view) {

Small.openUri("main", this); // open bundles.main Launch Activity

// Small.openUri("main/page2", context);// 指定跳转到app.main.page2

}

调用openUri后,就可以跳转到插件的某个Activity了。

7.编译插件

1)Build libraries (准备基础库)

gradlew buildLib

7990714d10cb

buildLib_appmain.gif

如果插件module是Android Library,这时会生成app/smallLibs/armeabi/*.so

2)Build bundles (打包所有组件)

gradlew buildBundle

7990714d10cb

buildBundle_appmain.gif

生成app/smallLibs/armeabi/libcom_example_mysmall_app_main.so

7990714d10cb

so文件.png

运行

由于project有两个Phone & Tablet Module,运行时要选app噢

7990714d10cb

5 - run config.png

使用效果

你会发现,宿主app没有依赖app.main,仅仅把app.main编译成so文件, 宿主app就可以跳转到插件app.main页面了。这就是插件化的魅力——零依赖!

遇到的问题

之前遇到一个很奇葩的问题,如图:

7990714d10cb

some error

解决方法:

gradlew cleanLib

bradlew cleanBundle

重新buildLib、buildBundle即可

还试过运行时提示“找不到app/MainActivity”,解决:File->Invalidate Caches/Restart清一下缓存再重启AS就好了。

小结

Small算是最简单的插件化框架,如果你的project本来就已经组件化到一定程度,使用Small轻而易举。

由于笔者还未试过在实际项目中使用,可能有些潜在的坑未踩。Small的更新也是蛮积极的,目前大概一个月更新一次,在交流Q群&issue,Galenlin回应也很积极。

强烈建议大家看看Small Issue,了解大家在使用中遇到的问题,以及Galenlin和其他人提出的解决方案。目前就4页,中文的,不会太多哈哈。

笔者相信,未来半年一年,Small会更稳定、更容易在项目中集成,让我们更爽地体验插件化的优势!

推荐阅读:

关于转载

如果你想转载此文,请务必在转载时,加上原文作者&原文链接。谢谢


版权声明:本文为weixin_35972313原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。