自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(47)
  • 收藏
  • 关注

原创 字节码层面分析 class 类文件结构

本从字节码层面分析 class 类文件结构。首先来看一道面试题:java中 String 字符串的长度有限制吗?平时项目开发中,我们经常会用到 String 来声明字符串,比如 String str = “abc”, 但是你可能从来没有想过等于号之后的字符串常量到底有没有长度限制。要彻底答对这道题,就需要先学会今天所讲的内容——class 文件。class 的来龙去脉Java 能够实现"一次编译,到处运行”,这其中 class 文件要占大部分功劳。为了让 Java 语言具有良好的跨平台能力,Ja

2021-03-26 19:54:27 627

转载 GC 回收机制与分代回收策略

垃圾回收(Garbage Collection,简写为 GC)可能是虚拟机众多知识点中最为大众所熟知的一个了,也是Java开发者最关注的一块知识点。Java 语言开发者比 C 语言开发者幸福的地方就在于,我们不需要手动释放对象的内存,JVM 中的垃圾回收器(Garbage Collector)会为我们自动回收。但是这种幸福是有代价的:一旦这种自动化机制出错,我们又不得不去深入理解 GC 回收机制,甚至需要对这些“自动化”的技术实施必要的监控和调节。前面介绍了 Java 内存运行时区域的各个部分,其中程序计

2021-03-25 17:49:59 422

转载 程序运行时,内存到底是如何进行分配的?

有很多人将 Java 的内存分为堆内存(heap)和栈内存(Stack),这种划分方式在一定程度上体现了这两块区域是 Java 工程师最关注的内存区域。但是其实这种划分方式并不完全准确。Java 的内存区域划分实际上远比这复杂:Java 虚拟机在执行 Java 程序的过程中,会把它所管理的内存划分为不同的数据区域。下面这张图描述了一个 HelloWorld.java 文件被 JVM 加载到内存中的过程:HelloWorld.java 文件首先需要经过编译器编译,生成 HelloWorld.class

2021-03-24 10:45:13 947

原创 Linux中传统的IPC机制

介绍IPC全称为Inter-Process Communication,含义为进程间通信,是指两个进程之间进行数据交换的过程。IPC不是Android中所独有的,任何一个操作系统都需要有相应的IPC机制,比如Windows上可以通过剪贴板等进行进程间通信;Linux上可以通过管道(Pipe)、信号(Sinal)、信号量(Semophore)、消息队列(Message)、共享内存(Share Memory)和套接字(Socket)等来进行进程间的通信。可以看到不同的操作系统有着不同IPC机制,对于Andro

2021-02-24 11:00:20 2158

原创 GitHub图片加载异常以及README.md添加图片异常

这些问题是由于 github 的一些域名的 DNS 解析被污染,导致 DNS 解析过程无法通过域名取得正确的 IP 地址。解决方案如下:https://www.bilibili.com/video/BV1CD4y197tj?from=search&seid=1671507888412118222笔者是参考了视频中的解决方案。再总结一下就是:将如下代码拷贝添加到host文件中windows host 路径:C:\Windows\System32\drivers\etc\host需要拷贝的代码

2020-11-20 09:50:59 440

原创 Android LiveData(二):源码分析

Android LiveData(二):源码分析有上文对LiveData的基本认识,接下来直接进入LiveData的源码分析,首先进入observer方法,需要注意的是MainActivity继承AppCompatActivity,是LifecycleOwner接口实现类的子孙。而调用observer方法时传入当前MainActivity的上下文,可以理解为owner就是当前的MainActivity。public void observe(@NonNull LifecycleOwner owner,

2020-11-17 13:38:09 461

原创 Android LiveData(一):介绍和简单使用

传统的组件间的通信方式有Handler、BroadcastReceiver,Interface、EventBus等等方式实现,他们有自己适合的应用场景,也有各自的弊端。这里介绍新的组件通信同时LiveData,它是一个数据持有类,具有以下特点:数据可以被观察者订阅能够感知组件(Fragment、Activity、Service))的生命周期组件处于active状态时,会通知观察者有数据更新对于观察者模式,不妨先看一个自己模仿LiveData写的简单的例子,数据持有类:public class

