RouterModule
dependencies {
compile fileTree(include: [‘*.jar’], dir: ‘libs’)
compile project(‘:modulelib’)
compile ‘com.alibaba:arouter-api:1.2.1.1’
}
RouterModule依赖了LibraryModule
BaseModule
dependencies {
compile fileTree(include: [‘*.jar’], dir: ‘libs’)
testCompile ‘junit:junit:4.12’
compile project(‘:librarymodule’)
}
BaseModule作为一个基础库,依赖了LibraryModule
LibraryModule
这个作为最底层的劳苦大众,实际上就是提供了一个依赖,所以就没有什么好依赖,只能自己跟自己玩儿。
所以到这里的话,基本的依赖关系已经很清楚了,知道了整个架构图,接下来进行施工也就很简单了
组件通信
其实在当初进行模块划分的时候,是根据业务来的,所以当我们进入到一个模块之后,大部分逻辑应该还是在这个模块内进行处理的,但是偶尔还是会跟别的Module进行打交道,看一个界面
就拿GoodsModule跟CartModule来说,这两个Module是可以进行相互跳转的,在GoodsModule的列表页面点击购物车图标可以进入到CartModule的购物车列表,购物车列表点击商品也可以进入GoodsModule的商品详情页。除了这个跳转实际上还有变量的获取,比如在首页,我需要同时获取到GoodsModule中的HomeFragment、SortFragment,CartModule中的CartFragment,UserModule中的MineFragment。我是在MainModule中直接依赖了四个业务Module,实际上可以不这样,我们也可以使用Arouter来进行获取Fragment的实例。
获取实例
其实这里的实例大多数情况下指的就是Fragment,下面以Fragment为例,别的实例如法炮制即可
- 反射获取
由于模块间是隔离的,所以我们没办法直接创建Fragment的实例,那么这个时候其实很容易想到的就是反射,发射可谓无所不能,下面贴一下代码。
//获取Fragment实例
public static Fragment getFragment(String className) {
Fragment fragment;
try {
Class fragmentClass = Class.forName(className);
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
return fragment;
}
- Arouter
Arouter是阿里巴巴退出的一款路由框架,在组件中进行路由操作表方便,下面举例说明
目标Fragment中加入注解
@Route(path = “cart/fragment”)
public class CartFragement extends BaseFragment{
}
在任何地方获取实例
Fragmetn fragment = (Fragment) ARouter.getInstance().build(“/cart/fragment”).navigation();
方法调用
在不同的Module之间都存在方法的调用,我们可以在每个Module里面定义一个接口,并且实现这个接口,然后在需要调用的地方获取到这个接口,然后进行方法调用即可。为了统一管理,我们把每个Module的接口都定义在RouterModule里面,然后由于各个业务Module都依赖于这个RouteModule,然后只需要通过反射获取到这个接口,进行方法调用就可以了。
ModuleCall
Module之间回调的接口
public interface ModuleCall {
//调用init方法可以传递Context参数
void initContext(Context context);
}
Service接口继承自ModuleCall可以定义一些回调方法供本身之外的其他Module进行调用
public interface AppService extends ModuleCall {
//TODO 调用方法自定义
void showHome();
void finish();
}
Impl实现类则是对应在每个Module中的具体回调,是实现Service接口的直接子类
public class AppServiceImpl implements AppService {
@Override
public void showHome() {
}
@Override
public void finish() {
}
@Override
public void initContext(Context context) {
}
}
下面还是通过反射跟Arouter两种方式进行说明
- 反射调用
public static Object getModuleCall(String name) {
T t;
try {
Class aClass = Class.forName(name);
t = (T) aClass.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
return t;
}
获取接口
AppService appService = (AppService) ReflectUtils.getModuleCall(Path.APP_SERVICE);
其实跟获取Fragment实例一样,通过类名来获取对应的接口,然后调用对应的方法就行,有一点需要注意的就是,如果获取的接口之后调用的方法需要传入Context参数,那么在调用接口方法之前必须先调用initContext方法才能使用传入的Context,不然会报空指针异常。
- Arouter
Arouter中有一个IProvider接口,如下
public interface IProvider {
void init(Context var1);
}
其实IProvider跟上面的ModuleCall是一样的,只不过他在获取到接口实例之后,就会调用initContext方法,其中的Context来自ARouter.init(this)中传入的参数,不需要我们再手动调用initContext。
目标类中注入路径
@Route(path = Path.APP_SERVICE)
public class AppServiceImpl implements AppService {
private Context mContext;
@Override
public void showHome() {
Log.d(“go—>”, “home—>”);
}
@Override
public void finish() {
}
@Override
public void init(Context context) {
mContext = context;
}
}
任意地方获取目标类
AppService appService = (AppService) RouterUtils.navigation(Path.APP_SERVICE);
然后调用方法即可
UI跳转
跳转基本上指的就是Activity之间的跳转,废话不多说,依旧是Arouter跟反射
- 反射
//将类名转化为目标类
public static void startActivityWithName(Context context, String name) {
try {
Class clazz = Class.forName(name);
startActivity(context, clazz);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
//获取Intent
public static Intent getIntent(Context context, Class clazz) {
return new Intent(context, clazz);
}
//启动Activity
public static void startActivity(Context context, Class clazz) {
context.startActivity(getIntent(context, clazz));
}
- Arouter
将目标Activity注册到Arouter
@Route(path = Path.CART_MOUDLE_CART)
public class CartActivity extends BaseActivity<UselessPresenter, UselessBean> {
}
启动目标Activity
ARouter.getInstance().build(Path.CART_MOUDLE_CART).navigation()
入口参数
Application
当组件单独运行的时候,每个Module自成一个APK,那么就意味着会有多个Application,很显然我们不愿意重复写这么多代码,所以我们只需要定义一个ModuleApplication即可,其它的Application直接继承此ModuleApplication就OK了,看一下结构图:
实际上所有的逻辑都是在ModuleApplication中,业务Module分别有自己的子类,通过子类可以对Application做一些自己的定制化操作。
无参原因
之前在网上看到过携程以及得到的组件化,他们从MainModule进入到别的Module貌似都是不需要传参数的,所以不管是组件单独调试还是所有的Module一起远行对于从ModuleA跳转到ModuleB都是不需要传参的。但是很多时候不同的Module间跳转是需要传参的,就拿购物车来说,我单独调试的时候是需要知道用户的加密的userId,才能向服务器请求数据,如果是多个Module一起运行,访问购物车的时候,是可以从别的Module取到userId的,单独调试的时候就没法获取到,也就是入口的时候没有参数对购物车进行初始化。
解决方式
因为当我们在组件化进行调试的时候,我们每个Module在cartmodule/src/main/debug目录下有自己的Application,对于入口参数比较简单的情况,我们可以直接在Application中写死,而对于一些比较复杂的或者动态的参数,我们可以继续在此目录下新疆一个Activity来配置我们单Module调试所需要的参数,然后在整个项目进行编译的时候剔除debug目录下的文件。
sourceSets {
main {
if (isModuleRun.toBoolean()) {
manifest.srcFile ‘src/main/debug/AndroidManifest.xml’
} else {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
总结
可以看出,笔者的工作学习模式便是由以下 「六个要点」 组成:
❝ 多层次的工作/学习计划 + 番茄工作法 + 定额工作法 + 批处理 + 多任务并行 + 图层工作法❞
希望大家能将这些要点融入自己的工作学习当中,我相信一定会工作与学习地更富有成效。
下面是我学习用到的一些书籍学习导图,以及系统的学习资料。每一个知识点,都有对应的导图,学习的资料,视频,面试题目。
**如:我需要学习 **Flutter的知识。(大家可以参考我的学习方法)
点击这里了解更多即可领取!
- Flutter 的思维导图(无论学习什么,有学习路线都会事半功倍)
- Flutter进阶学习全套手册
- Flutter进阶学习全套视频
点击这里了解更多即可领取!
- Flutter 的思维导图(无论学习什么,有学习路线都会事半功倍)
[外链图片转存中…(img-BnteMkF8-1711174235621)]
- Flutter进阶学习全套手册
[外链图片转存中…(img-IIrSsGSs-1711174235622)]
- Flutter进阶学习全套视频
[外链图片转存中…(img-yZtA0Lwb-1711174235622)]文章来源:https://www.toymoban.com/news/detail-854015.html
大概就上面这几个步骤,这样学习不仅高效,而且能系统的学习新的知识。文章来源地址https://www.toymoban.com/news/detail-854015.html
到了这里,关于Architecture(5)电商APP组件化探索,差点无缘Offer的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!