查漏补缺

本文阅读量

Java 基础

设计模式

创建型设计模式

单例

懒汉
1
2
3
4
5
6
7
8
9
public class Singleton {
    private Singleton() {
    }
    private static final Singleton s = new Singleton();

    public static Singleton getSingleton() {
        return s;
    }
}
  • private 的构造函数
  • final staic的 内部属性
  • staic 获取接口
饿汉
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Singleton {

    private Singleton() { }

    private static Singleton s;

    public static synchronized Singleton getInstance() {
        if (s == null) {
            s = new Singleton();
        }
        return s;
    }
}
DCL
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class Singleton {

    private Singleton() { }

    private static s;

    public static Singleton getSingleton() {
        if (s == null) {
            synchronized (Singleton::class) {
                if (s == null) {
                    s = new Singleton();
                }
            }
        }
        return s;
    }
}
静态内部类
1
2
3
4
5
6
7
8
9
public class Singleton {
    private Singleton() { }
    private static class Holder {
        private static final Singleton holder = new Singleton();
    }
    public static Singleton getSingleton() {
        return Holder.holder;
    }
}
枚举
1
2
3
public enum  Singleton {
    INSTANCE;
}

工厂模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class RuleConfigParserFactory {
  private static final Map<String, RuleConfigParser> cachedParsers = new HashMap<>();

  static {
    cachedParsers.put("json", new JsonRuleConfigParser());
    cachedParsers.put("xml", new XmlRuleConfigParser());
    cachedParsers.put("yaml", new YamlRuleConfigParser());
    cachedParsers.put("properties", new PropertiesRuleConfigParser());
  }

  public static IRuleConfigParser createParser(String configFormat) {
    if (configFormat == null || configFormat.isEmpty()) {
      return null;//返回null还是IllegalArgumentException全凭你自己说了算
    }
    IRuleConfigParser parser = cachedParsers.get(configFormat.toLowerCase());
    return parser;
  }
}

构建者模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

public class ResourcePoolConfig {
  private String name;
  private int maxTotal;
  private int maxIdle;
  private int minIdle;

  private ResourcePoolConfig(Builder builder) {
    this.name = builder.name;
    this.maxTotal = builder.maxTotal;
    this.maxIdle = builder.maxIdle;
    this.minIdle = builder.minIdle;
  }
  //...省略getter方法...

  //我们将Builder类设计成了ResourcePoolConfig的内部类。
  //我们也可以将Builder类设计成独立的非内部类ResourcePoolConfigBuilder。
  public static class Builder {
    private static final int DEFAULT_MAX_TOTAL = 8;
    private static final int DEFAULT_MAX_IDLE = 8;
    private static final int DEFAULT_MIN_IDLE = 0;

    private String name;
    private int maxTotal = DEFAULT_MAX_TOTAL;
    private int maxIdle = DEFAULT_MAX_IDLE;
    private int minIdle = DEFAULT_MIN_IDLE;

    public ResourcePoolConfig build() {
      // 校验逻辑放到这里来做,包括必填项校验、依赖关系校验、约束条件校验等
      if (StringUtils.isBlank(name)) {
        throw new IllegalArgumentException("...");
      }
      if (maxIdle > maxTotal) {
        throw new IllegalArgumentException("...");
      }
      if (minIdle > maxTotal || minIdle > maxIdle) {
        throw new IllegalArgumentException("...");
      }

      return new ResourcePoolConfig(this);
    }

    public Builder setName(String name) {
      if (StringUtils.isBlank(name)) {
        throw new IllegalArgumentException("...");
      }
      this.name = name;
      return this;
    }

    public Builder setMaxTotal(int maxTotal) {
      if (maxTotal <= 0) {
        throw new IllegalArgumentException("...");
      }
      this.maxTotal = maxTotal;
      return this;
    }

    public Builder setMaxIdle(int maxIdle) {
      if (maxIdle < 0) {
        throw new IllegalArgumentException("...");
      }
      this.maxIdle = maxIdle;
      return this;
    }

    public Builder setMinIdle(int minIdle) {
      if (minIdle < 0) {
        throw new IllegalArgumentException("...");
      }
      this.minIdle = minIdle;
      return this;
    }
  }
}

// 这段代码会抛出IllegalArgumentException,因为minIdle>maxIdle
ResourcePoolConfig config = new ResourcePoolConfig.Builder()
        .setName("dbconnectionpool")
        .setMaxTotal(16)
        .setMaxIdle(10)
        .setMinIdle(12)
        .build();

原型模式

最典型的就是 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()

1
2
3
4
runtime.otalmemory()
runtime.freememory()
Debug.getNativeHeapSize()
Debug.getNativeHeadFreeSize()

堆区

  • 合理地减少加载进入堆区的内存。
    • 减少缓存大小。
    • 按需加载数据。
    • 共享对象。
    • 转移到其他地方,比如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文件和资源文件。针对这三个资源,可以用精简,压缩,动态化的手段。

资源文件

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 转发的方式

第三方开源库

Glide

https://wildma.blog.csdn.net/article/details/114766258?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-114766258-blog-109703935.pc_relevant_recovery_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-114766258-blog-109703935.pc_relevant_recovery_v2&utm_relevant_index=2

retrofit

内容由 bokmark 提供
Hugo 构建
主题 StackJimmy 设计