0%

在电脑安装多个版本的JDK,并自由切换,具有一定的灵活性。因为下载新JDK再配新环境变量真的很麻烦。SDKMAN可以帮我们解决这些烦恼。

以下是在Mac电脑安装SDKMAN并使用:

1
curl -s "https://get.sdkman.io" | bash

访问:https://get.sdkman.io/ 网站上的脚本,并使用bash执行

1
source $HOME/.sdkman/bin/sdkman-init.sh

执行sdkman初始化脚本

1
sdk list java

列出所有可用的jdk

1
sdk install java 19.0.2-oracle

安装指定的jdk

1
sdk use java 19.0.2-oracle

使用指定的jdk

昨天晚饭后去天河公园散步,回来时才发现出门没拿钥匙,最后找了开锁师傅解决。事情虽然解决了,却让我想起了几个月前曾和老婆开玩笑:我们得备把钥匙🔑藏起来,万一哪天忘记带钥匙我们也能回家。

谁知一句玩笑话却真的出现了。让我不禁想到了著名的墨菲定律:

如果有多过一种方式去做某事,而其中一种方式将导致灾难,则必定有人会这样选择

直白一点说就是:会出错的事总会出错

数学解释:

假设某意外事件在一次实验(活动)中发生的概率为p(p>0),则在n次实验(活动)中至少有一次发生的概率为pn=1-(1-p)n。
由此可见,无论概率p多么小(即小概率事件),当n越来越大时,pn越来越接近1。

感悟:
  • 想到的事情,立马要去做。
  • 能避免的风险尽量避免。

以下内容在一篇公众号里面看到的,觉得很有道理,记录在此,常思之。

01 沟通:先求同,再求异
明确共同目标,塑造价值认同。保持开放心态,积极倾听对方。

自评:

02 共情:先理解,再表达
准确辨识情绪,正确解读语义。听对方想说的,说对方想听的。

自评:

03 人际:先交流,再交心
选择交流对象,探索交流领域。尝试交流情感,保持稳定交往。

自评:

04 情商:先心情,再事情
安抚对方情绪,恢复正常对话。寻找共同利益,解决冲突矛盾。

自评:

05 职场:先升值,再升职
认清商业本质,正视价值交换。接受共性塑造,获得职务晋升。

自评:

06 工作:先计划,再行动
设定清晰目标,分析评估现状。制订详细计划,设定执行步骤。

自评:计划就是把大目标拆成更容易实现的小目标,给自己设定期限,坚定的完成小目标。有了目标,才不会放松自己,浑浑噩噩。

07 执行:先完成,再完美
舍弃完美主义,坚持效率优先。总结经验教训,快速优化迭代。

自评:早期写代码时追求完美,总想着要设计好代码。花过多的时间在代码设计上。后面还是想明白了,先把事情做完是最基本的要求,做完后有时间再去优化代码细节。因为思考是逐渐深入的,只有完成了,在完成过程中的思考,才能为后面的更好做好理论铺垫。

08 学习:先记录,再记忆
准备记录工具,捕捉关键信息。定期整理回顾,转为长期记忆。

自评:知识要结构化才能变成脑子里的思路,结构化就是对一方面知识进行概括,由多到少,由繁到简,由细节到抽象。记录和整理就是对知识进行结构化。尤其是现在快节奏的生活,大家没时间体系性的看书,都是碎片化的知识,看时很爽,很快忘记,不妨把小知识点记录成系统,归纳到自己的知识体系里面。

09 能力:先专注,再专业
正确选择方向,排除外界干扰。深度学习知识,持续精进技能。
10 事业:先成长,再成功
磨砺心灵意志,坚持求知探索。明确价值取向,积小胜为大胜。
11 发展:先站住,再站高
明确发展定位,夯实事业基础。进行长远规划,开展品牌建设。

12 创新:先仿造,再创造
寻找模仿对象,仔细观察学习。研究原理结构,思考优化改进。

13 流程:先僵化,再优化
设计业务流程,坚持落地执行。消除流程阻力,提升流程效率。

14 制度:先细化,再简化
杜绝制度弹性,堵住制度漏洞。提炼制度要点,进行制度宣贯。

