How can an Android cursor be at a negative position?
Asked Answered
D

4

3

While learning to iterate over a cursor, I learned that I needed to first move to position "-1" and then use "moveToNext" in a loop:

cursor.moveToPosition(-1);
for (int i = 0; cursor.moveToNext(); i++) {
  //do something with the cursor
}

While mathematically this makes sense, I don't know what it means to move to a cursor to a negative position. The documentation just says it's valid–doesn't seem to say how it's used.

Is this used ONLY to make iteration possible, or is there other use cases for the position -1?

Detestable answered 17/12, 2014 at 16:23 Comment(9)
This is pretty standard for cursors: the cursor starts before the first row (which has index 0). https://mcmap.net/q/99549/-what-39-s-the-best-way-to-iterate-an-android-cursorElisabeth
you dont move to a negative position you move it to the first position cursor.moveToFirst() aka 0Colonize
@Colonize if I moved to the first position and there was only one position, I'd never enter the loop.Detestable
because you move to the next positon before you do the first one so you skip the first positionColonize
I learned that I needed to first move to position "-1" I don't see much in the linked question that could lead you to believe that. Use moveToFirst and a while loop.Barrybarrymore
@Barrybarrymore I believe @Detestable is referring to my comment on the accepted answer to that question. Basically there are 2 clean ways to iterate: (a) moveToPosition(-1) followed by a while loop, and, (b) moveToFirst followed by a do-while loop.Custombuilt
@VickyChijwani: i don't consider moveToPosition(-1) to be clean, as it involves a magic number. A moveToBeforeFirst is really missing.Barrybarrymore
@Barrybarrymore Agreed. But moveToFirst + do-while loop won't work either, I just realized. If there are no items in the cursor, the do-while loop will still start an iteration and end up throwing an error. My mistake there. So that leaves option (a) only.Custombuilt
@VickyChijwani moveToFirst does work if you wrap it in an if statement, there is a reason moveToFirst returns a boolean you shouldnt just ignore itColonize
C
3

A cursor should not be at a negative position, a cursors data starts at position 0 which is why you always need to move the cursor to the first position before getting the data using

if(cursor.moveToFirst()){
    //you have data in the cursor
}

now to go through the cursor just simply use a do/while loop

do{
    //process cursor data
}while(cursor.moveToNext);

what you are doing with your for loop breaks that convention, if you move your cursor to the first position then try executing your for loop the cursor will try to move to the next position before you even process the first position. This is why you dont enter the for loop when you have 1 thing in the cursor

Colonize answered 17/12, 2014 at 16:38 Comment(9)
If it "should not be at a negative position", why does "moveToPosition" accept -1?Detestable
because its the default starting position no matter if there is or isnt dataColonize
It will accept any negative number, but if the number is negative it will default to -1. The code inside the cursor checks if position < 0, if it is it sets its instance variable mPos to -1 (the default) which allows the other methods to work as expected.Fernandez
@Fernandez so did I use it as it was intended to be used then?Detestable
@Detestable no the correct way to use a cursor is to move it to the first positionColonize
Well you don't want to use a for loop, a while loop makes more sense since the method returns a boolean. This way you don't have to worry about the i. When you create a cursor, it should default to -1, its in the constructor to most known subclasses of Cursor (interface). So it should already be at -1. So unless the cursor is null or it has been moved before, moveToNext() will move it to 0 if it can. So you could just use moveToNext(). moveToFirst() can be more readable sometimes if people don't understand how it works. also it could be useful if you want to move it to the first position.Fernandez
I've seen it used without moveToFirst() in Google applications that are open source, such as the Google I/O 2014 application. See link below for example (line 102). github.com/google/iosched/blob/…Fernandez
@Fernandez I wouldn't recommend using the cursor without moveToPosition(-1) or moveToFirst(). For example if you're using a CursorLoader, the loader re-uses the same Cursor instance so you must reset it before iterating. See my comment elsewhere for more details.Custombuilt
@VickyChijwani, good point. If you know the cursor may not be in the default position you should use moveToFirst(). It depends on the type of cursor, that one extra call isn't hurting anyones performance.Fernandez
F
1

The -1 index in cursors is the default starting position and the fallback position. Calling moveToFirst will always move to position 0 if it exists. You want to make sure if you do use moveToFirst, you process that entry then call moveToNext.

if(cursor.moveToFirst()){ // moves to 0, process it.
    process(...);
  while(cursor.moveToNext()){ // moves to 1...n, process them.
     process(...);
   }
 }

That is just one way to approach it, hope it helps.

Good Luck

Fernandez answered 17/12, 2014 at 16:33 Comment(2)
Using this method, I have to repeat process(...);. Seems like a code smell to me.Detestable
well process is a method, so it would be called the same amount of times regardless. It will be called sizeOf(cursor) times. moveToNext actually just calls moveToPosition(mPos + 1) internally, so you could just use moveToNext() if you know that the cursor is not null and its at -1.Fernandez
R
1

I suspect that default cursor position was intentionally set to -1 to make us able to iterate with just while(cursor.moveToNext()) {...}. There is no other reasons to have negative positions of cursor.

You don't need to reset position to -1 as long as you haven't affect this cursor before.

Reinwald answered 22/12, 2017 at 12:2 Comment(0)
F
0

-1 is the default position of a cursor and you always need to move the cursor to the first position ie 0th index. To perform your activity

cursor.moveToFirst(); //moves the cursor to the first position

Now to iterate

while(cursor.moveToNext())//when there's a value in cursor.moveToNext
{
//your action to be performed
}
Fungicide answered 17/12, 2014 at 16:49 Comment(2)
In your code cursor.moveToPosition(-1) and subsequent cursor.moveToNext() is equivalent to statement cursor.moveToFirst() which directly moves cursor to position 0Fungicide
Correct me if I'm wrong, but this method will skip the first element, or simply never enter the loop if there is only one element.Detestable

© 2022 - 2024 — McMap. All rights reserved.