0%

Android中绘制文字的方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
/**
* Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
* based on the Align setting in the paint.
*
* @param text The text to be drawn
* @param x The x-coordinate of the origin of the text being drawn
* @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
super.drawText(text, x, y, paint);
}

其中y文字baseline的y坐标

下图表示Paint.FontMetrics中存储的文字的各种信息(来源:简书):

阅读全文 »

二叉树的遍历根据根节点与左右子节点的遍历顺序的不同分为三种:

  • 前序遍历

    根左右:先遍历根节点,再左子树,再右子树(先从根节点开始,记录左节点直到没有)

    第一个为根节点

  • 中序遍历

    左根右:先左子树,再根子树,再右子树(从树的最左边的节点开始遍历)

  • 后序遍历

    左右根:先左子树,后右子树,再根节点

    最后一个为根节点

在遍历的时候,当父节点只有一个子节点时,依然要遵循以上三种遍历的先后顺序(没有该子节点则不写内容),以保证某一侧的子树(“左边的子树”或“右边的子树”)所有节点都被完全遍历,之后才可以根据遍历的规则切换到下一子树。

如如下子树:

1
2
3
4
5
6
7
      G
/ \
D M
/ \ / \
A F H Z
/
E
阅读全文 »

最近看到一个帖子,表示有人以"YYYY-MM-dd"格式化日期时,在2019-12-30时出现2020-12-30的BUG。

本文来简单分析一下为什么会出现这个情况。

根据JDK文档关于日期的定义y表示的是我们日常使用的年份,而Y表示的是Week year

先了解几个知识点:

Week year

阅读全文 »

Android中的跨进程通信IPC主要有以下几种方式:

  • BroadcastReceiver
  • ContentProvider
  • AIDL
  • Messenger
  • Socket
  • 文件

Linux 已经提供了管道、消息队列、共享内存和 Socket 等 IPC 机制

进程是资源分配的基本单位,线程是调度的基本单位。

一些基础知识

阅读全文 »

日常开发中,常用的存储键值对的数据结构是HashMap,根据Java笔记之HashMap保存数据Java笔记之计算Java对象的大小及其应用可以知道,HashMap存储键值对会占用比较多的内存控件,而对于内存限制较大的Android平台来说,为了避免这种浪费,官方推荐我们使用SpareArrayArrayMap,本文对这两个类的实现进行分析比较。

SpareArray以及他的衍生类都是以基本类型key,因为避免了自动装箱,并且用数组直接保存key、value(而非像HashMap那样将其封装为Node对象后再保存),因而节省了内存。

ArrayMap则支持所有类型的key,他是keyvalue全部保存在一个数组中n位为keyn+1位为value),避免了将其封装为Node对象带来的内存消耗。

当要保存的数据量比较小(小于几千个)的时候,如果KEY是基本类型,推荐使用SparseArray及其衍生类以节省内存,如果KEY是其他类型则使用ArrayMap;否则使用HashMap更加高效

SpareArray

阅读全文 »

原理

注意 除非特殊说明,以下所说的计算Java对象大小,不涉及该对象所持有的对象本身的大小,只计算该Java对象本身的大小(其中引用类型对象大小只计算为4 bytes),如果要遍历计算Java对象大小(包含其持有对象的大小)可以参考这篇文章 Sizeof for Java

一个Java对象在内存中的大小包括以下(以64位JVM启用压缩为例,综合这里这里的信息整理):

分类 大小(byte) 备注
对象头 8 保存对象的 class 信息、ID、在虚拟机中的状态
Oop指针 4
数据区 对象实际包含的数据,引用类型大小为4 bytes
数组长度 4 只有数组对象才有
8比特对齐 将对象总大小对齐到8字节所需的填充

此外,如果是(非静态)内部类的话,由于他默认持有外部类的引用,所以会比普通类的对象多4个byte。

https://stackoverflow.com/a/12193259/8389461

阅读全文 »

为什么匿名内部类使用局部引用要用final

先说结论:

由于JAVA匿名内部类的实现并不是真正的闭包,而是在生成内部类的时候将局部变量的引用拷贝了一份到内部类中。如果不将这个外部类设置为final的话,外部类或者内部类修改这个局部变量后,另外一处使用的仍然是修改前的值,这样就会产生问题,而如果将其修改为final则保证了局部变量与内部类使用的值是一致的。

JDK1.8 后局部变量不要求用final了?

不对,仍然是要求final的。

阅读全文 »

ThreadLocalThread中用来保存线程私有变量的数据结构。

一个ThreadLocal只能保存一个值,有set/get/remove方法。

Thread有一个threadLocalsThreadLocal.ThreadLocalMap)变量,该变量是一个定制的Hash Map,用来保存线程私有的数据(类型为ThreadLocal<?> Key, Object Value)。

特点

  1. 一个Thread可以有多个ThreadLocal变量

  2. 不同Thread可以通过一个ThreadLocal变量分别保存不同的变量而互不影响

  3. 如果不同的Thread使用的ThreadLocal变量保存的是同一个引用类型的对象(假设为obj),无论这些Thread使用的是同一个ThreadLocal对象还是完全不同的ThreadLocal对象,只要obj指向的对象改变,其余线程中的ThreadLocal对象也会访问到obj的最新值。

阅读全文 »

Photo by Pixabay from Pexels

HashMap使用由Node<K,V>(继承自Map.Entry<K,V>)组成的数组table保存数据。

table中保存数据时根据keyhashCode计算到一个随机保存位置(但都在table数组的大小范围内),当存储的数据总量超过加载系数loadFactor规定的阈值时则对table进行扩容

HashMap有以下全局变量

阅读全文 »