昨天被HR约面,原本约下个星期,我询问能不能早点面试,就约到了今天下午
面试前,上一场还有一个其他的面试,赶的比较急。
面试体验很不错,但是面试官有点严肃(不怎么笑),我总以为是因为我回答的不在点子上,一直都担心害怕
哦!B站没有笔试,直接约面的!前天看流程还是待测试之类的,结果后面就电话约面了。
面试内容:
- 看你有使用插件化,说一下你们实现的基本原理
- 插件化是将一个apk根据业务功能拆分成不同的子apk,插件化更关注动态加载、热更新
- 实现的是动态加载,用到某个模块的时候才去加载它
- 对于类的加载classloader
- 底层依赖于DexClassLoader,它里面的构造方法入参会有dexPath,optimizedDirectory等参数会指定加载类的地址,于是可以实现指定加载哪些类,进而实现动态加载的能力
- 对于资源的加载(这块不是很懂,是下来之后了解的)
- 反射调用AssetsManager的addAssetPath方法;
- 将外部的apk路径添加进去,构建新的Resource对象
- 通过classloader加载R.java获取drawable,对应的id
- 通过上述构建的Resource获取drawable对象。
- 热更新你们怎么去实现的呢?
- 腾讯的Tinker框架
- 动态加载类,插件的apk类文件,宿主是不会去加载的,框架去调用classloader加载这些类
- Tinker的实现原理就是把这些生成新的补丁包全部替换掉,在DexPathList 的实现里,有一个 Element[] dexElements 变量,这里面保存了所有的 dex。在加载 Class 的时候,就遍历 dexElements 成员,依次查找 Class,找到以后就返回然后替换。
- 原理和dex插桩一样
- Java volatile相关的
- 保证可见性,当一个变量被声明为volatile时,任何对该变量的修改都会立即被写入主内存,同时其他线程在读取该变量时会直接从主内存中获取最新的值
- 比如现在有一个变量i被volatile声明了,i++,需不需要加锁?
- 需要,i++不是一个原子操作,是三个执行步骤,volatile不能保证原子性
- Android常见的跨进程通信
- 管道
- intent,startActivity()里面传入的隐式Intent,跨activity通信
- Binder
- ContentProvider
- AIDL
- Android使用Binder跨进程通信的优势?
- Binder底层是在内核空间使用内存映射,进行跨进程通信
- 优势:
- 效率高,因为使用的内核空间,数据拷贝只需要一次,管道和socket都需要两次
- 安全,有UID/PID身份识别,socket这种就访问ip是客户端手动输入,就有可能造伪
- 面向对象的思想,使用比较方便
- handler的原理
- 一顿输出
- handler为什么不能跨进程通信
- 因为会有进程隔离
- Android min、compile、target版本的区别
- compileSdkVersion 告诉 Gradle 用哪个 Android SDK 版本编译你的应用
- 那么 minSdkVersion 则是应用可以运行的最低要求
- targetSdkVersion 是 Android 提供向前兼容的主要依据,系统判断能兼容到哪些版本
- App启动流程
- 不太了解,简单说了一点
- activity的启动模式
- 四种还有Android12最新的一种
- 一个应用已经死掉了,冷启动会把之前的栈拉起来吗?
- 应该不会,会重新创建一个activity栈
算法题:三数之和,双指针做的,去重遍历
反问,技术方向,负责内容等
#B站信息集散地#
#许愿##Android面经##客户端面经##哔哩哔哩面经#