2020-11-17 11:55:12 1865

原创 Handler之消息屏障你应该知道的

前言由于Handler消息机制的同步屏障问题使用的场景不多,即使不了解可能也不会影响正常开发,因此往往容易被忽视,笔者也是自认比较熟悉Handler的消息机制,在之前同步屏障也算盲区,要想更全面的掌握Handler消息机制,同步屏障就不应该缺席。本文将从同步屏障的插入、删除、使用场景等角度分析同步屏障的工作原理消息的分类Message分为3中:普通消息(同步消息)、屏障消息(同步屏障)和异步消息。我们通常使用的都是普通消息,而屏障消息就是在消息队列中插入一个屏障,在屏障之后的所有普通消息都会被挡着,

2020-11-06 14:37:22 4827

原创 数据结构与算法:二叉查找树/排序树/搜索树

二叉树的前序遍历,中序遍历,后续遍历的思想,对其应分别对应的介绍了快速排序、汉诺塔、归并排序。二叉树的增删查操作很普通,时间复杂度与链表并没有太多差别。但当二叉树具备一些特性的时候,则可以利用这些特性实现时间复杂度的降低。二叉查找树/排序树/搜索树二叉查找树(也称作二叉排序树,二叉搜索树)具备以下几个的特性:若左子树不为空,那么左子树上面的所有节点的关键字值都比根节点的关键字值小若右子树不为空,那么右子树上面的所有节点的关键字值都比根节点的关键字值大左右子树都为二叉树没有重复值(

2020-10-26 19:10:37 979

原创 数据结构与算法:树及二叉树

树(Tree)什么是“树”?再完备的定义,都没有图直观。所以我在图中画了几棵“树”。你来看看,这些“树”都有什么特征?树满足递归定义的特性。也就是说,如果一个数据结构是树结构,那么剔除掉根结点后,得到的若干个子结构也是树,通常称作子树。在一棵树中,根据结点之间层次关系的不同,对结点的称呼也有所不同。我们来看下面这棵树,如下图所示:A 结点是 B 结点和 C 结点的上级,则 A 就是 B 和 C 的父结点,B 和 C 是 A 的子结点。B 和 C 同时是 A 的“孩子”,则可以称 B 和 C 互为

2020-10-23 07:10:40 577

原创 数据结构与算法:递归

如何理解“递归”?在数学与计算机科学中,递归 (Recursion))是指在函数的定义中使用函数自身的方法,直观上来看,就是某个函数自己调用自己。咱们生活中就有很多用到递归的例子。周末你带着女朋友去电影院看电影,女朋友问你,咱们现在坐在第几排啊?电影院里面太黑了,看不清,没法数,现在你怎么办?递归就开始排上用场了。于是你就问前面一排的人他是第几排,你想只要在他的数字上加一,就知道自己在哪一排了。但是,前面的人也看不清啊,所以他也问他前面的人。就这样一排一排往前问,直到问到第一排的人,说我在第一排,然后再

2020-10-14 12:56:47 502

原创 数据结构与算法:栈及其应用

文章目录栈的介绍栈的基本操作顺序栈链式栈栈在表达式求值中的应用栈的应用案例总结栈的介绍栈是一种特殊的线性表。栈与线性表的不同,体现在增和删的操作。具体而言,栈的数据结点必须后进先出。后进的意思是,栈的数据新增操作只能在末端进行,不允许在栈的中间某个结点后新增数据。先出的意思是,栈的数据删除操作也只能在末端进行,不允许在栈的中间某个结点后删除数据。也就是说,栈的数据新增和删除操作只能在这个线性表的表尾进行,即在线性表的基础上加了限制。如下图所示:栈的基本操作如何通过栈这个后进先出的线性表,来实现增

2020-10-14 10:56:00 683

原创 数据结构与算法:链表及其应用

