接口过多,一定程度影响了编码效率。一定程度上导致Presenter的代码量过大。
为了降低Presenter中业务繁多的问题,Google又推出了MVVM,试图通过数据驱动来减少Presenter的代码量。
1.3 架构设计模式-MVVM
(1) 定义
-
M(Model)层:仍然是
实体模型
(但是不同于之前定义的Model层),主要负责数据获取、存储和变化,提供数据接口供 ViewModel 层调用。 -
V(View)层:对应
Activity/Feagment
和xml布局
文件 ,负责View的绘制以及与用户交互
说明:View层仅能操作UI(数据绑定来实现 UI 更新);不能做任何和业务逻辑有关的数据操作
- VM(ViewModel)层:负责完成Model层和View层间的数据
交互
和业务逻辑
说明:ViewModel层仅能做和业务逻辑有关的数据操作;不能做UI相关的操作
============================================================================
插件化来由:随着业务的增多,业务逻辑代码越来越多,apk包也逐渐增大,不利于维护和升级。通过插件化开发可将功能模块解耦,不同的维护团队仅维护某模块的业务,同时当app升级时可仅对某功能模块进行升级而不需整体升级。
2.1 插件化要解决的问题—如何动态加载apk
(1) android类加载器及区别
类加载器作用:java字节码通过类加载器加载到java虚拟器。
-
PathClassLoader:仅能加载文件目录下的apk。
-
DexClassLoader:可以加载apk文件中的字节码(从dex实体jar文件中加载java字节码)。主要用于动态加载和代码热更新等。
(2)反射: java中的反射使我们在运行时获得这个类的属性、方法和class内部的信息机制,最重要的是我们可以在运行时实例化这个对象调用方法,这也是java反射的最大优点。
(3) 实现动态加载apk
什么是动态加载apk:android中有一个速度程序会主动到指定的sd卡中去加载apk,并通过代理activity去执行。
实现:需要一个代理activity去执行apk中的activity,主要通过反射去获得它的属性和方法,从而进行apk的调用。
实现原理:类加载器
(加载类)+反射
(获取属性和方法)+动态代理
(执行)
如:
2.2 插件化要解决的问题—如何加载资源
通过android中ServiceManager类的隐藏方法来加载资源。
2.3 插件化要解决的问题—如何加载代码
使用java中的类加载机制,但是android和java也有一点不一样,android比java多了组件和生命周期,所以并不是类加载进来就能使用(不能管理生命周期)。
=====================================================================================
(1) 热更新流程
-
检测到线上严重的crash(参考:app检测crash并发送日志到服务器的实现)
-
线上版本拉出bugfix分支并在分支上修复问题
-
jenkins构建及生成补丁
-
app在合适时机通过推送或主动拉取补丁文件
-
将bugfix代码合并到master上
(2) 热更新主流框架
-
Dexposed
-
AndFix
-
NuWa
(3) 热更新原理
- Android类加载机制(类加载器)
PathClassLoader类:用来加载系统类
DexClassLoader:用来加载dex文件、jar文件包和apk包等
- 热修复机制(原理)
原理:在ClassLoader中创建一个dexElements数组,根据线上的crash定位找到对应的类文件,然后把这个类文件修复完成后打包成一个dex文件并放到dexElements数组的最前方。那么当ClassLoader遍历dexElements数组(加载数组中的dex文件)时,因为ClassLoader会优先加载最前方的dex文件,所以不会加载线上有crash的dex文件,只会加载修复完的dex文件,从而完成热修复过程。
=============================================================================
(1) 进程保活概念
进程保活:让进程在
内存
中永远存在且无法杀死,就算被杀死也能保活。
进程被杀死的原因:人为地调用kill;被第三方安全软件杀死。
进程保活并非是一种流氓手段,在很多场景下我们需要一个常驻进程来为用户提供服务,如:
- 接收屏幕开关的系统广播:因为广播接收者不支持静态注册,必须在进程中动态注册广播接收者来接收,如果没有常驻进程,那么锁屏应用无法为用户正常提供服务。
- 定位服务:需要在后台维护一个长连接,以便及时地将信息(推送的信息/定位信息等)传达给用户。
缺点:进程保活在内存,不管如何优化,或多或少都会增加性能的开销。所以需在
进程保活
和内存消耗
之间寻找平衡点来为用户进程保活。
(2) android进程优先级和回收策略
- android进程优先级:前台进程 > 可见进程 > 服务进程 > 后台进程 > 空进程
- android进程的回收策略:主要依靠LMK ( Low Memory Killer )机制来完成。LMK机制通过 oom_adj 这个阀值来判断进程的优先级,oom_adj 的值越高,优先级越低,越容易被杀死。
`拓展`:LMK ( Low Memory Killer ) 机制基于Linux的OOM(Out Of Memery)机制,通过一些比较复杂的评分机制,对进程进行打分,将分数高的进程判定为bad进程,杀死并释放内存。LMS机制和OOM机制的不同之处在于:OOM只有当系统内存不足时才会启动检查,而LMS机制是定时进行检查。
(3) android进程保活方案
- 利用系统广播拉活
在发生系统事件时,系统会发出相对响应的广播(常用的广播事件如:开机、网络状态变化、文件或sd卡的卸载等),我们可以在mainfest.xml文件中静态注册广播监听器
缺点(无法拉活的情形):广播接收者被管理软件或系统软件通过自启动管理等功能禁用的场景下是无法接受广播的,从而无法自启动进行系统拉活;系统广播事件是不可控制的,只有在发生事件时才能进行拉活,无法保证进程被杀死后立即被拉活。
- 利用系统Service机制拉活
将Service中的onStartCommand()回调方法的返回值设为
START_STICKY
,就可以利用系统机制在Service挂掉后自动拉活。
拓展:onStartCommand()的返回值表明当Service由于
系统内存不足
而被系统杀掉之后,在未来的某个时间段内当系统内存足够的情况下,系统会尝试创建这个Service,一旦创建成功就又会回调onStartCommand()方法。
缺点(无法拉活的情形):Service第一次被异常杀死后会在5s内重启,第二次会在10s内重启,第三次会在20s内重启,若Service在短时间内被杀死的次数超过3次以上系统就会不惊醒拉活;进程被取得root权限的管理工具或系统工具通过强制stop时,通过Service机制无法重启进程。
- 利用Native进程拉活
思想:利用Linux中的fork机制创建一个Native进程,在Native进程可以监控主进程的存活,当主进程挂掉之后,Native进程可以立即对主进程进行拉活。
在Native进程中如何监听主进程被杀死:可在Native进程中通过死循环或定时器,轮询地判断主进程被杀死,但是此方案会耗时耗资源;在主线程中创建一个监控文件,并且在主进程中持有文件锁,在拉活进程启动后申请文件锁将会被阻塞,一旦成功获取到锁说明主进程挂掉了。
如何在Native进程中拉活主进程:主要通过一个am命令即可拉活。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
写在最后
最后我想说:对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
上述【高清技术脑图】以及【配套的架构技术PDF】可以点击下面链接免费获取
少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
[外链图片转存中…(img-gRg4DKZ9-1711354393142)]
[外链图片转存中…(img-1kcDD7ri-1711354393143)]
上述【高清技术脑图】以及【配套的架构技术PDF】可以点击下面链接免费获取
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。