操作过Android手机的朋友应该对在待机界面拖动图标的交互效果都有比较深刻的印象,比如说,当把图标拖动起来,图标会悬浮并随着拖动变换位置,当拖动释放后,图标会自动的寻找附近合适的空白网格位置。Android在实现这个效果的过程中采用了很多编程技巧,本文着重论述的VacantCell缓存就很具有代表性。 VacantCell缓存主要是对同一种类型对象的缓存机制,这种机制的目的是复用已经分配过但已过期的对象,从而避免频繁的new新的对象。我们知道对象分配是一件比较耗费系统资源的事情,在需要频繁、大量的分配对象的时候Android平台很可能出现堆内存不足进而导致系统变慢、应用报错重启等严重问题。用户在待机界面拖动图标是很频繁的事情,而Android的屏幕中空白网格的寻址算法就采用了这种VacantCell缓存来避免频繁new大量新的对象。VacantCell类的实现其实很简单,就不到50行实现代码:
- static final class VacantCell {
-
- int cellX;
-
- int cellY;
-
- int spanX;
-
- int spanY;
-
- // We can create up to 523 vacant cells on a 4x4 grid, 100 seems
-
- // like a reasonable compromise given the size of a VacantCell and
-
- // the fact that the user is not likely to touch an empty 4x4 grid
-
- // very often
-
- private static final int POOL_LIMIT = 100;
-
- private static final Object sLock = new Object();
-
- private static int sAcquiredCount = 0;
-
- private static VacantCell sRoot;
-
- private VacantCell next;
-
- static VacantCell acquire() {
-
- synchronized (sLock) {
-
- if (sRoot == null) {
-
- return new VacantCell();
-
- }
-
-
- VacantCell info = sRoot;
-
- sRoot = info.next;
-
- sAcquiredCount--;
-
- return info;
-
- }
-
- }
-
- void release() {
-
- synchronized (sLock) {
-
- if (sAcquiredCount < POOL_LIMIT) {
-
- sAcquiredCount++;
-
- next = sRoot;
-
- sRoot = this;
-
- }
-
- }
-
- }
-
- @Override
-
- public String toString() {
-
- return "VacantCell[x=" + cellX + ", y=" + cellY + ", spanX=" + spanX +
-
- ", spanY=" + spanY + "]";
-
- }
-
- }
可以看到,VacantCell实际上是一个Java静态内部类,其外部类CellLayout.java的代码路径是packagesappsLauncher2srccomandroidlauncher2CellLayout.java(具体如何下载Android gingerbread Launcher单个模块的下载方法见 Android源码下载——用git clone实现单个目录下载)。