15 管理:先自己,再别人
约束自身言行,做好团队表率。明确团队规则,落实奖惩措施。

16 影响:先管理,再领导
建立团队秩序,做好利益平衡。激发团队动能,引领创新变革。

总之,做事,顺序不能错,逻辑不能反!

概述

Measure是一个开源的性能监控项目,它包含:Android、iOS、前端、后端。这里分析一下Android端的逻辑实现。

分析

项目的基本结构:

  • measure-android

    • measure
    • measure-android-gradle
    • sample
  • measure模块的内容:

    • ANR捕获:Native实现,注册信号处理器,捕获SIGQUIT信号
    • AppLaunch:区分冷起、热起、温启动,并对外回调。
    • AppExit:ActivityManager#getHistoricalProcessExitReasons的使用
    • performance:
      • cpu usage
      • memory usage
    • NetworkChange:网络变化的监控
    • ScreenShot:生成屏幕截图,PixelCopy的使用,或者Canvas画上去
    • 其他模块:周期性的心跳包(Heartbeat)去执行任务。Okhttp拦截器。
  • measure-android-gradle

    • Manifest数据读取,AppId、VersionCode、VersionName
    • Mapping文件上传
    • Apk、Aab大小信息上传
总结:

1、冷热起的判断逻辑,这部分代码参考自Square的PaPa有参考价值
2、各功能的对外调用都是接口化的,无侵入性
3、项目简单,阅读起来很顺。
4、包含前后端代码,看板,值得学习。

概述

书籍简介
高纬度思考法:如何从解决问题进化到发现问题

作者简介:
细谷功,商务顾问。毕业于东京大学工学部。初任职于东芝,后进入安永咨询公司(Ernst&Young Consulting,QUNIE 前身),负责产品开发等领域的战略制定及业务改革计划的制订、执行和定义。现任QUNIE 顾问研究员,另于企业和大学开展思维能力相关的研修和业务。

书本结构:

第一部分:知、无知、未知及其结构

1.1 “未知的未知”这一死角
认识到知的三个层次,即:已知的已知、已知的未知、未知的未知。尤其是要意识到未知的未知这一层。

1.2 “知”是“事实和解释的组合”

  • 事实和解释的关系:事实只有一个,解释因人而异

1.3 “无知、未知”的思考框架

1.4 已知和未知的不可逆循环

1.5 苏格拉底和德鲁克所提倡的”无知”的两种视角

第二部分:解决问题的困境:能解决问题的人,不能发现问题

2.1 “知”的困境
2.2 封闭体系的困境
2.3 “解决问题”的困境

第三部分:从解决问题到发现问题

3.1 蚂蚁思维与蝈蝈思维的差异

蝈蝈:发现问题型思维
蚂蚁:解决问题型思维

蝈蝈的思维 蚂蚁的思维
流量 存量
开放体系 封闭体系
可变维度 固定维度

什么是蝈蝈和蚂蚁的流量与存量:蚂蚁储存食物、蝈蝈不储存食物
什么是开放和封闭体系:有巢和无巢
什么是可变维度和固定维度:蚂蚁平面移动,蝈蝈会跳跃

3.2 从存量到流量

  • 在变化少的环境下,存量思维是有益的

  • 在变化激烈的世界里,流量思维更具价值

  • 蚂蚁是有产者,重视守护自己的产业、口碑和名声

  • 蝈蝈是无产者,没有什么可守护的,更具开放性

3.3 从封闭体系到开放体系

  • 蚂蚁以巢为中心活动、蝈蝈无巢活动。
  • 封闭体系以主观为中心进行思考,开放体系则拥有客观看待自身的视角。

3.4 从固定思维到可变思维

3.5 从“奇点”出发的问题发现法

3.6 蚂蚁和蝈蝈能否共存共荣:两种思维在同一个人中、两种思维在不同人之间的相处中,的作用、分配、影响。

  • 各领域的蚂蚁和蝈蝈:这里借用数学领域简单阐述
  • 在“二维”中,蚂蚁常占据压倒性的优势:
    假如只用手攻击的拳击选手和手脚并用的自由搏击选手“公平地同台”较量,自由搏击选手就不能用脚。在这种情况下不难推测,始终只用手攻击的拳击选手比手脚并用的自由搏击选手更占优势。
  • 蝈蝈在蚂蚁窝里跳不起来:
  • 互相怎么看
  • 通过“元级”克服对立结构
  • 决定是蚂蚁还是蝈蝈的性格和环境

