[译]通过 Hardware Layer 提升 Android 动画性能

欢迎转载,但请务必在明确位置注明文章出处! http://johnnyshieh.github.io/android/2017/01/11/android-hardware-layer-animation/

当有人问我关于动画性能表现不佳问题时,我首先会问他们是否使用 Hardware layer。

在动画过程中你的视图可能在每一帧都需要进行重绘。如果使用 Hardware layer,可以避免重绘每一帧,因为 View 的渲染一旦进入离屏缓冲区就能够被复用。

另外,Hardware Layer 缓存在 GPU 上,它能够使动画中的某些操作变得更顺畅。通过使用 Hardware Layer 能够迅速渲染简单的变换(如,移动,旋转,缩放,透明度)。因为许多动画都是多种变换的组合,所以使用 Hardware Layer 能够显著提高动画性能。

用法

在使用 Hardware layer 之前,你的视图需要启用硬件加速,可以在 AndroidManifest 文件中的 application 或所在的 activity 加上android:hardwareAccelerated="true", 当 Target API >= 14 时,硬件加速是默认启用的。

View 的 layer API 非常简单:View.setLayerType()。你应该只是暂时设置 Hardware Layer,因为它们无法自动释放(稍后介绍)。基本使用步骤如下:

阅读全文

线程安全之 synchronized 关键字

欢迎转载,但请务必在明确位置注明文章出处! http://johnnyshieh.github.io/java/2017/01/10/java-synchronized/

一般在遇到线程安全的问题时候,大家都经常会使用 synchronized 关键字,来达到线程互斥访问的目的,但是这也间接造成它被程序员滥用的局面。下面分析 synchronized 关键字的原理、用法以及注意事项,帮助大家更好地使用它。

1. synchronized 的用法

synchronized 关键字可以修饰代码块或者方法,是最基本的互斥同步手段,可以避免多个线程之间的竞争条件(race conditions)。

1
2
3
4
5
// 修饰代码块
synchronized (ReferenceType) {...}

// 修饰方法(包括静态方法)
synchronized MethodDeclaration 

2. 实现原理

synchronized 关键字可以使得同一时刻只有一个线程能访问一个代码块或者方法,但是其内部原理究竟是如何呢。要理解其原理,首先要知道一点:所有对象都自动含有单一的锁与其对应(每个已加载的类对象也对应一个锁),这个锁也叫作互斥锁。用 synchronized 修饰即代表着加了某一个对象的锁,修饰代码块时明确指明是什么对象的锁,而在修饰方法时,如果修饰成员方法,指被调用该方法对象的锁,如果修饰静态方法,指该 Class 类型的锁。

在线程执行到 synchronized 修饰的代码块或者方法时,会尝试获取一个对象的互斥锁,执行完后会释放这个锁。如果获取对象锁失败,当前线程就要阻塞等待,所以当一个线程持有一个对象的锁时,其他线程无法获得这个锁,从而达到互斥访问的目的。在执行 synchronized 方法或 synchronized 代码块时出现异常,JVM 会自动释放获取的锁。

阅读全文

Java 内存模型

欢迎转载,但请务必在明确位置注明文章出处! http://johnnyshieh.github.io/java/2017/01/05/java-memory-model/

为了写出正确工作的并发程序,我们非常有必要理解 Java 内存模型。Java 内存模型描述了不同线程如何以及何时可以看到被其他线程修改后的共享变量的值,以及如何对共享变量执行同步操作。下面从一些基本概念开始解析 Java 内存模型,让大家理解多线程通信时需要注意的一些事项。

1. 内存模型

由于计算机的内存与处理器的运算速度有几个数量级的差距,所以现代计算机系统都会加入一层或多层读写速度接近处理器运算速度的高速缓存作为中间缓冲:将运算需要的数据先复制到缓存中,让运算更快地进行,当运算结束后再从缓存同步会内存中,这样处理器就无须等待缓慢的内存读写。但是这样会引入缓存一致性问题,在多处理器系统中,每个处理器有独立的高速缓存,而它们又共享同一主内存,所以在修改同一内存区域时,不知道以哪个缓存数据为准。下图描述了处理器、高速缓存与主内存之间的交互关系:

在操作系统中,cpu的最小执行单位是线程,所以在计算机系统中,内存模型是线程对内存或高速缓存读写过程的抽象。

阅读全文

2016年终总结

不知不觉2016又要过去了,去年开始计划每年的最后一天写一篇年终总结,所以在元旦来临之前总结下今年的经历,迎接新一年的到来。

首先值得高兴的是,可以通过百度直接搜索到我的博客了,去年还是不能搜索到的。博客的样式也在闲余时间中修修改改,现在的样式自己比较满意。不过今年才写了12篇博客,上半年工作比较忙,工作中做的需求也没学到多少新鲜的知识,所以有几个月都没写博客。在新的一年要更好地管理时间,多自学新技术,提高博客输出产能。

上半年写了一个基于 Volley 扩展的网络请求框架 VolleyEx ,学习了网络请求和图片加载的相关内容,但后面看到了 Retrofit 的设计,架构非常优美,所以记录自己扩展 Volley 框架的文章就写了2篇就停止了。后面在几个月的空闲时间中写了干货集中营的移动App,主要是为了学习 RxJava、Retrofit、Dagger2、Glide 等流行的开源框架,这个项目 – Gank 在 Github 上的 Star 数有两百多,是我目前的第一个开源项目,有这么多人赞同很开心。

阅读全文

Android命名规范与编码风格

欢迎转载,但请务必在明确位置注明文章出处! http://johnnyshieh.github.io/android/2016/12/22/android-coding-standards/

在团队开发项目中,统一的命名规范与编码风格非常重要,只有这样才像一个优秀团队开发的产品。而且这样方便阅读其他人的代码,便于后期维护。我觉得 Android 源码的可读性很好,风格统一,而在实际项目中经常看到混乱的风格,缩进有的是tab有的是space,命名有的是中文拼音有的是英文,看上去非常的乱。相信大家都喜欢简洁整齐的代码,这就需要团队成员稍微牺牲下个性,遵守统一的规范,自己读起来也赏心悦目。下面我根据自己的一些编码规范和网上的一些资料整理出一套 Android 命名规范,至于编码风格是根据 Google 的提供的 Android code style 略微修改而成,直接在 Android Studio 导入即可, 所以下面主要是介绍命名规范内容。

1. Android 命名规范

下面的命名规范,有些是我个人习惯,有不喜欢的地方可以复制后修改即可,做到简单易记就好,便于团队成员遵守。

基本命名方式

  1. 大驼峰命名法(UpperCamelCase):所有单词的第一个字母大写

  2. 小驼峰命名法(lowerCamelCase):除首单词外,其余所有单词的第一个字母大写

  3. 下划线命名法(case1_case2):单词与单词之间用下划线间隔,所有单词小写

一般建议用来命名的单词简单明了,不要用中文拼音,找个词典翻译下还能提高自己英文水平。有些单词可以写成一些约定俗成的缩写,也可以根据团队成员间的约定进行缩写命名。

阅读全文