阿里两轮面试都被问了组件化问题,你会嘛?,一名毕业三年的女程序媛面试头条经验

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
img

正文

  • 匿名的内存共享。比如用 Sharedpreferences,在处于多线程场景下,往往会线 程不安全,这种更多是存储一一些变化很少的信息,比如说组件里的配置信息等 等。

  • Intent Bundle 传递。包括显性和隐性传递,显性传递需要明确包名路径,组件 与组件往往是需要互相依赖,这背离组件化中 SOP(关注点分离原则),如果走 隐性的话,不仅包名路径不能重复,需要定义一套规则,只有一个包名路径出错, 排查起来也稍显麻烦,这个方式往往在组件间内部传递会比较合适,组件外与其 他组件打交道则使用场景不多。

说了这么多,那组件化通信什么机制比较适合呢?既然组件层中的模块是相互独 立的,它们之间并不存在任何依赖。没有依赖就无法产生关系,没有关系,就无 法传递消息,那要如何才能完成这种交流?

目前主流做法之一就是引入第三者,比如图中的 Base Module。

基础组件化架构

组件层的模块都依赖于基础层,从而产生第三者联系,这种第三者联系最终会编 译在 APP Module 中,那时将不会有这种隔阂,那么其中的 Base Module 就是 跨越组件化层级的关键,也是模块间信息交流的基础。比较有代表性的组件化开 源框架有得到 DDComponentForAndroid、阿里 Arouter、聚美 Router 等等。

除了这种以通过引入第三者方式,还有一种解决方式是以事件总线方式,但这种 方式目前开源的框架中使用比例不高,如图:

事件总线

事件总线通过记录对象,使用监听者模式来通知对象各种事件,比如在现实生活 中,我们要去找房子,一般都去看小区的公告栏,因为那边会经常发布一些出租 信息,我们去查看的过程中就形成了订阅的关系,只不过这种是被动去订阅,因 为只有自己需要找房子了才去看,平时一般不会去看。小区中的公告栏可以想象 成一个事件总线发布点,监听者则是哪些想要找房子的人,当有房东在公告栏上 贴上出租房信息时,如果公告栏有订阅信息功能,比如引入门卫保安,已经把之 前来这个公告栏要查看的找房子人一一进行电话登记,那么一旦有新出租消息产 生,则门卫会把这条消息一一进行短信群发,那么找房子人则会收到这条消息进 行后续的操作,是马上过来看,还是延迟过来,则根据自己的实际情况进行处理。 在目前开源库中,有 EventBus、RxBus 就是采用这种发布/订阅模式,优点是简 化了 Android 组件之间的通信方式,实现解耦,让业务代码更加简洁,可以动态 设置事件处理线程和优先级,缺点则是每个事件需要维护一个事件类,造成事件 类太多,无形中加大了维护成本。那么在组件化开源框架中有 ModuleBus、CC 等 等。

这两者模式更详细的对比,可以查看这篇文章多个维度对比一些有代表性的开源 android 组件化开发方案

实现方案

事件总线,又可以叫做组件总线,路由+接口,则相对好理解点,今天从阅读它 们框架源码,我们来对比这两种实现方案的不同之处。

组件总线

这边选取的是 ModuleBus 框架,这个方案特别之处在于其借鉴了 EventBus 的思 想,组件的注册/注销和组件调用的事件发送都跟 EventBus 类似,能够传递一些 基础类型的数据,而并不需要在 Base Moudel 中添加额外的类。所以不会影响 Base 模块的架构,但是无法动态移除信息接收端的代码,而自定义的事件信息 类型还是需要添加到 Base Module 中才能让其他功能模块索引。

其中的核心代码是在与 ModuleBus 类,其内部维护了两个 ArrayMap 键对值列 表,如下:

private static ArrayMap<Object,ArrayMap<String,MethodInfo>>

moduleEventMethods = new ArrayMap<>();

private static ArrayMap<Class<?>,ArrayMap<String,ArrayList>>

moduleMethodClient = new ArrayMap<>()

在使用方法上,在 onCreate()和 onDestroy()中需要注册和解绑,比如

ModuleBus.getInstance().register(this);

ModuleBus.getInstance().unregister(this);

最终使用类似 EventBus 中 post 方法一样,进行两个组件间的通信。这个框架 的封装的 post 方法如下