第四部分:发现问题的元思考法,升维发现问题

4.1 上位概念&下位概念

理解:“上位”是一种思考抽象度的提升。作者说“上位概念是指用以思考的解释层”,这句话应该这么理解:我们观察到现象A/B/C,这三个现象有一些共性,那么我们提炼这些共性,再去思考现象ABC,就是一种思维提升,站在上位的概念思考问题。

4.2 通过“抽象化、类推”升维

若将个别事实视作具体,则基于某共同点抛弃其他所有特征、视 为“同一范畴内”的解释,就是抽象。顾名思义,抽象意味着“提取特征”。
科学的进化一言以蔽之,就是找到各个特殊事象间的共同点,得出定律,再将其适用 于各种各样的事象。各类科学技术的进步,都基本上均遵循这一原则。

4.3 通过思考的“轴”升维
书本定义:“观察个别事象(即下位概念)时,作为基准的上位概念的视角”
4.4 通过“Why”升维
4.5 为了活用“元思考法”

总结

1、知的三个层次:已知的已知、已知的未知、未知的未知
2、蚂蚁和蝈蝈两种动物类比两种思维方式:解决问题思维vs发现问题思维
3、在组织管理中,如何使蚂蚁思维和蝈蝈思维的人都能发挥自己的才能。
4、三种升维方式:抽象化类推、思考轴、Why

本书借用两个动物的生活习性,类比两种思维方式。全书被划分成四个部分,重点是第四部分的三种升维方式,可以帮助我们提升思考的维度。粗读一遍总体感觉没有特别大的收获。
创造了一些“上位”,“下位”等专有名词的概念,反而让读者觉得神秘高大上,其实没什么新意,增加了理解难度,不知道是不是翻译的不好导致的。
总体推荐阅读指数3.5星。


概念

一种空间高效的概率型数据结构,用于判断一个元素是否存在于集合中。

空间高效:用几个比特位来标识存在与否,不占用太多内存空间。
概率型:有几率把一个不存在的元素判定为存在。

Hash表存在的问题:数据量很大时,占用内存太多了。

基本操作

插入操作:

初始bit数组A[m-1]全部置0,通过映射函数,将要插入的值随机映射到数组范围内,将该位置为1

查找操作:

将要查找的元素通过映射函数,映射到数组中,判断该bit位是否为1

应用

  • 网页爬虫对 URL 去重,避免爬取相同的 URL 地址;
  • 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱;

参考资料

图片来源
1

概述

书籍简介
认知天性 : 让学习轻而易举的心理学规律
关于作者

三位作者:

  • 彼得·布朗(Peter C. Brown)
    一位作家和独立出版人,专注于撰写历史、商业和心理学方面的书籍。他在《认知天性》中担任主要撰稿人,负责将科学家们的研究成果转化为易于理解和应用的内容
  • 亨利·勒迪格(Henry L. Roediger III)
    华盛顿大学心理与脑科学系的教授。他的研究主要集中在记忆和学习方面,尤其是记忆的提取和测试效应(testing effect)。勒迪格教授在认知心理学领域发表了大量的研究论文,并获得了多项荣誉和奖项。
  • 马克·麦克丹尼尔(Mark A. McDaniel)
    华盛顿大学心理与脑科学系的教授,专注于认知心理学和教育心理学。他的研究兴趣包括记忆、学习策略和如何在实际教育环境中应用这些策略。麦克丹尼尔教授也在认知心理学领域发表了许多重要的研究成果,并与勒迪格教授共同开展了大量的合作研究。
结构
  • 学习是挑战天性的必须课
  • 学习的本质:知识链和记忆结
  • “后刻意练习”时代的到来
  • 知识的“滚雪球”效应
  • 打造适合自己的心智模型
  • 选择适合自己的学习风格
  • 终身学习者基本的基本
  • 写给大家的学习策略
