Java 基础
设计模式
创建型设计模式
单例
懒汉
|
|
- private 的构造函数
- final staic的 内部属性
- staic 获取接口
饿汉
|
|
DCL
|
|
静态内部类
|
|
枚举
|
|
工厂模式
|
|
构建者模式
|
|
原型模式
最典型的就是 java的clone方法。
结构型 设计模式
代理模式
在不改变原始类(或叫被代理类)的情况下,通过引入代理类来给原始类附加功能。一般情况下,我们让代理类和原始类实现同样的接口。但是,如果原始类并没有定义接口,并且原始类代码并不是我们开发维护的。在这种情况下,我们可以通过让代理类继承原始类的方法来实现代理模式。
retrofit 就是代理模式之中的动态代理的典型。
动态代理 一个接口 由一个代理对象实现。
桥接模式
将抽象和实现解耦,让它们可以独立变化。
装饰模式
装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能。这也是判断是否该用装饰器模式的一个重要的依据。
适配器模式
解决兼容性问题。
外观模式、门面模式
对子系统进行统一的接口设计,对外暴露,将模块的内部细节进行隐藏。
享元模式
共享一部分对象,节约内存。
行为型 设计模式
观察者
观察者模式,将观察者和被观察者代码解耦。借助设计模式,我们利用更好的代码结构,将一大坨代码拆分成职责更单一的小类,让其满足开闭原则、高内聚低耦合等特性,以此来控制和应对代码的复杂性,提高代码的可扩展性。
模版方法
在父类中定义好了一系列的流程,只留下一些关键的方法由负责实现的子类去实现。
策略
策略模式定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。
责任链
okhttp 对于request和response的处理,非常经典的责任链模式。
状态
状态模式是状态机的一种实现方式即可。状态机又叫有限状态机,它有 3 个部分组成:状态、事件、动作。其中,事件也称为转移条件。事件触发状态的转移及动作的执行。不过,动作不是必须的,也可能只转移状态,不执行任何动作。
迭代器
迭代器模式,也叫游标模式。它用来遍历集合对象。这里说的“集合对象”,我们也可以叫“容器”“聚合对象”,实际上就是包含一组对象的对象,比如,数组、链表、树、图、跳表。
备忘录
备忘录模式也叫快照模式,具体来说,就是在不违背封装原则的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后恢复对象为先前的状态。这个模式的定义表达了两部分内容:一部分是,存储副本以便后期恢复;另一部分是,要在不违背封装原则的前提下,进行对象的备份和恢复。
Java 基础
虚拟机
GC
Andriod GC
https://source.android.com/docs/core/runtime/gc-debug?hl=zh-cn http://lihaizhou.top/2021/10/27/%E5%AF%B9Android-S-ART-GC%E7%9A%84%E6%BA%90%E7%A0%81%E6%A2%B3%E7%90%86/ https://juejin.cn/post/6875678394332217357 http://lihaizhou.top/2021/10/27/%E5%AF%B9Android-S-ART-GC%E7%9A%84%E6%BA%90%E7%A0%81%E6%A2%B3%E7%90%86/#/%E5%89%8D%E8%A8%80 http://lihaizhou.top/2021/11/01/%E7%AC%AC%E4%B8%89%E8%A7%86%E8%A7%92-%E4%B8%80%E4%B8%AAART-GC%E7%9A%84%E4%BC%98%E5%8C%96%E6%95%85%E4%BA%8B/#/%E8%B0%B7%E6%AD%8CReview
jvm 如何实现异常
Android 基础
启动模式
standard 标准模式
在启动者的activity所在的栈上启动。每次启动都会创建一个实例。
singleTop 模式
如果目标栈顶已经存在目标activity 则复用该Activity。如果目标栈顶不存在activity则启动一个新Activity。
singleTask 模式
根据taskAffinity寻找目标栈,如果栈中有此Activity的存在,则将此Activity提到栈顶,其他Activity被出栈。如果目标栈不存在这创建task,然后创建activity实例。
singleInstance 模式
独占一个task,且只有这一个实例。 由于独占,所以此Activity启动的Activity会跳到 其他task。
FLAG_ACTIVITY_SINGLE_TOP
类似于SingleTop,该flag将考虑task affinity 找到一个栈然后进行类似于singletop启动模式的操作。
FLAG_ACTIVITY_NEW_TASK
考虑task affinity,然后创建一个新的task。
FLAG_ACTIVITY_CLEAR_TOP
类似于single task的效果,清空上方堆栈。
fragment
fragment 原理
fragment
各个版本适配情况
gradle 基本认识
https://juejin.cn/post/6844903870091493384 https://android.googlesource.com/platform/tools/base/+/refs/tags/gradle_3.0.0/build-system/
点击事件
https://www.jianshu.com/p/38015afcdb58
性能优化
内存优化
内存优化分三方面来理解。
- Java 堆区
- native 内存
- 虚拟内存
内存关键指标。pss 、rss 、 private clean 、 private dirty、 swap pss dirty、 heap alloc 、 heap free
线下获取方式。dumpsys meminfo pid
线上获取方式。ActivityManager::getMeminfo()
|
|
堆区
- 合理地减少加载进入堆区的内存。
- 减少缓存大小。
- 按需加载数据。
- 共享对象。
- 转移到其他地方,比如native区,或者其他进程。
- 及时地释放对象。 监控内存占有率 及时释放缓存。内存泄漏。
- 转移到其他地方,比如native区,或者其他进程。
native 内存
- bitmap 监控,可以使用 asm的插件 lancet hook所有的bitmap的创建。然后可以进行报警,强制转化bitmapconfig。
- so native代码中内存的使用的注意,native内存泄露,可以使用native_memory_leaker来监控
虚拟内存
- 线程收敛,使用公用的线程池,同样可以使用lancet进行监控。监控线程池和thread的创建。
- 修改线程的栈大小,目前没有用过。
速度优化
速度优化的本质合理的提高cpu的利用率。以及提高缓存的命中率
合理使用cpu线程池。
io线程池,核心线程数
提高线程优先级
将主线程的优先级设置为最高。 将渲染线程的优先级设置为最高。
绑定大核
/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq 去找大核。 然后通过 sched_setaffinity 将线程绑定到大核上。
在cpu闲暇期间执行一些任务
关键在于监控cpu是否闲暇,可以通过 linux 的 times 方法获取cpu的时间片,然后做一个cpu的变化速率的监控。然后再实现一些任务,这些任务的执行时间要少。
ci中集成 redex
冷热端分离 lru cache
包体积优化
包体积主要由 dex 文件,so文件和资源文件。针对这三个资源,可以用精简,压缩,动态化的手段。
资源文件
- 精简。
- lint检查。
- shrinkResources。
- 图片只存放一份。
- https://github.com/bytedance/AabResGuard/blob/develop/wiki/zh-cn/README.md
- 压缩。
- 图片格式。
- 动态化。
- 能从服务器下载的资源都从服务器下载。
dex文件
- 精简。
- 删除无用代码,lint检测无用代码,jacoco 检查使用率,线下测试。
- 混淆。
- redex重排带来的包体积优化。
- 压缩
- 动态化
so 文件
- 精简。
- 单abi的so文件。
- –gc-sections编译时加入 可以精简so里面无用的代码。
- 压缩。
- extractNativeLibs
- 动态化
插件化
- 如何加载dex
- 通过自定义 dexclassloader 去加载。
- 修改 baseDexClassLoader 里的 dexpathlist 里面的dexelemnts
- 如何加载so
- 通过自定义 dexclassloader 去加载
- 修改 baseDexClassLoader 里的 dexpathlist 的nativeLibraryDirectories
- 如何加载资源文件
- 通过创建assetmanager 和resource 去获取,然后用asm去修改获取resrouce 地方的代码
- 如何跳过四大组件的检查。
- hook的方法
- 代理Activity 转发的方式