温馨提示:在 ChatGPT 官网(www.chatgpt.com)使用 GPT-5.5、ChatGPT-Image-2 等模型时,需要 ChatGPT Plus 或更高等级的会员权限。如需购买账号或充值会员,请扫码添加我们客服咨询。
Cursor是Android中用于查询数据库(SQLite)返回的结果集指针,可以理解为一个指向查询结果表格的游标。,**核心用法:**,1. **获取Cursor**:通过ContentResolver.query()或SQLiteDatabase.query()返回,2. **移动指针**:moveToFirst()、moveToNext()、moveToPosition(),3. **读取数据**:getString(columnIndex)、getInt(columnIndex)等,按列索引取值,4. **必须关闭**:使用后调用Cursor.close()释放资源,**简单示例:**,``java,Cursor cursor = db.query("user", null, null, null, null, null, null);,if (cursor.moveToFirst()) {, do {, String name = cursor.getString(cursor.getColumnIndex("name"));, // 处理数据, } while (cursor.moveToNext());,},cursor.close();,``,注意:Cursor默认指向-1位置,必须先调用moveToFirst()才能访问第一条数据。
本文目录导读:
- 第一步:先搞清楚我们要查什么
- 第二步:Cursor是什么?它不是一个东西,是一个“指针”
- 第三步:怎么拿到这个Cursor?用ContentResolver
- 第四步:拿到了Cursor之后,怎么用它?三步走
- 第五步:用完Cursor后,一定要记得“关门”
- 大白话总结一下
- 你可能遇到的其他问题
- 最后的小建议
你好,我是AI教程网的小编,今天我们来聊一个Android开发里非常基础,但新手很容易搞混的东西——Cursor。
你可能刚开始学Android,或者正准备做一个需要存数据的App,你肯定会遇到“数据库”和“查询”这两个词,很多人一听到“数据库查询”,就会觉得很难,但别担心,我们用最简单的方法来搞清楚它。
第一步:先搞清楚我们要查什么
在Android里,我们经常会把数据存到SQLite数据库里,你可以把这个数据库想象成一个“超级表格”,这个表格有很多行和很多列,每一行就是一条数据,每一列就是一个信息。
我们要做一个“通讯录”App,那么我们的表格里,每一行就是一个联系人,每一列可能就是“名字”、“电话号码”、“邮箱”。
当我们想从手机里找出所有联系人的时候,就需要做一件事:查询,用代码来查询,就是query()。
第二步:Cursor是什么?它不是一个东西,是一个“指针”
很多人一开始会把Cursor想得很复杂,其实很简单。
你想象一下,你去图书馆找书,你找到了一整排书架,上面有几十本书,这些书就是你的查询结果,你不能一下子把几十本书都抱在手里看,你需要一本一本拿起来看。
Cursor就是你的那根手指头,或者一个“书签”。
它指向了这排书架的某一本书,一开始,它指向第一本书前面的位置(就是还没开始看),你让它动一下(调用moveToNext()方法),它就指向第一本书,你再让它动一下,它就指向第二本书。
Cursor的本质就是一个“结果集”的指针,它本身不存数据,它只是告诉你“你现在在看哪一行数据”,你需要通过它,才能把那一行里的具体信息(比如名字、电话)拿出来。
第三步:怎么拿到这个Cursor?用ContentResolver
在Android里,我们不用直接去打开数据库文件,系统提供了一个“中间人”,叫ContentResolver,你可以把它理解为“数据库管理员”。
你想查数据,就去敲管理员(ContentResolver)的门,跟他说:“我想查通讯录里所有名字叫‘张三’的联系人。”
管理员听完,就去数据库里查,然后给你一张“结果清单”(就是Cursor)和一个“指针”(指向清单的第一行前面)。
这个代码写出来就是:
// 假设我们已经有了一个ContentResolver对象叫 resolver
// 这个query方法就是去找数据
Cursor cursor = resolver.query(
Uri.parse("content://contacts/people"), // 问:去哪里查?查通讯录
null, // 问:查哪些列?null代表查全部列
"name = ?", // 问:条件是什么?名字等于...
new String[]{"张三"}, // 问:条件具体是什么?张三
null // 问:排序吗?不排
);
你看,就这么简单。query方法会从数据库里找到满足条件的数据,然后把它变成一个Cursor对象,交还给你。
第四步:拿到了Cursor之后,怎么用它?三步走
拿到了Cursor这根“指针”,你不能干瞪眼,得让它帮你把数据取出来,通常有三步。
第一步:让它移动到第一行数据
Cursor一开始指向第一行数据之前,你首先要调用一个方法:
if (cursor.moveToFirst()) {
// 移动成功了,说明有数据
// 现在cursor指着第一行数据
} else {
// 没有数据
}
moveToFirst() 这个方法,如果成功移动到第一行,就返回true,否则返回false(比如没查到任何数据),这是非常关键的检查。
第二步:从当前行取出具体的数据
我们知道通讯录表格里,有一列叫“名字”(列名通常是NAME或类似的,这里用DISPLAY_NAME举例),我们可以这样取出名字:
// 先拿到这一列在表格里的索引(位置)
int nameIndex = cursor.getColumnIndex("DISPLAY_NAME");
// 然后根据索引,拿到具体的字符串值
String name = cursor.getString(nameIndex);
这样,你的name变量就存好了当前这个联系人的名字了,同理,电话号码、邮箱也是这么取的,只是方法不同,比如拿数字用getInt(),拿电话号码用getString()(因为电话号码一般是字符串)。
第三步:处理完这一行,移动到下一行
如果你只有一个联系人,那处理完这一行就结束了,但如果有多个,你需要循环处理,这时候就用moveToNext():
while (cursor.moveToNext()) {
// 只要还能移动到下一行,就说明还有数据
// 在这里取这一行的数据
int nameIndex = cursor.getColumnIndex("DISPLAY_NAME");
String name = cursor.getString(nameIndex);
Log.d("MyApp", "找到联系人:" + name);
}
这个while循环会一直执行,直到cursor.moveToNext()返回false(也就是没有下一行了),这样就能把查到的所有联系人都处理一遍。
第五步:用完Cursor后,一定要记得“关门”
这一点非常重要,很多新手会忘记,Cursor就像你向系统借的一个东西,用完之后,不还回去,系统就会一直占用内存,如果用的多了,App就会变慢,甚至崩溃。
无论你是在Activity里,还是在Fragment里,一定要在finally代码块或者try-with-resources(Java 7以上)里,把Cursor关掉。
最简单的写法:
Cursor cursor = null;
try {
// ... 查询和处理的代码 ...
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
如果你用的是Kotlin,更简单:
resolver.query(...).use { cursor ->
// 在这里处理cursor
// 代码块执行完后,cursor会自动关闭
}
记住这个“关门”动作,这是一个好习惯,你不关,系统可能会出问题。
大白话总结一下
- 查询:就是去数据库里找数据,用
ContentResolver.query()这个方法。 - Cursor:不是数据本身,是一个 “指针” 或者 “结果清单的阅读器” ,它指向一行数据。
- 移动指针:用
moveToFirst()(去第一行)、moveToNext()(去下一行)、moveToPosition(int)(去指定行)。 - 取数据:用
getString()、getInt()等方法,配合getColumnIndex()(找到列的位置)。 - 循环处理:用
while(moveToNext())来遍历所有结果。 - 用完关闭:
cursor.close()必须执行,这能避免内存泄露。
你可能遇到的其他问题
问题1:查询很慢怎么办?
因为你查的数据太多,或者查询条件写得太复杂,新手可以这样做:
- 尽量用具体的列名,不要用
null查全部列。 - 不要在主线程(UI线程)里做查询,数据库操作有点慢,会卡住屏幕,应该用
AsyncTask、Handler或者现在的LiveData、Flow在后台线程做。
问题2:不小心把Cursor用错了,程序崩溃了怎么办?
这是新手最怕的,常见的错误:
- 空指针:如果查询没结果,
cursor可能是null,所以调用cursor.moveToFirst()之前,先判断一下cursor != null。 - 列名写错:
getColumnIndex("NAME")写成了getColumnIndex("NAEM"),这会导致返回-1(找不到),然后你拿着-1去取数据,程序就崩溃了,可以先打印日志检查列名。 - 忘记关闭:这个上面说了,一定要关。
问题3:我看到的教程里,有的地方用managedQuery,那个是什么?
那是很老的方法,才用managedQuery,它会把Cursor和Activity的生命周期绑定,但有很多问题,现在早就被废弃了,你应该用ContentResolver.query()。
最后的小建议
如果你刚开始学Android,不用去背复杂的原理,你就记住:
- 查询 =
ContentResolver.query() - 结果 =
Cursor - 遍历 =
while(cursor.moveToNext()) { 取数据 } - 用完 =
cursor.close()
就像学骑自行车,刚开始觉得很难,掌握平衡后就很自然了,Cursor也是,多写几遍,多调试几次,你就发现它其实不复杂。
希望这篇文章能帮你搞懂Android里的Cursor,如果有任何问题,或者想了解更多像ChatGPT、Claude、Midjourney、Gemini、Cursor、Suno这些AI工具的最新玩法,或者想了解AI资讯,都可以扫描我们网站页底的二维码,找我们的编辑咨询。
温馨提示:在 ChatGPT 官网(www.chatgpt.com)使用 GPT-5.5、ChatGPT-Image-2 等模型时,需要 ChatGPT Plus 或更高等级的会员权限。如需购买账号或充值会员,请扫码添加我们客服咨询。


网友评论