以下是我这个系列的相关文章,有兴趣可以参考一下,可以给个喜欢或者关注我的文章。
[Android]如何做一个崩溃率少于千分之三噶应用app--章节列表
记得我之前有介绍了一种非常适合于组件化后做插件化的框架,就是Small。
我在第九章节的时候就有介绍了Small的使用,还有深入分析Small的运行原理。
近来使用Small研发插件中,遇到一些问题,就在这里和大家讨论一下。
这里说一下Small的的一些缺陷,
(1)其不支持动态Service,Service都只能放在宿主里面了。
(2)Small暂时是只能通过冷更新(就是完全重启App时才能加载,如果有更新,当你按home键或者返回键退出,其会将整个Process杀死重启),源码中木有在运行途中增
这一篇的简书,理解难度将会加大,因为公司代码就不宜张贴啦,如果同学没有项目木有实现过插件化的,理解起来会有一定的瓶颈。
1.关于插件化选型
可以参考以下文章
基础看
深入看这个
估计看完这些你就快可以疯掉了。^_^
选型基本需要考虑的问题
1.对四大组件的支持(hook点支持)
2.so库支持
3.打包时资源冲突
4.更新方式和时机
2.插件间通信
每个插件都是基于base的module去开发,那么通过这个base module那么我们就可以通过ModuleBus或者路由的机制完成传输了。
Small本身定义的OpenUri来启动对应的模块,并未有提供可以传递各种参数的方法。
而我们是通过自定义一个PluginManager封装,类似之前介绍的分发机制去封装一个方法标志字符串标志,然后传输intent,context,viewgroup等对象,通过PluginManager遍历过滤再传输到对应的插件模块,其他需要传输的信息都可以封装到intent里面。
3.资源冗余问题
你想像一下,如果你每个工程会依赖baseApi,那么编译生成的base 的module,当生成xxx.so文件的时候,不就会出现一份冗余的base module代码和资源吗?
这个问题其实Small有自定义的编译代码,其自己写了一套编译的groovy代码,所以在编译的时候重复依赖的module移除了。
Small的编译代码,如果没点gradle构建工程基础和groovy编译想法的确不容易找到
我这里简单指明一下吧
之前说了使用DevSample查看Small的源码,这里编译的最终配使用的是AppPlugin
然后可以看到解决依赖的方法通过,过滤掉D.txt里面的所要依赖的
通过app-D.txt compile.exclude掉这些依赖的库
通过afterEvaluate最终加载这个过滤方法。
AppPlugin这里也会有将每个module里面生成的R.txt重复的资源id过滤掉,还有保留public.txt的id
这里publicEntries是保存的public.txt里面的内容,而bundle.Entries保存的是R.txt的内容的
bundleEntries是过滤掉重复的R id的算法。
如果不熟悉Gradle构建流程,也不打算深入了解的,就不需要深究了。
这里只要知道,每个module都编译的时候都共有一份D.txt R.txt和public.txt,然后small的构建会过滤掉相同的资源。然后编译出来的so文件插件运行的时候,还是通过一样的资源id来索引到公用的base module的内容。
那么为了增强每个功能模块的独立性,每个功能module都独立成为一个工程(Small的这个工程模块只是独立成一个module),那么要怎么处理才能使工程都去除资源重复呢?
这里其实也很简单,我们保证我们都依赖的自定义扩展的Small库,base的module是被宿主module引用的,那么需要保证其生产的D.txt和R.txt和public.txt,其他的module都需要持有(手动或者配置下载到其他的module里面),然后编译的时候修改加入遍历这些txt的资源文件。
4.重复触发
我在一个插件module里面发送一个信号,然后多个module都需要接受这些信号,那么如何控制其它module接收顺序,或者触发顺序调节呢?给个选择题吧
(1)插件提供判断参数给触发插件,将触发顺序的逻辑都写在触发插件里面。(这里还需要考虑如果插件不存在的判空问题)
(2)将触发的逻辑分发到其他插件,然后通过插件获取其他插件的状态(没启动或者不需要处理)而去判断是否做相应的操作
这里需要考虑到充分解耦的问题,因为代码调整的触发逻辑,控制不好我们很可能需要更替一个或者多个module,就因为一个修改就更替module,这样的设计是非常不好的。估计有人肯定觉得这些方案都不适合吧。
那么我就提供第三种方案吧。
(3)PluginManager在发送信号到其他插件时候,在发送前做过滤操作,需要过滤什么信号,就需要读取一个列表过滤列表(通过包名过滤或者信号名过滤),做成服务器可配置,那么随时都可以转换顺序触发逻辑了。
如果你看到这里有更好的解耦方案,也可以提出来,让我们继续学习。
5.全局弹框
有人是否有想过Android的弹框(自定义Dialog)是怎么弹出来的?
你想要在任意页面里面可以弹出提示的弹框需要如何做?
我们弹出弹框需要依赖于window,并且我们创建dialog的时候需要顶层Activity的Content对象
那么我们需要如何可以获取到顶层的Activity的Content对象呢?
这里面Application可以提供该顶层Activity时候的声明周期,作出回调,然后我们可以通过做成base
Module保存,其他插件获取context实现或者直接获取弹框对象。(这里面需要api level 14)
6.最重要的提醒
我们最希望的是不能让插件的任何调用会嵌入到宿主module或者其他插件的module,任何通信最好还是通过底层base module做的通信来协议来做,因为一旦木有判空,插件移除将会影响到宿主或者其他插件崩溃。
这节就到这里,希望对大家有一定的帮助。
如果你有更好的建议,请在评论中留言,我会和各位继续相互讨论,谢谢!
下一节将会更精彩!!!
我建立了一个关于Android架构学习的群,里面可以进一步进行组件化学习和架构思想的的交流。
群号是316556016,也可以扫码进群。我在这里期待你们的加入!!!
网友评论