内容
  • 1、学习是挑战天性的必须课
    • 天性懒惰孕育了认知规律和心智模型
      • 耗费心血的学习才是深层次的,效果也更持久。不花力气的学习就像在沙子上写字,今天写上,明天字就消失了。
      • 与反复阅读这种复习方法相比,回想事实、概念或事件会更有效。这种方法被称为检索式练习。
    • 科学“照妖镜”下的学习方法
      • 背诵、不断重复、反复阅读、功利性记忆、集中练习等方式,看起来很刻苦,其实效果不好,很快被忘记。
      • 对文字越熟悉、越流畅阅读,会造成一种掌握的假象。
      • 当事关重大时,当抽象的事务被形象化时,当事情和个人息息相关时,你就会把学到的东西记得更牢。
      • 轻易接受别人的观点,不给自己提问题,没有去想什么是自己不知道的
    • 知识多不等于学习能力强
      • 学习知识不能求快,要求扎实,循序渐进理解。
    • 考试是最有效的学习策略之一
      • 不要把考试当做衡量学习成果的标尺,而是记忆检索的练习,一种学习工具。
      • 主动检索(考试)可以强化记忆,而且检索花费的心思越多,受益就越多。

读书笔记:不要无意识的重复,集中练习、把抽象形象化,找到知识与自己的关联。别太在意考试的成绩。

  • 2、学习的本质:知识链和记忆结
    • 知识最终将变成条件反射
      • 可以带来更好的学习效果:从记忆中检索知识或是早期的训练内容,把这些和新体验联系起来,借助观察和思考,预先演练你下次可能采取的不同做法。
    • 自我检查:给知识链打上记忆结
      • 重复检索能让记忆更清透,而且它把记忆这条绳子又缠了一圈,使其变得 更牢靠。
    • 只需一次自测:一周后回忆率28%跃迁为39%
      • 自测是一种检索式学习,可以强化记忆。
    • 如何成为一名主动学习者
    • 为何学习越轻松效果越不好

读书笔记:不断回顾知识(考试)可以加深印象,减少遗忘。反思也是一种记忆检索。

  • 3、“后刻意练习”时代的到来
    • 频繁的集中练习只会产生短期记忆
    • 间隔练习使知识存储得更牢固
    • 穿插练习有助于长期记忆
    • 多样化练习促进知识的活学活用
    • 善用练习组合,带来成长性思维
    • 知识是平面的,复合型知识是立体的
    • 关于练习的几条普适性原则

读书笔记:这一部分的副标题是连贯深入的。

  • 4、知识的“滚雪球”效应
    • 学习的三个关键步骤
      • 编码
      • 巩固
      • 检索
    • 欲求新知,先忘旧事
      • 使用Mac电脑,要先忘记Windows电脑,因为Windows的操作习惯会干扰你的学习。忘掉的不是知识本身,而是检索的线索。
    • 越容易想起,越不容易记住
    • 学习中必须要做哪些努力
      • 重新巩固记忆
      • 打造心智模型:复杂理论或连续运动技能融合成有意义的整体。
      • 举一反三
      • 构建概念学习
      • 学习迁移
      • 做好学习的心理准备
    • 这些”良性干扰“能提升学习效果
    • 化解因失败带来的焦虑感
    • 创造性源于不设限的学习
    • 别在无法克服的困难上浪费时间

读书笔记:

  • 5、打造适合自己的心智模型
    • 没头脑的机制1和爱自省的机制2
      • 指反射脑和逻辑脑(《思考快与慢》)
    • 学习时避免错觉和记忆扭曲
    • 打造适合自己的心智模型
    • 你无法从不擅长的事情里学到知识
    • 实践和测验才能暴露学习漏洞