public void post(Class<?> clientClass,String methodName,Object…args){

if(clientClass == null || methodName == null ||methodName.length() == 0) return;

ArrayList clientList = getClient(clientClass,methodName)

for(Object c: clientList){ ArrayMap<String,MethodInfo> methods = moduleEventMethods.get©;

Method method = methods.get(methodName).m;

method.invoke(c,args);

}

可以看到,它是通过遍历之前内部的 ArrayMap,把注册在里面的方法找出,根据传入的参数进行匹配,使用反射调用。

接口+路由

接口+路由实现方式则相对容易理解点,我之前实践的一个项目就是通过这种方 式实现的。具体地址如下:DemoComponent 实现思路是专门抽取一个 LibModule 作为路由服务,每个组件声明自己提供的服务 Service API,这些 Service 都是一些接口,组件负责将这些 Service 实现并注册到一个统一的路由 Router 中去,如果要使用某个组件的功能,只需要向 Router 请求这个 Service 的实现,具体的实现细节我们全然不关心,只要能返回我们需要的结果就可以了。 比如定义两个路由地址,一个登陆组件,一个设置组件,核心代码:

public class RouterPath {

public static final String ROUTER_PATH_TO_LOGIN_SERVICE = “/login/service”;

public static final String ROUTER_PATH_TO_SETTING_SERVICE = “/setting/service”; }

那么就相应着就有两个接口 API,如下:

public interface ILoginProvider extends IProvider {

void goToLogin(Activity activity);

}

public interface ISettingProvider extends IProvider {

void goToSetting(Activity activity);

}

}

这两个接口 API 对应着是向外暴露这两个组件的能提供的通信能力,然后每个组 件对接口进行实现,如下:

@Override

public void init(Context context) {

}

@Override

public void goToLogin(Activity activity) {

Intent loginIntent = new Intent(activity, LoginActivity.class);

activity.startActivity(loginIntent);

}

}

这其中使用的到了阿里的 ARouter 页面跳转方式,内部本质也是接口+实现方式 进行组件间通信。

调用则很简单了,如下:

ILoginProvider loginService = (ILoginProvider)

ARouter.getInstance().build(RouterPath.ROUTER_PATH_TO_LOGIN_SERVICE).naviga tion();

if(loginService != null){

loginService.goToLogin(MainActivity.this);

}

还有一个组件化框架,就是 ModularizationArchitecture ,它本质实现方式也是 接口+实现,但是封装形式稍微不一样点,它是每个功能模块中需要使用注解建 立 Action 事件,每个 Action 完成一个事件动作。invoke 只是方法名为反射,并 未用到反射,而是使用接口方式调用,参数是通过 HashMap 传递的,无法传递 对象。具体详解可以看这篇文章 Android 架构思考(模块化、多进程)。,string>

页面跳转

页面跳转也算是一种组件间的通信,只不过它相对粒度更细化点,之前我们描述 的组件间通信粒度会更抽象点,页面跳转则是定位到某个组件的某个页面,可能 是某个 Activity,或者某个 Fragment,要跳转到另外一个组件的 Activity 或 Fragment,是这两者之间的通信。甚至在一般没有进行组件化架构的工程项目 中,往往也会封装页面之间的跳转代码类,往往也会有路由中心的概念。不过一 般 UI 跳转基本都会单独处理,一般通过短链的方式来跳转到具体的 Activity。 每个组件可以注册自己所能处理的短链的 Scheme 和 Host,并定义传输数据的 格式,然后注册到统一的 UIRouter 中,UIRouter 通过 Scheme 和 Host 的匹 配关系负责分发路由。但目前比较主流的做法是通过在每个 Activity 上添加注 解,然后通过 APT 形成具体的逻辑代码。

下面简单介绍目前比较主流的两个框架核心实现思路:

最后说一下我的学习路线

其实很简单就下面这张图,含概了Android所有需要学的知识点,一共8大板块:

  1. 架构师筑基必备技能
  2. Android框架体系架构(高级UI+FrameWork源码)
  3. 360°Androidapp全方位性能调优
  4. 设计思想解读开源框架
  5. NDK模块开发
  6. 移动架构师专题项目实战环节
  7. 移动架构师不可不学习微信小程序
  8. 混合开发的flutter

Android学习的资料

我呢,把上面八大板块的分支都系统的做了一份学习系统的资料和视频,大概就下面这些,我就不全部写出来了,不然太长了影响大家的阅读。

330页PDF Android学习核心笔记(内含上面8大板块)

Android学习的系统对应视频

总结

我希望通过我自己的学习方法来帮助大家去提升技术:

  • 1、多看书、看源码和做项目,平时多种总结

  • 2、不能停留在一些基本api的使用上,应该往更深层次的方向去研究,比如activity、view的内部运行机制,比如Android内存优化,比如aidl,比如JNI等,并不仅仅停留在会用,而要通过阅读源码,理解其实现原理

  • 3、同时对架构是有一定要求的,架构是抽象的,但是设计模式是具体的,所以一定要加强下设计模式的学习

  • 4、android的方向也很多,高级UI,移动架构师,数据结构与算法和音视频FFMpeg解码,如果你对其中一项比较感兴趣,就大胆的进阶吧!

希望大家多多点赞,转发,评论加关注,你们的支持就是我继续下去的动力!加油!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

希望大家多多点赞,转发,评论加关注,你们的支持就是我继续下去的动力!加油!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-n0gR7LDf-1713370730683)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值