基本介绍相比数组,链表是一种稍微复杂一点的数据结构。数组和链表都属于线性表,一个是顺序存储结构,一个是链式存储结构,最主要的的差别是底层存储结构。数组需要一块连续的内存空间来存储,对内存要求较高,如果申请一个100MB大小的数组,当内存中没有连续的、足够大的存储空间时,即使内存剩余空间总和大于100MB,仍然申请失败。链表恰恰相反,它并不需要一块连续的内存空间,它通过“指针”将一组零散的内存块串联起来使用,所以如果申请的是 100MB 大小的链表,只要剩余内存不小于于100MB根本不会有问题。如果剩余

2020-10-13 17:54:55 1033

原创 数据结构与算法:冒泡排序、插入排序、选择排序

排序算法太多了,有很多可能你连名字都没听说过,比如猴子排序、睡眠排序、面条排序等。我只讲众多排序算法中的一小撮,也是最经典的、最常用的:冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。按照时间复杂度把它们分成了三类,本文先分析冒泡、插入、选择三种排序算法排序算法时间复杂度是否基于比较冒泡、插入、选择O(n²)√快排、归并O(nlongn)√桶、计数、基数O(n)×带着问题去学习,是最有效的学习方法。所以按照惯例,我还是先给你

2020-10-07 22:14:56 1796

原创 数据结构与算法:数组

定义什么是数组?数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。先简单介绍一下几个关键词线性表、连续的内存空间线性表(Linear List),顾名思义,线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。其实除了数组,链表、队列、栈等也是线性表结构。而与它相对立的概念是非线性表,比如二叉树、图等。之所以叫非线性,是因为,在非线性表中,数据之间并不是简单的前后关系连续的内存空间和相同类型的数据,正是因为这两个限制,它才有了

2020-10-06 11:44:56 433

原创 数据结构与算法:复杂度分析

为什么需要复杂度分析?你可能会有些疑惑,我把代码跑一遍,通过统计、监控,就能得到算法执行的时间和占用的内存大小。为什么还要做时间、空间复杂度分析呢?这种分析方法能比我实实在在跑一遍得到的数据更准确吗?首先,我可以肯定地说,你这种评估算法执行效率的方法是正确的。很多数据结构和算法书籍还给这种方法起了一个名字,叫事后统计法。但是,这种统计方法有非常大的局限性。1.测试结果非常依赖测试环境测试环境中硬件的不同会对测试结果有很大的影响。 比如,我们拿同样一段代码,分别用 Intel Core i9 处理器和

2020-10-05 17:49:52 490

原创 Android组件化实战六:路由架构设计

前言结合前面的模块之间的交互,主要分析了类加载、全局Map记录(跳转目标Class)两种交互方式,以及APT和JavaPoet技术生成类文件,本文分析组件化的路由架构,我们到底需要通过APT和JavaPoet生成什么样的类文件呢?组件化路由架构设计先来看这样一幅架构设计图,组文件记录是一对一的即一个子模块对应一个组文件记录,而一个组文件记录对应多个路径文件记录,第二点比较好理解,因为各个子模块有多个Activity,对应多个路径信息。对应第一点,为什么要生成一对一的组(名)文件记录呢?试想一下,如果

2020-06-25 07:29:17 741

原创 Android组件化实战五: APT的高级用法JavaPoet

前言上一篇文章简单介绍了APT及其使用,生成相应的java文件,帮我们执行相关的操作,生成java文件的方式是字符串拼接的方式,但是如果要生成的java文件成员属性和方法比较多,这种方式就比较麻烦了,而且容易出现人为失误。所有就有了API调用的方式生成java文件,也就是JavaPoet。什么是JavaPoet项目主页及源码:https://github.com/square/javapoetAPT + JavaPoet = 超级利刃JavaPoet是square推出的开源java代码生成框架,提

2020-06-18 10:49:15 689

原创 Android组件化实战四: APT的介绍与使用

