cursor的遍历时moveToFirst和moveToNext的区别

本文深入探讨了在使用SQLite和ContentProvider时,如何正确遍历Cursor。解释了Cursor初始位置为-1的原因,并提供了正确的遍历方法,避免遗漏首条记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原创链接:https://blog.youkuaiyun.com/zx422359126/article/details/75944216

问题:当时刚接触sqlite和contentProvider时候记得cursor初始位置不正确 所以要moveToFirst 才能使cursor正确指向第一个位置。那么问题来了,遍历的时候要用moveToNext(在我印象中是同时使用的),所以脑海中默认写法是这样:

        if (cursor!=null){
            try{
                cursor.moveToFirst();
                while(cursor.moveToNext()){
                    String address=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS));
                    Log.d(TAG, address);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                if (cursor!=null) {
                    cursor.close();
                }
            }
        }

但是这样并不对啊,这样把第一条结果略过了!那么为什么去掉moveToFirst()就正确了呢?

            try{
                //去掉moveToFirst
                while(cursor.moveToNext()){
                    String address=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS));
                    Log.d(TAG, address);
                }
            }

先看下面这段代码:

        Cursor cursor=contentResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,null,null,null,null);
        Log.d(TAG,"cursor初始位置"+cursor.getPosition());
        cursor.moveToFirst();
        Log.d(TAG,"movetofirst的位置"+cursor.getPosition()+"");

就是把初始位置和moveToFirst的位置记录一下,看logcat显示:
cursor初始位置-1
movetofirst的位置0
也就是说:cursor初始位置是在-1,而数据是从0开始的,所以cursor.moveToNext刚好是从-1变成0,不需要moveToFirst而是直接循环moveToNext就可以完成遍历。

钻下牛角尖:那我想两者一起用怎么办?其实也没什么难。

            cursor.moveToFirst();
            while(!cursor.isAfterLast()){
                //dosomething
                cursor.moveToNext();
            }

 或者

        if (cursor!=null && cursor.moveToFirst()){
                do {
                    String address = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS));
                    Log.d(TAG, address);
                } while (cursor.moveToNext());

/**

     * Move the cursor to the first row.
     *
     * <p>This method will return false if the cursor is empty.
     *
     * @return whether the move succeeded.
     */
这是moveToFirst()的源码注释,是一个boolean值,如果是空(查询不到结果,与null区分)返回false,所以moveToFirst也可以当作判断条件。

 

### 如何在代码中正确设置 Cursor 的位置 在 Android 开发中,`Cursor` 是用于操作数据库查询结果的核心对象之一。为了正确处理 `Cursor` 中的数据,合理设置其位置至关重要。 #### 设置 Cursor 位置的方法 以下是几种常见的方法来移动设置 `Cursor` 的当前位置: 1. **单行数据解析** 如果只需要解析一条记录,可以使用 `moveToFirst()` 方法将 `Cursor` 定位到第一条记录上。此方法返回布尔值,表示是否有可用的第一条记录。 ```java boolean isDataAvailable = cursor.moveToFirst(); if (isDataAvailable) { int value = cursor.getInt(cursor.getColumnIndex("column_name")); } ``` 2. **多行数据解析** 当有多个记录需要历时,可以通过 `moveToNext()` 方法逐行读取数据。通常会将其放在 `while` 循环中,直到没有更多记录为止。 ```java while (cursor.moveToNext()) { String data = cursor.getString(cursor.getColumnIndex("another_column")); // 处理每一行的数据 } ``` 3. **特定索引定位** 使用 `moveToPosition(int position)` 可以直接跳转到指定的行号(注意:索引从0开始)。如果目标位置超出范围,则返回 `false`。 ```java if (cursor.moveToPosition(5)) { // 跳转至第6行 long idValue = cursor.getLong(cursor.getColumnIndex("_id")); } else { Log.e("Error", "无法找到该位置"); } ``` 4. **最后一条记录** 若要快速访问最后一项,可调用 `moveToLast()` 方法完成定位工作。 ```java if (cursor.moveToLast()) { double result = cursor.getDouble(cursor.getColumnIndexOrThrow("numeric_field")); } ``` 以上所有涉及游标的移动函数均需考虑边界情况以及异常捕获机制[^1]。 另外,在实际项目开发过程中,除了上述基本操作外,还可以借助版本控制系统如 Git 来管理复杂的业务逻辑变更历史,从而更好地维护与优化关于 Cursor 的相关源码文件结构及其功能性扩展部分[^2]。 #### 注意事项 - 始终记得关闭不再使用的 Cursor 对象实例以防资源泄漏问题发生。 - 在执行任何移位动作之前先验证当前状态是否有效。 ```java if (!cursor.isClosed()) { try { cursor.close(); } catch(Exception e){ Log.d("DatabaseHelper","Exception on closing the cursor.",e); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值