PrototypeZ / AppJoint

🔧 Cross module Android development made easy!
764 stars 120 forks source link

这是我非常喜欢的组件化方案,and一点小建议 #31

Open razerdp opened 5 years ago

razerdp commented 5 years ago

首先感谢作者的思路,我认为这套方案非常对我胃口,几乎无缝切换各个组件而不需要重新sync gradle简直不要太赞~非常nice的说

其次关于url,我倒是认为可以通过某个组件专门用来解析然后分发调用各组件的接口service

这次接入的时候我没有直接选择AppJoint依赖,而是参考appjoint和Arouter的思路重新写了一遍AnnotationProcessor(原谅我不怎么会写gradle-plugins TAT),在重写的过程中发现了一些可以优化的地方:

  1. 关于依赖,在多模块下,虽说大家普遍都是在root.gradle里定义ext变量,但每个子项目的gradle里都得写一遍一样的代码块,其实这部分我认为都可以抽出来到root.gradle里统一管理,我这里采取的是在root.gradle里写subprojects来管理:参考代码

  2. 关于ModuleSpec和AppSpec,读了源码感觉这两个注解似乎是为了保证module能够初始化而使用,但其实可以通过ContentProvider来进行Modules的初始化,官方大佬的LifeCycle就是这么玩的~所以我这个重构的代码里没有这两个方法,只有一个@ServiceImpl注解

  3. 关于Service的实现类,有没有一种可能会存在一个声明的Service有多个实现呢,为了兼顾这种情况,我在apt的时候解析的是HashMap<Class, SparseArray<Object>>,注解允许设定int值来决定一个tag,这样应该可以解决某个Service对应多个impl实现的问题(说不定还可以搞定优先级呢~)

  4. 关于拦截器,其实个人感觉拦截器完全可以自己在Router模块里实现的。。。不过如果有库能提供也许会更好哈哈

  5. 关于多个module组合,其实这个在我们项目里是直接预留了一个test的application,需要组合哪些就直接依赖对应的module,所以其实感觉这个问题不大

  6. 关于组件的初始化顺序,有时候不排除会有这么一种可能:先初始化某个组件,再初始化另外一个组件(比如A组件后初始化B组件),这一块目前暂时没有很好(优雅)的想法,暂留一个坑

  7. 异想天开:因为在第二点里提到了provider,这货得在manifest里声明,在这里异想天开了一下:不知道能否编译期内写入到manifest里呢(利用占位?)这里我就暂时没有去探究了哈~不过幻想总是得有的

最后这里提供一下我这边实践的工程,因为思路是参照AppJoint的,所以没必要封装为库了,只是一个实现了上面除了拦截器的实践工程:Component

最后的最后,感谢作者大大的思路,真的很棒呢

PrototypeZ commented 5 years ago

@razerdp 首先非常感谢提出如此详细的建议,非常抱歉回复较晚,一方面工作较忙,另一方面由于您的建议很具体,有一些我确实之前不是特别懂,花了一些时间调研。

  1. gradle 里的subprojects 我才发现原来这么有用,感谢你的建议,我之前有计划把现在纯 plugin 的模式,改为 apt + plugin 的模式,但是又担心配置过于麻烦,我感觉这个可以帮我节省不少配置,很赞
  2. 这两个注解确实是为了做初始化工作,而且现在已经可以支持按照 priotiy 进行初始化了。
  3. 很好的建议!我在调研期间已经支持这个功能,并已经发了新的一版
  4. 拦截器的功能我觉得交给 ARouter 这样的库去做更好,我这个小工具功能很纯粹,就是只做跨模块接口调用。良好的接口设计可以避免“拦截器”这样的需求出现。
  5. 很赞!我也是这么建议的
  6. 这个功能已经实现,但是我现在觉得可以用更好的方式实现。
  7. 使用provider进行初始化我之前考虑过,但是觉得无法控制先后顺序,但是现在经过调研,我确定可以在编译期间修改 manifest 增加任意 provider,下个版本的优化,就往这个方向走。

最后,十分感谢您的建议!

razerdp commented 5 years ago

事实上,provider的方式我当时想的是利用 android:initOrder,也就是在manifest里面写order,但是并不是很好管理也不明显。

https://developer.android.com/guide/topics/manifest/provider-element.html#init

同时要求使用者这么写其实也不太方便,所以目前除了你的priotiy 暂时没想到很好的方案。等我想到了我会来留言的-V-

PrototypeZ commented 5 years ago

@razerdp 嘿嘿,我就是看到了 initOrder 这个属性,我的思路时对用户暴露 prioiry 这个接口,实际的实现是,在编译期增加 provider 并且添加 initOrder ,用户不需要直接去操作 manifest 。我估计这个时可行的 :)

razerdp commented 5 years ago

ya,第7点建议我也是想过这个,但是想到可能会硬修改开发者的代码,所以就暂时放在一边。。。今天我去读读源码看看有木有突破点哈-V-

PrototypeZ commented 5 years ago

[捂脸]其实我一直在硬改开发者的代码 逃

razerdp commented 5 years ago

研究了一轮。。。providerinfo的order在packageParser怼入。。。无解~(hook的话就没那么好了)

既然可以写入manifest的话,可以考虑继承你的contentprovider然后编译期写入←_←但是这么高的话,还不如appjoint自己有个provider,里面管理现有的ModuleSpec的列表自己调动初始化。。用户还不用写provider呢。。。

PrototypeZ commented 5 years ago

你研究的时PackageManagerService的代码吗?

我的意思是,AppJoint 的现有的api完全不变,创建新的provider ,以及把provider 写入manifest 都由工具来做。另外,如果我自己维护一个 provider 来管理用户的注解类就和现在的实现差不多了,能交给系统来做的就交给系统去做吧,嘿嘿

cbfg5210 commented 5 years ago

之前好像有看过不建议使用 ContentProvider 来做初始化的,如果作者打算这样做的话需要了解好可能存在的消耗或者问题喔。