前言上一篇文章分析了组件化模块交互的两种实现方式,对于全局Map保存目标Activity的路径信息和类对象方案,如果Activity的数量繁多,则需要在主模块app的application中重复执行多次保存操作,既不优雅,又不符合实际开发场景,我们想到的解决之一就是想办法生成一个来完成这个重复枯燥的任务,生成一个类来帮我们找到跳转目标Activity的class对象。好比Butterknife生成一个文件专门完成findViewById的操作一样。这就涉及到注解处理器即apt技术,接下来就了解apt的使用

2020-06-18 08:20:06 1996 4

原创 Android组件化实战三: 模块之间的交互

前言上一篇文章记录了组件化开发中的项目部署需要注意的地方,而本文旨在实现模块之间的交互,比如页面的跳转,数据的传递等等,而在集成化模式下,各个子模块都是library,到底该如何实现呢?首先我们要知道传统的组件间的通信方式,以及其适用场景和优缺点。组件间通信的传统方式EventBus:不同的消息需要定义不同的EventBean(一对一),导致EventBean会非常多,而且一对多就会混乱、难以维护反射:反射技术可以实现,维护成本高且容易出现高版本@hide限制隐式意图:维护成本还好,只是比较麻烦

2020-06-12 17:40:39 3263

原创 Android 组件化实战二: 项目部署