读书笔记:

  • 6、选择适合自己的学习风格
    • 主动学习能制造掌控感
    • 你是分析型、创新型、还是实践型思维
      • 第一种智力区分模型:8种
        • 逻辑——数学智力:批判性思考,以及使用数字和抽象概念的能 力,诸如此类。
        • 空间智力:三维判断,以及在脑海中具象化的能力。
        • 语言智力:使用文字和语言的能力。
        • 肢体动觉智力:行动敏捷和控制身体的能力。
        • 音乐智力:对声音、旋律、音色,以及音乐的敏感性。
        • 人际交往智力:“读懂”他人,以及与人有效协作的能力。
        • 内省智力:理解自身,准确判断自身知识、能力、效率的能力。
        • 自然观察智力:区分和关联周围自然环境的能力(例如园丁、猎人 或厨师特有的智力)。
      • 第二种智力区分模型:3种
        • 分析型智力 :分析型智力是我们解决问题的能力,典型的例子就是解答测验中的问题
        • 创新型智力 :创新型智力是我们综合并应用现有的知识与技能,应对那些新的特殊情况的能力;
        • 实践型智力 :实践型智力是我们适应日常生活的能力——明白在具体环境下需要做什么并行动,也就是我们所说的“街头智慧”。
    • 学不好的领域暴露了你的能力结构
    • 用搭积木的方法构建知识
    • 有人喜欢看说明书,有人喜欢动手试错

读书笔记:不同的文化与学习场景需要不同的智力类型。

  • 7、终身学习者基本的基本
    • 双胞胎的认知能力也会天差地别
      大脑的结构与整体构造在很大程度上是由基因决定的,但神经网络的精细构造似乎也可以由经验来塑造,而且具备大幅修改的能力。
    • 性格、求知欲和家庭条件对学习的影响
      智商是基因🧬与环境共同作用的产物。
      人类智商在持续升高,因为教育、文化(电视机兴起)、营养(脂肪酸、铁、维B)发生了极大的变化。
      社会经济地位也会影响智商。早期教育可以提升贫困孩子的智商。
    • 脑力训练可以提升学习自信
      流体智力:指推理、发现关系、抽象 思维,以及在解决问题的同时头脑中保留信息的能力。
      晶体智力:指积累的关于世界的知识,以及从过去的学习与经验中提炼出来的 程序或心智模型。
    • 想要终身成长,请像专家一样思考
      1、信念:你要相信智力水平不是固定的,而是在很大程度上掌握在自己手中。
      2、面对失败的态度:那些将失败归咎于本身无能的人——说“我就是不够聪明”的人——会变得无助;而那些认为失败是努力不够或策略不对的人则会深入发掘,尝试不同的做法。
      3、目标:有的学生以成绩为目标,而有的学生则以学习为目标。对于前一种人来说,他们努力是为了证明自己的能力。对于第二种人来说,他们努力则是为了学到新的知识或技能
    • 学习执行力比学习技巧更重要:成为专家需要一万小时刻意练习。
    • 掌握几个适合自己的记忆方法:记忆宫殿等记忆技巧

读书笔记:智商 = 基因 + 环境因素。我们可以通过改变环境因素提升我们的智商。

  • 8、写给大家的学习策略
    • 给学生的学习策略
      • 练习从记忆中检索新知识
      • 有间隔的安排检索练习
      • 学习时穿插安排不同类型问题
    • 给职场人士的学习策略
    • 给教师的学习策略
      • 向学生解释学习的过程
      • 教学生如何学习
      • 在课堂上创造合意困难
      • 保证透明度:让学生理解用意。
    • 给培训者的学习策略
全书总结

从作者的职业可以看出,一个出版人和两个教授合作出版的一本书。属于认知心理学范畴。主要介绍学习、认知、大脑相关实验和结论。

1、自己究竟有没有掌握一个知识点。考试(测验、自测)是一个很好的检验手段。不像学校里的考试,要以正确的心态看待考试,只是检测自己知识的掌握度,而不是要一较高下。

个人理解:
获取到新知识,停留在浅层记忆,会有迷惑性,以为自己懂了。实则过段时间就忘记了。我们应该间隔性的回忆知识,内化吸收,这样才能将知识灵活运用。

日志库是一个项目的基础功能之一,它应该包括但不限于以下功能:

  • 扩展性:支持把日志记录到多个地方,如:本地文件、控制台、崩溃系统。
  • 高性能:日志记录较为频繁时,如何写文件,提高性能。
  • 稳定性:崩溃前一刻的日志不丢失。

以下是一些开源的日志库,做一个记录:

基于 mmap, 高性能、高可用的 Android 日志收集框架

1
2
3
Log4a.i(TAG, "Hello,Log4a!");
Log4a.flush();
Log4a.release();
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
class Test {
LogConfiguration config = new LogConfiguration.Builder()
.logLevel(BuildConfig.DEBUG ? LogLevel.ALL // Specify log level, logs below this level won't be printed, default: LogLevel.ALL
: LogLevel.NONE)
.tag("MY_TAG") // Specify TAG, default: "X-LOG"
.enableThreadInfo() // Enable thread info, disabled by default
.enableStackTrace(2) // Enable stack trace info with depth 2, disabled by default
.enableBorder() // Enable border, disabled by default
.jsonFormatter(new MyJsonFormatter()) // Default: DefaultJsonFormatter
.xmlFormatter(new MyXmlFormatter()) // Default: DefaultXmlFormatter
.throwableFormatter(new MyThrowableFormatter()) // Default: DefaultThrowableFormatter
.threadFormatter(new MyThreadFormatter()) // Default: DefaultThreadFormatter
.stackTraceFormatter(new MyStackTraceFormatter()) // Default: DefaultStackTraceFormatter
.borderFormatter(new MyBoardFormatter()) // Default: DefaultBorderFormatter
.addObjectFormatter(AnyClass.class, // Add formatter for specific class of object
new AnyClassObjectFormatter()) // Use Object.toString() by default
.addInterceptor(new BlacklistTagsFilterInterceptor( // Add blacklist tags filter
"blacklist1", "blacklist2", "blacklist3"))
.addInterceptor(new MyInterceptor()) // Add other log interceptor
.build();

Printer androidPrinter = new AndroidPrinter(true); // Printer that print the log using android.util.Log
Printer consolePrinter = new ConsolePrinter(); // Printer that print the log to console using System.out
Printer filePrinter = new FilePrinter // Printer that print(save) the log to file
.Builder("<path-to-logs-dir>") // Specify the directory path of log file(s)
.fileNameGenerator(new DateFileNameGenerator()) // Default: ChangelessFileNameGenerator("log")
.backupStrategy(new NeverBackupStrategy()) // Default: FileSizeBackupStrategy(1024 * 1024)
.cleanStrategy(new FileLastModifiedCleanStrategy(MAX_TIME)) // Default: NeverCleanStrategy()
.flattener(new MyFlattener()) // Default: DefaultFlattener
.writer(new MyWriter()) // Default: SimpleWriter
.build();

XLog.init( // Initialize XLog
config, // Specify the log configuration, if not specified, will use new LogConfiguration.Builder().build()
androidPrinter, // Specify printers, if no printer is specified, AndroidPrinter(for Android)/ConsolePrinter(for java) will be used.
consolePrinter,
filePrinter);
}
````

