Logische fout met SQLite-query

Dus ik maak een aanvraag voor mijn klas waarbij de gebruiker een formulier verzendt en de gegevens worden opgeslagen in een database. Op dit moment probeer ik een controle uit te voeren die controleert of de gebruikersnaam die de gebruiker probeert te kiezen in de database bestaat of niet. Hier is mijn code nu:

//Username duplicate check                                                                                                                       
String mSelection = MyContentProvider.COLUMN_USERNAME + "= ?";
String[] mSelectionArgs = new String[] { "Username" };
String[] mProjection = new String[]{MyContentProvider.COLUMN_USERNAME};
mCursor = getContentResolver().query(MyContentProvider.CONTENT_URI,
                                     mProjection,
                                     mSelection,
                                     mSelectionArgs, 
                                     null);
if (mCursor.moveToFirst()){
if (userName.getText().toString().equals(mCursor.getString(mCursor.getColumnIndex(MyContentProvider.COLUMN_USERNAME)))){
    submitCheck = false;
    userName.setHint("Username taken");
}   

}     mCursor.close ();

Wanneer dit wordt uitgevoerd, genereert de if-instructie een fout. Dit is de logcat:

06-24 00:56:55.125: E/AndroidRuntime(907): FATAL EXCEPTION: main
06-24 00:56:55.125: E/AndroidRuntime(907): android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.database.AbstractCursor.checkPosition(AbstractCursor.java:400)
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.database.CursorWrapper.getString(CursorWrapper.java:114)
06-24 00:56:55.125: E/AndroidRuntime(907):  at com.connor.black.HomeWork2Activity$1.onClick(HomeWork2Activity.java:132)
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.view.View.performClick(View.java:3511)
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.view.View$PerformClick.run(View.java:14105)
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.os.Handler.handleCallback(Handler.java:605)
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.os.Handler.dispatchMessage(Handler.java:92)
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.os.Looper.loop(Looper.java:137)
06-24 00:56:55.125: E/AndroidRuntime(907):  at android.app.ActivityThread.main(ActivityThread.java:4424)
06-24 00:56:55.125: E/AndroidRuntime(907):  at java.lang.reflect.Method.invokeNative(Native Method)
06-24 00:56:55.125: E/AndroidRuntime(907):  at java.lang.reflect.Method.invoke(Method.java:511)
06-24 00:56:55.125: E/AndroidRuntime(907):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
06-24 00:56:55.125: E/AndroidRuntime(907):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
06-24 00:56:55.125: E/AndroidRuntime(907):  at dalvik.system.NativeStart.main(Native Method)

Hier is een klein beetje van mijn inhoudprovider voor een bepaalde context:

public class MyContentProvider extends ContentProvider{
public final static String DBNAME = "FormStorage";
public static final String AUTHORITY = "com.connor.black.provider";
public final static String TABLE_NAMESTABLE = "formstable";
private static UriMatcher sUriMatcher;

public final static String COLUMN_FIRSTNAME = "FirstName";
public final static String COLUMN_LASTNAME = "LastName";
public final static String COLUMN_PHONE = "PhoneNumber";
public final static String COLUMN_EMAIL = "Email";
public final static String COLUMN_USERNAME = "Username";
public final static String COLUMN_PASSWORD = "Password";
public final static String COLUMN_GENDER = "Gender";
public final static String COLUMN_COUNTRY = "Country";
public static final Uri CONTENT_URI = Uri.parse("content://com.connor.black.provider/" + TABLE_NAMESTABLE);


private static final String SQL_CREATE_MAIN = "CREATE TABLE " + TABLE_NAMESTABLE + "("+"_ID INTEGER PRIMARY KEY, "+
                                                                    "FirstName TEXT, " +
                                                                    "LastName TEXT, " +
                                                                    "PhoneNumber TEXT, " +
                                                                    "Email TEXT, " +
                                                                    "Username TEXT, " +
                                                                    "Password TEXT, " +
                                                                    "Gender TEXT, " +
                                                                    "Country TEXT)";
0

2 antwoord

U moet de kolomindexwaarden niet hard coderen, rechtstreeks in uw code. Dit is zo omdat,

  1. Het is een slecht ontwerp.

  2. Het maakt uw project moeilijk te onderhouden (dat wil zeggen als u later een kolom aan uw tabel toevoegt, is het mogelijk dat het gehele getal van de kolom kan veranderen, waardoor uw code wordt overtreden).

