`
zhiying201039
  • 浏览: 43132 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android原理揭秘系列之VacantCell缓存

 
阅读更多

操作过Android手机的朋友应该对在待机界面拖动图标的交互效果都有比较深刻的印象,比如说,当把图标拖动起来,图标会悬浮并随着拖动变换位置,当拖动释放后,图标会自动的寻找附近合适的空白网格位置。Android在实现这个效果的过程中采用了很多编程技巧,本文着重论述的VacantCell缓存就很具有代表性。
VacantCell缓存主要是对同一种类型对象的缓存机制,这种机制的目的是复用已经分配过但已过期的对象,从而避免频繁的new新的对象。我们知道对象分配是一件比较耗费系统资源的事情,在需要频繁、大量的分配对象的时候Android平台很可能出现堆内存不足进而导致系统变慢、应用报错重启等严重问题。用户在待机界面拖动图标是很频繁的事情,而Android的屏幕中空白网格的寻址算法就采用了这种VacantCell缓存来避免频繁new大量新的对象。

VacantCell类的实现其实很简单,就不到50行实现代码:

Java code
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的代码路径是\packages\apps\Launcher2\src\com\android\launcher2\CellLayout.java(具体如何下载Android gingerbread Launcher单个模块的下载方法见博文Android源码下载——用git clone实现单个目录下载)。

下面我们具体分析下VacantCell的缓冲机制是如何实现的。

cellX、cellY、spanX、spanY几个成员是空白网格的纵横索引号和占据相应单元网格数,我们这里可以不用关心。

POOL_LIMIT定义了可以缓存的VacantCell的最大值,正如注释所说,最多可以分配多达523个VacantCell对象,但是对于4X4的屏幕网格定义来说,100个的缓冲数应该是足够的了。也就是说,这个100的数值是一个经验值,我们可以根据实际情况作灵活修改。

sLock是一个Java Object对象,主要是拿来作同步控制的,我们可以不用关心。

sAcquiredCount是一个非常重要的变量,其实际上就是一个计数器,实时的统计当前缓存了多少个VacantCell对象值。根据这个计数器和POOL_LIMIT可以控制缓存对象不超过POOL_LIMIT的上限。

sRoot和next是缓存VacantCell对象链式存储的两个关键引用,分别表示VacantCell对象链表的表头和特定VacantCell对象链接的下一对象的引用。

好了,下面介绍VacantCell缓存的两个关键静态方法acquire()和非静态方法release()。

当需要VacantCell新对象的时候,Launcher会调用静态内部类的VacantCell的静态方法acquire()以获取新的VacantCell对象。请注意,这里获取新对象不是直接new一个VacantCell对象,而是acquire的。我们看acquire方法的内部,当sRoot为null的时候,是直接new VacantCell并直接return的,因为这个时候实际上还没有缓存可用;当sRoot不为null,这意味着已经有缓存的VacantCell对象了,那么直接从链表中取出sRoot指向的对象,并将sRoot所在对象指向的next作为新的表头sRoot,同时把sAcquiredCount计数减1。这实际上是一种典型的从链表中删除表头的操作,相信熟悉数据结构的朋友对此都不会陌生。

如果说acquire()方法提供的是如何利用VacantCell链式缓存,那么release()方法解决的就是如何构建VacantCell链式缓存的问题。我们看到,只有sAcquiredCount < POOL_LIMIT的前提下才会将VacantCell对象加入链式缓存。将当前VacantCell对象加入链式存储也很简单,将当前VacantCell对象的next指向原来的表头,将静态sRoot应用指向当前对象,同时sAcquiredCount加1。也就是说,这个操作其实就是把当前VacantCell对象插入VacantCell链表的表头。

那么如何使用这个VacantCell对象缓存呢?第一,当需要新的VacantCell对象的时候,通过调用VacantCell的静态方法acquire()来获取对象,而不是直接new VacantCell对象;第二,当一个VacantCell对象已经过期,不再需要的时候,调用该对象的release()方法将这个不再需要的对象加入缓存。

需要指出的是,如果直接new VacantCell对象也不会有直接的问题,只不过这意味着没有采用VacantCell缓存机制;如果一个对象不需要时不显示调用release()方法也不会有直接的问题,这意味着这个对象不会加入进VacantCell缓存链表,当没有链表各节点对象的引用关联,这个对象最终将被Android的Dalvik虚拟机当做垃圾自动回收。

本文详细分析了Android Launcher模块VacantCell缓存的实现原理,当我们需要频繁构造、释放大量的相同类型的Java对象的时候,我们考虑采用类似的缓存机制,这在某些场合下能有效的解决频繁分配对象导致的内存不足的问题。

 

引用 7 楼 rav009 的回复:
VacantCell 怎么判定一个VacantCell对象已经过期呢?


这里过期的意思是指该对象不再需要了,这个是算法自己能够明确的,当不需要该该对象的时候就是过期,这个时候显示的调用release()方法将这个不再需要的对象加入缓存。

 

本帖原始出处:http://blog.csdn.net/droidpioneer/article/details/6758057

分享到:
评论

相关推荐

    Android在线视频播放之边缓存边播放

    本篇文章将深入探讨如何在Android中实现这种功能,主要围绕"Android在线视频播放之边缓存边播放"的主题展开。 首先,我们需要了解流媒体的基本概念。流媒体是指在网络上传输并实时播放的多媒体数据,它允许用户在...

    Android图片的三级缓存原理

    Android图片的三级缓存原理,介绍了图片三级缓存的原理,介绍了Android中软引用的使用,以及lruCache进行图片缓存,请访问我的博客进行查看:http://blog.csdn.net/qq_20889581?viewmode=contents

    Android WebView 缓存详解

    Android WebView 缓存详解 一. 两种缓存类型: 页面缓存:加载一个网页时的html、JS、CSS等页面或者资源数据,这些缓存资源是由于浏览器 的行为而产生,开发者只能通过配置HTTP响应头影响浏览器的行为才能间接地...

    android缓存技术之文件缓存

    在Android应用开发中,缓存技术是至关重要的,它能够提高应用性能,减少网络请求,提升用户体验。本文将深入探讨Android中的文件缓存技术,尤其是如何利用文件来存储和读取字符串数据。文件缓存是一种常见的本地缓存...

    Android app缓存清理实现

    在Android应用开发中,缓存管理是至关重要的一个环节,它关系到应用的性能、内存使用以及用户体验。本文将深入探讨如何实现Android app的缓存清理,并基于提供的"CacheClear"压缩包文件,讲解如何封装一个获取和清理...

    Android应用源码之Android 图片缓存、加载器.zip

    本压缩包“Android应用源码之Android 图片缓存、加载器.zip”包含了关于Android图片加载和缓存机制的源代码示例,将帮助我们深入理解这一核心话题。 首先,我们需要了解图片加载库的重要性。在Android中,常见的...

    Android 数据缓存工具类

    首先,我们要理解数据缓存的基本原理。数据缓存是一种在本地存储常用数据的技术,它减少了网络请求的次数,提高了应用响应速度。在Android中,常见的缓存机制有内存缓存和磁盘缓存。内存缓存(如LruCache)利用系统...

    Android应用缓存机制

    Android应用缓存机制是优化应用程序性能的关键组成部分,它涉及到如何高效地存储和检索数据,以减少网络请求和I/O操作,提升用户体验。Android系统提供了多种缓存策略和技术,包括内存缓存、磁盘缓存、SQLite数据库...

    Android-Glide原理缓存加载

    Glide原理解析,手写Glide框架。视频教程。 Glide三级缓存原理 Glide源码解析 相关算法讲解

    Android WebView加载网页以及本地图片缓存问题

    总结,Android的WebView组件提供了丰富的功能,能够加载远程和本地资源,同时支持缓存机制,提高用户体验。开发者需要根据实际需求调整其配置和行为,以实现最佳的加载效果和性能。在处理图片资源时,特别要注意路径...

    Android图片加载的三级缓存Demo

    这个"Android图片加载的三级缓存Demo"就是针对这一问题的一个实例,它通过LruCache、DiskLruCache这两种缓存机制来高效地管理和加载图片。 首先,LruCache(Least Recently Used Cache)是Android SDK提供的一个...

    android图片的异步下载和缓存

    "android图片的异步下载和缓存"这个主题涉及到如何高效、流畅地显示图片,避免阻塞UI线程,并且实现图片的本地缓存,提高用户体验。下面我们将详细探讨这两个核心概念。 1. **异步加载**: 在Android中,主线程...

    深踩Android Studio 缓存的坑及解决方法

    深踩 Android Studio 缓存的坑及解决方法 Android Studio 是 Android 应用开发的主要 IDE,但是在使用过程中,我们经常会遇到缓存的问题。缓存的问题会导致项目依赖项无法更新,从而影响项目的开发和编译。在这篇...

    Android实现新闻列表的磁盘缓存.zip

    在Android开发中,数据缓存是一项重要的技术,用于提高应用性能和用户体验。"Android实现新闻列表的磁盘缓存"项目就是针对这个问题提供的一种解决方案。它结合了MVP(Model-View-Presenter)架构模式、RxJava响应式...

    Android文件缓存与内存缓存

    在Android开发中,为了优化用户体验,提高应用性能,通常会采用文件缓存和内存缓存技术,特别是处理像ListView这样的滚动列表组件加载网络图片时。本文将深入探讨这两种缓存机制,以及如何解决图片错位问题。 首先...

    Android http缓存实现

    在Android开发中,HTTP缓存是一种重要的技术,它允许应用程序在本地存储网络请求的数据,以便在没有网络连接或网络连接不稳定时仍能访问这些数据,从而实现离线应用的功能。HTTP缓存主要遵循HTTP协议中的缓存控制...

    Android-一个Android和Java的reactive缓存库

    【Android-一个Android和Java的reactive缓存库】 在移动应用开发中,尤其是在Android平台上,数据缓存是一个至关重要的概念。它可以帮助提高应用程序的性能和用户体验,通过将经常访问的数据存储在本地,减少网络...

    android图片缓存优化,内存缓存加sdcard缓存,性能很好,防止oom

    本文将深入探讨Android图片缓存的优化策略,包括内存缓存和SDCard缓存,并以此为例详细解析`ImagesCache`这个项目。 内存缓存: 内存缓存是为了快速访问图片而设计的,它将图片数据存储在应用程序的内存中。当用户...

    Android缓存——将数据以对象的方式缓存到本地

    总结,Android缓存是提高应用性能的关键技术之一,尤其是在处理网络数据时。SharedPreferences作为简单易用的磁盘缓存方式,适用于存储少量的字符串型数据,如登录凭证。通过理解和实践CacheTestDemo,开发者可以更...

    android 图片的二级缓存

    下面将详细阐述二级缓存的工作原理、实现方式以及它如何帮助避免OOM。 一、二级缓存的概念 二级缓存通常包括内存缓存(一级缓存)和磁盘缓存(二级缓存)。当应用需要加载图片时,首先会尝试从内存缓存中查找,如果...

Global site tag (gtag.js) - Google Analytics