+ [logger](https://github.com/orhanobut/logger) 13.7k star


```java
class Test {
FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder()
.showThreadInfo(false) // (Optional) Whether to show thread info or not. Default true
.methodCount(0) // (Optional) How many method line to show. Default 2
.methodOffset(7) // (Optional) Hides internal method calls up to offset. Default 5
.logStrategy(customLog) // (Optional) Changes the log strategy to print out. Default LogCat
.tag("My custom tag") // (Optional) Global tag for every log. Default PRETTY_LOGGER
.build();

Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy));
}

概述

源码

startup库是一个极简启动优化库,可以解决启动中的依赖顺序问题。

基本使用

1.1 实现Initializer接口

1
2
3
4
5
6
7
8
9
10
class LoggerInitializer : Initializer<Logger> {
override fun create(context: Context): Logger {
Logger.init(context)
return Logger
}

override fun dependencies(): List<Class<out Initializer<*>>> {
return emptyList()
}
}

1.2 AndroidManifest.xml中声明

1
2
3
4
5
6
7
8
9
10
<provider>
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">

<meta-data
android:name="me.xxx.demo.LoggerInitializer"
android:value="androidx.startup"/>
</provider>

源码分析

1、默认由ContentProvider onCreate中获取AppInitializer单例
2、调用AppInitializer单例的discoverAndInitialize,解析Manifest里面的mate
3、解析完后放入Set<Class>>中
4、遍历Set,调用doInitialize进行初始化
4.1 检查循环依赖问题
4.2 找到此项的所有依赖项,递归调用doInitialize
4.3 此项依赖初始化完成

缺点

  • 不支持线程控制和等待

其他相关库

android-startup

在接入Google Admob时,依据官方文档 或 依据开发习惯,我们一般先对Admob SDK进行初始化,然后进行广告加载:

1
2
3
4
5
6
7
8
// first init the admob sdk
MobileAds.initialize(context) {
//init successful
}

//second load Ad
val adRequest = AdRequest.Builder().build()
adView.loadAd(adRequest)

那么,多思考一下,我们有个疑问:

1、一定要先初始化,才能加载广告吗❓

实验设计:不执行初始化操作,直接请求广告。

1
2
val adRequest = AdRequest.Builder().build()
adView.loadAd(adRequest)

实验结论:不初始化SDK也能成功加载到广告。

2、为什么不初始化也能加载广告呢❓

猜想:
1、初始化和加载有关联性:加载广告时,发现没有初始化,先进行了初始化,再执行广告加载操作。
2、初始化和加载无关联系:加载广告不需要SDK初始化,两者无关联。

设:广告初始化耗时m毫秒,广告加载耗时n毫秒,总耗时m+n毫秒。

实验设计:
A组:执行初始化,同时执行广告加载。
若初始化和加载有关联性,广告加载时长约等于m+n。
若初始化和加载无关联性,广告加载时长约等于n。

日志输出示例:

1
2
3
4
2024-07-06 10:10:06.061 23555-23555 InitAndLoad     com...oid.gms.example.bannerexample  D  call init....
2024-07-06 10:10:06.224 23555-23555 InitAndLoad com...oid.gms.example.bannerexample D start load....
2024-07-06 10:10:07.401 23555-23555 InitAndLoad com...oid.gms.example.bannerexample D after init = 1340
2024-07-06 10:10:08.416 23555-23555 InitAndLoad com...oid.gms.example.bannerexample D onAdLoaded...cost = 2192

初始化耗时 m=1340ms
加载耗时 n=2192ms

B组:延迟10s执行初始化。立即执行广告加载。

日志输出示例:

1
2
3
4
2024-07-06 13:23:42.675 27481-27481 DelayInitAndLoad    com...oid.gms.example.bannerexample  D  start load....
2024-07-06 13:23:43.453 27481-27481 DelayInitAndLoad com...oid.gms.example.bannerexample D call init....
2024-07-06 13:23:46.208 27481-27481 DelayInitAndLoad com...oid.gms.example.bannerexample D onAdLoaded...cost = 3532
2024-07-06 13:23:53.486 27481-27481 DelayInitAndLoad com...oid.gms.example.bannerexample D after init = 24

初始化耗时 m=24ms
加载耗时 n=3532ms

结论:由于广告加载成功后,才调用初始化逻辑,因此初始化时长大幅降低。故:初始化和加载有关联性。

3、聚合的SDK初始化了吗❓

实验设计:
A:不初始化SDK,加载广告后,打开AdInspector。
B:初始化SDK,加载广告后,打开AdInspector。

实验结论:不初始化只能加载Admob自身的广告,初始化后可以加载聚合源的广告。

3、初始化成功后再加载广告 VS 直接加载广告 加载速度的对比

直接加载:

第一组 第二组 第三组 第四组 第五组
2915ms 1581ms 1435ms 1621ms 1581ms

初始化后加载:

第一组 第二组 第三组 第四组 第五组
初始化 2373ms 2374 2463 2427 2298
加载 1468ms 1386 1505 2498 1250
日志总耗时 3843 3762 3970 4927 3550

结论:初始化后才加载广告慢于直接加载广告。

4、一种开屏广告的优化方案

不初始化SDK也能加载到Admob广告,且加载速度较快,但是没有参与bidding,价格较低。
初始化之后,加载聚合源广告,速度较慢,但经过bidding后,价格会高一点。

结合两个加载方式,闪屏时段内加载广告,闪屏n秒时长内,加载到bidding类型则展示bidding类型。没加载到,则展示Admob类型。