  3. Er is geen manier om zeker te weten of 0 overeenkomt met de kolom gebruikersnaam. De gehele waarde wordt toegewezen door een interne bibliotheek die uw SQLite-database beheert ... u moet nooit vertrouwen op interne bibliotheken, omdat het Android-team de implementatie op elk moment kan wijzigen.

Ik stel voor dat je je code wijzigt in het volgende:

int userCol = mCursor.getColumnIndex(MyContentProvider.USERNAME_COLUMN);
mCursor.getString(userCol);
0
toegevoegd
Ik denk dat ik iets heb gevonden. Ik heb een ongeldige pointer-uitzondering gekregen toen ik deze final int userCol = mCursor.getColumnIndex (MyContentProvider.USERNAME_COLUMN); probeerde
toegevoegd de auteur Connor Black, de bron
Ik heb de gegevens gewist, opnieuw uitgevoerd en ik krijg nog steeds een uitzondering voor een lege aanwijzer
toegevoegd de auteur Connor Black, de bron
Ik heb mijn vinkje gewijzigd in deze if (userName.getText (). ToString (). Equals (mCursor.getString (mCur & zwnj; sor.getColumnIndex (M & zwnj; yContentProvider.COL & zwnj; UMN_USERNAME)))) maar dit heeft nieuwe fouten veroorzaakt. Ik ga mijn vraag updaten
toegevoegd de auteur Connor Black, de bron
Ja, ik heb MyContentProvider.COLUMN_USERNAME doorgegeven
toegevoegd de auteur Connor Black, de bron
Ik heb het teruggezet en de gebruiker kan nog steeds een bestaande gebruikersnaam invoeren.
toegevoegd de auteur Connor Black, de bron
Ik krijg geen force close-fout, alleen een logische fout. Ik kan het formulier twee keer indienen met dezelfde gebruikersnaam, wat niet mag gebeuren.
toegevoegd de auteur Connor Black, de bron
Allereerst heb ik mijn antwoord bijgewerkt. Ten tweede ... dat is een probleem en het betekent waarschijnlijk dat de USERNAME_COLUMN niet bestaat. Probeer de installatie van uw toepassing ongedaan te maken en vervolgens opnieuw te installeren (of ga naar "Instellingen -> Toepassingen -> [uw toepassing] -> Gegevens wissen"). Test het dan uit. Als het nog steeds niet werkt, laat het me weten.
toegevoegd de auteur Alex Lockwood, de bron
Wacht, sorry. Je hebt het MyContentProvider.COLUMN_USERNAME toch doorgegeven? (niet USERNAME_COLUMN )
toegevoegd de auteur Alex Lockwood, de bron
Ofwel gebruikersnaam , userName.getText() , userName.getText (). ToString() , of mCursor is null . Ga na welke null is en werk uw vraag met de informatie bij.
toegevoegd de auteur Alex Lockwood, de bron
@ConnorBlack, hebt u de aanroep mCursor.moveToFirst() verwijderd? Deze oproep was belangrijk ... zet het terug :)
toegevoegd de auteur Alex Lockwood, de bron
Krijgt u een foutmelding? Update uw vraag zodat deze 100% up-to-date is ... Ik kan niet raden welk probleem u ondervindt, tenzij alles is bijgewerkt en ik weet precies wat er aan de hand is. Voor de liefde van God verbreek je deze regel code ook in meerdere regels: userName.getText (). ToString (). Equals (mCursor.getString (mCurs & zwnj; or.getColumnIndex (My & zwnj; ContentProvider.COLU & zwnj; MN_USERNAME))) . U maakt het ongelooflijk moeilijk voor uzelf om uw code te debuggen, want er is geen manier om te vertellen welk deel van de regel u een NullPointerException geeft.
toegevoegd de auteur Alex Lockwood, de bron
toegevoegd de auteur Alex Lockwood, de bron

Het ziet er 0 uit is _ID in uw tabel probeer het met de 5e index ..........

0
toegevoegd
Ik deed het, werkte niet.
toegevoegd de auteur Connor Black, de bron
Wat mij betreft, zou u zich zelfs niet bezig moeten houden met wat de werkelijke waarden zijn, omdat ze op elk moment kunnen veranderen. De werkelijke gehele waarden moeten voor 100% worden geabstraheerd uit uw code.
toegevoegd de auteur Alex Lockwood, de bron
oh sorry, gebruikersnaam is de 5e index. Het is beter om getColumnIndex (MyContentProvider.USERNAME_COLUMN) te proberen; zoals Alex zei per stander ..........
toegevoegd de auteur Dheeresh Singh, de bron