Ragnarok Note

Articles by Ragnarok Zhou

Project Lacie Initiate

Motivation

我记得去年在组内介绍Annotation和Annotation Process Tool的时候,当时不少小伙伴都认为这个是一个非常棒的工具,用来做代码生成非常合适,但是也存在不少问题,主要的争论点在于,对于大型的项目,其代码量非常大,无论是在IDE内或者在命令行中进行编译,即使只是普通的增量编译,打包,也需要耗上非常长的时间。而普通的APT则需要每次都先拉起一次编译过程,因为实际上整个Annotation Processing是Java编译中的一个步骤,另外如果在Annotation Processing的过程中另外产生了新的代码的话,还需要重新编译生成的代码,这会导致整个编译过程变得更加漫长,如下图,为Java源码编译的过程,摘自OpenJDK官网。

于是,后续我就逐渐开始想方法实现有一个类似Annotation Processor的API的工具,但并不需要拉起Javac进行编译,只需要输入源码即可,然后由开发者自行定义生成代码的规则,即可完成APT的功能。

Research

要实现这样的一个工具,最先迫切的就是需要一个语法解析器,这样子才能从源码中提取出所需要的信息。当时候的想法是自己来实现Tokenizer和Parser(真庆幸大学的时候教编译原理的灭绝大法师的训练,我还记得怎么写哈哈哈哈),但很快我就找到了JavaCC这个工具,这玩意可以说是Java编译器的生成工具,实际上Javac的前端也是这个东西来生成的。但是JavaCC生成的代码非常乱并且其API并不是很好用。当时候我想当JDK中一定是有单独Javac前端独立出来的,于是我又找到了JDK中的tools ...

TextView预渲染研究

Android中的TextView是整个framework中最复杂的控件之一,负责Android中显示文本的大部分工作,framwork中的许多控件也直接或者间接的继承于TextView,例如Button,EditText等。其内部实现也相当复杂,单论代码行数来说,android-22中TextView有足足9509行,另外,TextView中许多操作都非常繁重,例如setText操作,需要设置SpanWatcher,或者需要重现创建一个SpannableString,还需要根据情况重新创建Text Layout,这些操作加起来之后令一次setText操作非常耗时。为了提升TextView的渲染效率,最近研究了一下预渲染的方法,接下来给大家讲解一下原理。

TextView渲染基本原理

首先来介绍下TextView的基本渲染原理,总的来说,TextView中负责渲染文字的主要是这三个类:

  1. BoringLayout
    主要负责显示单行文本,并提供了isBoring方法来判断是否满足单行文本的条件。

  2. DynamicLayout
    当文本为Spannable的时候,TextView就会使用它来负责文本的显示,在内部设置了SpanWatcher,当检测到span改变的时候,会进行reflow,重新计算布局。

  3. StaticLayout
    当文本为非单行文本,且非Spannable的时候,就会使用StaticLayout,内部并不会监听span的变化,因此效率上会比DynamicLayout高,只需一次布局的创建即可,但其实内部也能显示SpannableString,只是不能在span变化之后重新进行布局而已。

另外,以上三个类都继承于Layout类,在此类中统一负责文本的具体绘制,在Layout ...

使用Kotlin进行Android开发

What is Kotlin

Kotlin,原意是在俄罗斯的一个小岛,JetBrain在2011年推出了以这个来命名的一个运行在JVM上的语言, 看上去有点类似C#和Scala的结合,并且同为静态类型,作为一门JVM上的语言,可以轻松兼容Java,并且整个语言设计的非常轻量。目前的版本为0.12.200,尚未发布正式版。


Kotlin的下载和配置在其官网上有,在这里就不再赘述了,值得一提的是,作为JetBrains家出品的语言,自家的IDEA当然全力支持!

基本语法介绍

Kotlin的语法非常简洁,熟悉Java或者Scala的人都可以快速上手:

函数声明:

fun foo(va: Int): Int {
    return 1
}

也可以单行声明:

fun foo(va: Int): Int = 1

lambda当然也是支持的:

var c = {foo: Int -> println(foo ...

使用JDK的Parser来解析Java源代码

在JDK中,自带了一套相关的编译API,可以在Java中发起编译流程,解析Java源文件然后获取其语法树,在JDK的tools.jar(OSX下可以在/Library/Java/JavaVirtualMachines/jdk_version/Contents/Home/lib中找到)中包含着这整套API,但是这却不是Oracle和OpenJDK发布中的公开API,因此对于这套API,并没有官方的正式文档来进行说明。但是,也有不少项目利用了这套API来做了不少事情,例如大名鼎鼎的lombok使用了这套API在Annotation Processing阶段修改了源代码中的语法树,最终结果相当于直接在源文件中插入了新的代码!

由于这套API目前缺少相关文档,使用起来比较困难,例如,解析源代码中的所有变量,并打印出来:

public class JavaParser {

    private static final String path = "User.java";

    private JavacFileManager fileManager;
    private JavacTool javacTool;

    public JavaParser() {
        Context ...

探索在Android中使用Emoji Font的方法

先说结论,在android4.4以前,无法使用像苹果那样的emoji字体样式,最简单的解决方案是使用ImageSpan配合SpannableString,而在4.4及之后的版本,则可以直接采用类似iOS/OSX的方案进行快速渲染。

Apple Color Emoji

Emoji表情,最初是从日本的“绘文字”演化过来,在没有正式定下规范之前,日本的三大电信运营商,NTT DoCoMo,au/KDDI,Softbank都各自有一套关于Emoji的编码规范,而且在这个时候,每个Emoji表情对应的表情图片也是没有统一规范的。这时候,应用最广泛的是应该的属于日本软银(Softbank)的Softbank编码了,在iOS系统的早期的版本上,采用的也是这个编码规范。

后来,在2010年10月,随着Unicode6.0的发布,Emoji的编码以及对应的表情图片正式被规范化,核心Emoji表情包含722个Emoji编码。而到了Unicode 7.0(2014年6月发行)之后,更多的Emoji表情被加入了进来,包括一些其他比较偏门的Emoji表情组,例如WebdingsWingdings,也被编入了Unicode 7 ...