我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android开发笔记之:深入理解Cursor相关的性能问题

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android开发笔记之:深入理解Cursor相关的性能问题

当数据库中存有大量数据的时候,用Cursor查询时要注意,有可能引发性能问题。数据库查询出来的Cursor都会由一个CursorWindow来进行数据管理,包括内存空间的申请和数据的填充。CursorWindow对Cursor中的内容大小有限制,限制为1024*1024也就是1M,换句话说Cursor中数据的大小不能超过1M,如果超过1M会引发如下的错误:
代码如下:
08-23 05:48:31.838: DEBUG/Cursor(1805): skip_rows row 149
08-23 05:48:31.844: ERROR/CursorWindow(1805): need to grow: mSize = 1048576, size = 11499, freeSpace() = 7397, numRows = 80
08-23 05:48:31.844: ERROR/CursorWindow(1805): not growing since there are already 80 row(s), max size 1048576
08-23 05:48:31.844: ERROR/Cursor(1805): Failed allocating 11499 bytes for blob at 228,7
08-23 05:48:31.849: DEBUG/Cursor(1805): finish_program_and_get_row_count row 12
08-23 05:48:31.851: DEBUG/browser/BrowserBookmarkFoldersAdapter(1805): getView()-Position:149
08-23 05:48:32.019: DEBUG/Cursor(1805): skip_rows row 148

这表明CursorWindow中的空闲空间已经不足,已经在申请新的空间,但似乎申请失败。这个错误有时候会导致查询得到的Cursor为null,有时候不会引发太严重的问题。但是它会引起性能上的问题,不停的申请空间会占用大量的CPU时间,从而导致整个手机变卡。特别是在ListView或GridView中绑定的Cursor,会导致无法滑动,或者滑动变的十分的卡。用Android2.3的原生Browser,打开其中的历史记录,当有超过200条历史记录时,不停的滑动,特别是由下向上滑时会变的十分的卡,而对于其书签,如果条目超过100,且每个都有缩略图时,滑动会变得特别的卡,甚至都打不开,就是这个原因。
这个问题没有根本的解法,这是Android系统的限制,唯一可行的就是想办法避免,也就是尽可能让Cursor的大小 小于1M,以下是可行的方法:
1. 只查询需要的字段
这个特别重要,根据UI显示的需要,或者实际的需要查询需要的字段。就是一定要给ContentResolver.query(uri, projection)第二个参数PROJECTION,如果这个参数为null,那么就会查询表中所有的字段,那么当条数一增加Cursor的大小 会增长很快。Browser中历史记录的原因就是它在query的时候查询了所有的字段,其数所库中保存了favicon和thumbnail二进制文件,因此当包含了这二个字段时,Cursor的容量很容易就达到了限制。
2. 二进制文件不要存在数据库中
数据库仅适用于保存一些较短文字,整数,布尔,浮点数等一些,易于查询和操作的轻量级的数据,目的也是在于快速搜索和查询。对于像图片,较长的文字(如文章)等大数据,最好直接以文件形式存储在硬盘中,然后在数据库保存它们的访问路径。对于像favicon这样的小图片也可以考虑存在数据库中,但是像对于thumbnail的图片就不明智,除非整个应用在数量上有限制(比如只有几十或百级)否则很容易在查询的时候达到1M的限制。
3. 对于特别大量的数据超过5000级或万级或十万级或百万级的要分段查询
无论表中的一条记录数据量如何的小,当条数达到5000级或者万级或者更多的时候,还是会达到1M的限制,这时就需要分段查询,比如每次查询500个,或者1000个。另外,如果是要做展示用,这么多数据一下子出来,用户也不方便查看。
【实例】Android2.3书签,历史记录和最多访问三个页面当数据量达到300左右时,就会出现滑动很卡的现象,特别是由下向上滑动时,特别的卡,会狂打出:
代码如下:
08-23 05:48:31.844: ERROR/CursorWindow(1805): need to grow: mSize = 1048576, size = 11499, freeSpace() = 7397, numRows = 80
08-23 05:48:31.844: ERROR/CursorWindow(1805) : not growing since there are already 80 row(s), max size 1048576
08-23 05:48:31.844: ERROR/Cursor(1805): Failed allocating 11499 bytes for blob at 228,7

这样的LOG。而书签似乎都没有办法打开和滑动,其特别的卡。
究其原因就是它们在查询的时候都用了同一个字段集Browser.HISTORY_PROJECTION这个是把bookmarks表中的所有字段都 查询出来。书签,历史记录和最多访问虽是三个不同的展示页,但它们的数据是相同的都是来自bookmarks表。Bookmarks表中存有_id,title,url,bookmark,favicon,touch_icon,thumbnail等字段,其中favicon和thumbnail是二进制图片数据(byte[])。Browser.HISTORY_PROJECTION里面包含了所有的字段,当然也包含了favicon和thumbnail,所以当条目一旦达到200多时,Cursor就会达到其1M的限制,因此会导致性能下降,滑动变卡。
事实上对于历史记录和最多访问二个页面来讲thumbnail和touch_icon根本就没有用到,它只需要_id,title,url,bookmark和favicon;对于书签页,也仅是在GRID时才用到thumbnail。所以,只需要把查询时的字段集Browser.HISTORY_PROJECTION中的THUMBNAIL去掉,即可以解决滑动变卡。

您可能感兴趣的文章:Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题Android开发中遇到端口号占用问题解决方法Fedora14下android开发: eclipse与ibus确有冲突的问题分析Android开发笔记之:ListView刷新顺序的问题详解在android开发中尽量不要使用中文路径的问题详解android开发环境遇到adt无法启动的问题分析及解决方法Android程序启动时出现黑屏问题的解决方法Android中fragment嵌套fragment问题解决方法Android Studio的中文乱码问题解决方法Android拍照保存在系统相册不显示的问题解决方法Android动态添加View的问题解决方法Android 异步获取网络图片并处理导致内存溢出问题解决方法Android开发常见问题总结


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android开发笔记之:深入理解Cursor相关的性能问题

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android开发笔记之:深入理解Cursor相关的性能问题

当数据库中存有大量数据的时候,用Cursor查询时要注意,有可能引发性能问题。数据库查询出来的Cursor都会由一个CursorWindow来进行数据管理,包括内存空间的申请和数据的填充。CursorWindow对Cursor中的内容大小有
2022-06-06

Android开发笔记之:深入理解多线程AsyncTask

Understanding AsyncTaskAsyncTask是Android 1.5 Cubake加入的用于实现异步操作的一个类,在此之前只能用Java SE库中的Thread来实现多线程异步,AsyncTask是Android平台自己
2022-06-06

Android开发笔记之:ListView刷新顺序的问题详解

背景一个典型的ListView,每个Item显示一个TextView,代表一个Task,需要实现二个编辑方式:一个是用CheckBox来标识任务已经完成,另一个要实现的编辑是删除任务。对于完成的CheckBox就直接放在布局中就可,但对于删
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录