前言组件化项目的意义主要体现在这几个方面,首先就是面试的时候,如果简历上写了三五年的工作经历,但是被问到组件化的相关原理打不上来,确实说不过去。在开发需求层面,即不相互依赖、又可以相互交互、任意组合、高度解耦;在团队开发效率层面,可以分模块打包、测试,统一版本管理。Phone Module和Android Library区别、切换[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uZF1rvIC-1591940447347)(C:\Users\dell\Pictures\C

2020-06-12 13:43:08 750

原创 Android 组件化实战一: Gradle基础语法

前言组件化的重要性无需多言,Android 组件化系列文章旨在彻底掌握组件化的原理,从0到1搭建一个自定义的组件化框架。本文主要介绍组件化过程中项目部署涉及的Gradle基本语法。打印信息// 在app/build.gradle文件中println("hello world!")println"hello world!"println'hello world!'效果一样:hello world!println 666结果:666变量的使用方式在工程根目录新建文件gradle文件con

2020-06-12 09:04:51 807

原创 Android屏幕刷新机制原理分析

60Hz刷新频率由来12fps:由于人类眼睛的特殊生理结构,如果所看画面之帧率高于美秒越10~12帧的时候,就会认为是连贯的24fps:有声电影的拍摄及播放帧率均为美秒24帧,对一般人而言已经算可接受30fps:早期的高动态电子游戏,帧率少于美秒30帧的话就会显得不连贯,这是因为没有动态模糊使流畅度降低60fps:在与手机交互的过程中,如触摸和反馈 60帧以下是能感觉出来的,60帧以上不能察觉变化当帧率低于60fps时感觉画面有卡顿迟滞现象Android系统每隔16ms发出VSYNC信号(1

2020-06-11 12:46:17 4610 1

原创 Android UI绘制流程之测量篇

经过前一片前奏的分析,我们知道从ViewRootImpl的performTraversals方法正式进入View的测量、布局、绘制流程。本文着重分析View的measure流程。直接上代码吧frameworks/base/core/java/android/view/ViewRootImpl.javaprivate void performTraversals() { ... if (!mStopped || mReportNextDraw) { boolean focu

2020-05-20 15:31:25 1220

原创 Android UI绘制流程前奏

1.前言2.View是如何添加到屏幕窗口上的要弄清楚UI绘制流程和原理,我们首先要了解的就是View是如何被添加到屏幕窗口上的。带着这个问题我们来进行源码分析,关于界面的展示,立马浮现在脑海的就是这样一段代码:public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(

2020-05-18 22:10:15 1026

原创 Activity的启动流程分析与总结

前言​看了数片分析Activity启动流程的文章,但是自从看了《Android进阶解密》关于Activity启动流程的分析,我就放弃了自己撸一遍的念头。因为书里关于这部分的分析比较详细。这里记录一下书中关于Activity的启动流程。加深一下印象,便于以后温习查看。Activity的启动过程分为两种,一种是根Activity的启动过程,可以认为是初次点击桌面的应用图标,启动Manifest中注册的作为应用的启动页面的Activity。根Activity的启动过程也可以理解为应用程序的启动过程。另一种就是

2020-05-17 13:16:29 3679 2

原创 Application创建流程分析

前言要想启动一个应用程序,首先要保证这个应用程所需要的应用程序进程已经创建启动。AMS在启动应用程序时,会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote孵化器进程来启动需要的应用程序进程。因此应用程序进程启动过程可以概括为两个部分:AMS发送启动应用程序进程请求Zygote接收请求并创建应用程序进程关于这部分的具体流程分析可参考《Android进阶解密》第二章内容。本文重点分析Zygote创建应用程序进程走到ActivityThread的main方法后,创建Applica

2020-05-15 16:46:44 1274

原创 彻底掌握Android touch事件的分发机制

文章目录1. 基本介绍1.1 MotionEvent1.2 控件的事件分发、拦截、消费1.3 大致流程图2. Activity对点击事件分发过程3.ViewGroup的touch事件分发过程3.1 宏观结构3.1 步骤1的具体代码及分析3.2 步骤 2 具体代码及分析3.3 步骤3具体代码及分析3.4 为什么 DOWN 事件如此特殊3.5 容易被遗漏的 CANCEL 事件4. View对touch事件的处理过程5. 总结主要参考文献:任玉刚《Android开发艺术探索》1. 基本介绍1.1 Motio

2020-05-14 16:37:10 620

原创 任性,通过线程检查子线程照样更新UI

前言关于子线程更新UI的文章,网上一搜一大堆,但是还是自己总结了一下。受篇幅所限,也许大家根本没有耐心看完,这里就先说结论吧主线程和UI线程是两个不同的概念UI线程指的是ViewRootImpl实例化时,所在的线程如果ViewRootImpl在主线程实例化,那么主线程就是UI线程,在子线程实例化,子线程就是UI线程即使ViewRootImpl实例化了,通过checkThread线程检查...

2020-05-06 22:32:12 554

原创 Lambda表达式不再只是听说

文章目录1. Lambda表达式简介1.1 什么是Lambda?1.2 为什么要使用Lambda表达式?1.3 Lambda对接口的要求2. Lambda表达式基础语法2.1接口准备2.2 通过对上面接口的使用来了解Lambda语法2.2.1 Lambda表达式基础语法3.Lambda表达式语法精简3.1参数类型精简3.2参数列表小括号精简3.3 方法体大括号精简3.4 return精简4.Lam...

2020-04-30 22:20:49 414

原创 EventBus的使用及实现原理

1.EventBus的介绍与使用1.1常见的组件间的通信方式Intent:跳转+传参(局限性非常大)Handler:通常用来更新主线程UI,使用不当容易出现内存泄露Interface:接口回调,仅限于同一线程中数据交互BroadcastReceiver:有序广播+无序广播AIDL:跨进程通信,代码阅读性不友好,维护成本偏高EventBus优点代码简单,快Jar包小,~50k...

2020-03-14 13:28:20 1957

原创 Bitmap之巨图加载

前言在Android开发中,有时候会有加载巨图(长图)的需求,可以上下左右滑动,双击放大或缩小如何加载一个大图而不产生OOM呢?使用体统提供的BitmapRegionDecoder,区域解码器,可以用来解码一个矩形区域(Rect)的图像,有了这个我们就可以自定义一块矩形的区域,然后根据手势来移动矩形区域的位置就能慢慢看到整张图片了。效果演示:1.初始化变量public BigImageV...

2020-03-05 13:38:29 803

原创 Bitmap之内存管理

文章目录前言1.Bitmap简介2.BitmapFactory.Options控制图片解码的参数3.Bitmap的内存占用3.Bitmap的高效加载/内存压缩/采样率压缩4.Bitmap的缓存策略5.Bitmap的内存复用6.小结前言在Android应用程序内存问题中,Bitmap内存问题,占了相当的比重,所以弄清楚Bitmap内存管理的机制原理就尤为重要。下面就分析总结一下,Bitmap内存...

2020-03-04 21:23:26 1121

原创 Bitmap之压缩方案

文章目录前言1.基础知识1.1色彩模式1.2四种模式的区别1.3具体对比1.4bitmap内存占用大小计算方式1.5图片存在的形式1.6BitampFactory加载Bitmap对象的方式2.压缩方案2.1采样率压缩2.2尺寸压缩2.3质量压缩2.4哈夫曼压缩2.4.1背景介绍2.4.2代码逻辑2.4.3压缩原理前言在Bitmap的内存管理中,介绍了Bitmap的压缩、缓存、复用等问题。其中的...

2020-02-27 17:10:29 2863

原创 数据结构与算法:哈夫曼树与哈夫曼编码

1.Haffman树我们先以成绩评级举例分析,一步一步的认识Haffman树和Haffman编码。分数0~5960~6970~7980~8990~100成绩不及格及格中等良好优秀所占比例5%15%40%30%10%如果是要真实实现这个功能,当然有更好的逻辑实现。但是这里为了便于分析,就拿这样的伪代码举例了。通过if 判断语句进行成绩评...

2020-02-26 22:32:20 7122 1

原创 Android性能优化四:卡顿监测方案及原理

文章目录1.卡顿介绍及优化工具的选择1.1背景介绍1.2工具介绍2.自动化卡顿检测方案原理2.1自动化卡顿监测原理2.2具体实现2.3第三方自动检测库AndroidPerformanceMonitor和BlockCanary3.ANR的分析与实战3.1ANR的分类,也就是四大组件的ANR3.2ANR执行流程3.3ANR分析思路4.卡顿单点问题检测方案4.1IPC问题监测指标4.2常规方案4.3IP...

2020-02-08 16:09:51 3265 1

原创 Android性能优化系列三:布局优化

UI绘制流程与原理CPU与GPU工作流程CPU的任务繁多,做逻辑计算外,还要做内存管理、显示操作,因此在实际运算的时候性能会大打折扣,在没有GPU的时代,不能显示复杂的图形,其运算速度远更不上今天复杂三维游戏的要求。即使CPU的工作频率超过2GH或更高,对它绘制图形提高也不大,这时GPU的设计就出来了。结构图对比如下:黄色:Control控制器,用于协调控制整个CPU的运行,包括取出指令、...

2020-02-05 20:23:11 630

原创 Android性能优化系列二:内存优化

文章目录内存优化方向以及工具简介Java内存管理机制Android内存管理机制内存抖动内存泄露Memory AnalyzerARTHook优雅检测不合理图片Bitmap内存模型获取bitmap占用内存的方式不合理图片处理的常规方式ARTHook介绍避免可控的内存泄露非静态内部类导致的内存泄露Handler造成的内存泄露没有正确使用Context注册监听为关闭注册监听为关闭Bitmap未及时释放资源...

2020-02-03 16:53:07 581

原创 Android性能优化系列一:启动优化

文章目录黑白屏优化冷/热/暖启动代码未优化造成的问题App启动时间检测方式方式一:adb命令方式二:手动打点启动优化工具选择traceview介绍Systrace介绍优雅获取方法耗时异步优化分析异步优化方案优化-启动器启动器的具体使用更优秀的延迟初始化方案更优方案黑白屏优化黑白屏原因​ 在App的启动流程中,我们已知:当系统加载并启动App时,需要消耗相应的时间,即使不到1s,用户也会感觉...

2020-02-01 12:56:57 1207

原创 不得不知道的Java锁

1.Java主流锁的整体认知话不多说,直接上图,先对Java主流锁有一个整体的认知2.乐观锁悲观锁概念悲观锁与乐观锁是一种广义概念,体现的是看待线程同步的不同角度2.1乐观锁定义:乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据锁实现:CAS算法,例如AtomicInteger类的原子自增是通过CAS自旋实现...

2020-01-14 11:35:12 289

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除