Why is this variable set to an empty string when it is already initialized to an empty string?

I took the following snippet from snippet 5 in this content provider developer guide.

The confusion is that in the first statement String[] mSelectionArgs = {""};

, mSelectionArgs[0]

the value is set ""

.

Then, if mSearchString

empty ( TextUtils.isEmpty(mSearchString)

) is then mSelectionArgs[0]

assigned again ""

.

So the question is, why do they set it to an empty string when it's already initialized to an empty string?

/*
 * This defines a one-element String array to contain the selection argument.
 */
String[] mSelectionArgs = {""};

// Gets a word from the UI
mSearchString = mSearchWord.getText().toString();

// Remember to insert code here to check for invalid or malicious input.

// If the word is the empty string, gets everything
if (TextUtils.isEmpty(mSearchString)) {
    // Setting the selection clause to null will return all words
    mSelectionClause = null;
    mSelectionArgs[0] = "";

} else {
    // Constructs a selection clause that matches the word that the user entered.
    mSelectionClause = UserDictionary.Words.WORD + " = ?";

    // Moves the user input string to the selection arguments.
    mSelectionArgs[0] = mSearchString;

}
...

      

+3


source to share


2 answers


Aside from the added clarity and readability of the code as noted in another answer, this coding style makes the code less error prone and easier to maintain.

Thus, if the initial value is mSelectionArgs

changed or new code is added that overrides this value before the block is executed if-else

, the code in that block will execute correctly. Without this "rudimentary" assignment, a change as described above could result in an error that would be very difficult to track down.

As a side note:

This special piece of code is not that good (yes I know it is from the Android developer site ...) - if you pass null

as an selection

argument query()

then it is better to pass null

as an argument as well selectionArgs

. I would change this example to something like this (by setting selection

and selectionArgs

the value null):

// Gets a word from the UI

mSearchString = mSearchWord.getText().toString();

// Remember to insert code here to check for invalid or malicious input.

String[] mSelectionArgs = null;

// If the word is the empty string, gets everything
if (TextUtils.isEmpty(mSearchString)) {
    // Setting the selection clause to null will return all words
    mSelectionClause = null;
    mSelectionArgs = null;

} else {
    // Constructs a selection clause that matches the word that the user entered.
    mSelectionClause = UserDictionary.Words.WORD + " = ?";

    // Moves the user input string to the selection arguments.
    mSelectionArgs = new String[] {mSearchString};

}

      

Edit: Why is the above code snippet better than the original one?

Error passing null in quality selection

and not null in quality selectionArgs

. This array will be passed to the specific address ContentProvider

you are addressing and should not be used at all as it selection

does not contain any placeholders ?

. Anyone ContentProvider

violating this assumption is a mistake. While not a bug, it looks odd - why are you passing in an object that should be ignored anyway? It also has an execution cost (which is higher if ContentProvider

running in a different process) that is proportional to the size of the transferred object.



Edit 2: Why is the above code snippet much better than the original one? It turns out that what I said above can be misleading. I found this the hard way:

 Caused by: java.lang.IllegalArgumentException: Cannot bind argument at index 3 because the index is out of range.  The statement has 1 parameters.
        at android.database.sqlite.SQLiteProgram.bind(SQLiteProgram.java:212)
        at android.database.sqlite.SQLiteProgram.bindString(SQLiteProgram.java:166)
        at android.database.sqlite.SQLiteProgram.bindAllArgsAsStrings(SQLiteProgram.java:200)
        at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:47)
        at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314)
        at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1161)
        at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1032)
        at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1200)

      

The above exception was thrown because I tried to pass selectionArgs

one that contained more items than the number of ?

placeholders in selection

.

These two methods SQLiteProgram.java

should "blame" for this exception:

public void bindAllArgsAsStrings(String[] bindArgs) {
    if (bindArgs != null) {
        for (int i = bindArgs.length; i != 0; i--) {
            bindString(i, bindArgs[i - 1]);
        }
    }
}

private void bind(int index, Object value) {
    if (index < 1 || index > mNumParameters) {
        throw new IllegalArgumentException("Cannot bind argument at index "
                + index + " because the index is out of range.  "
                + "The statement has " + mNumParameters + " parameters.");
    }
    mBindArgs[index - 1] = value;
}

      

Now that I've learned about this behavior, I think that the sample code from the Android Developers site is not just ineffective, but also complete crap!

Bottom line: if you pass null

as selection

, pass null

as selectionArgs

. If selection

it is not null and contains ?

placeholders, make sure the length of the array selectionArgs

is equal to the number of placeholders ?

in selection

.

+2


source


I like it because it is symmetrical

if something
    var = x
else
    var = y

      



It is clear what var

is under each condition, without having to go back and visit its initial value.

+3


source







All Articles