2013-05-19 92 views
0

我成功地在SQLite數據庫中設置了一組填充了緯度和經度的ListView。我編寫了代碼,以便我可以點擊其中的一對來調用Google地圖並從用戶當前位置導航。當我點擊時,我收到一個dialogFragment,詢問我是否想刪除LatLang對;如果用戶確認,該對將從SQLite數據庫中刪除,從列表中刪除,並重新填充列表。SQLite ListView CursorIndexOutofBoundsException:請求索引-1,大小爲0

得到這個工作後,我試圖重寫代碼,在SQLite數據庫中包含另一列以保存LatLang對的字符串標籤。但現在,當我點擊一個LatLang對,而不是打開谷歌地圖的意圖,沒有任何反應。當我保持點擊,然後確認刪除,應用程序崩潰與CursorIndexOutofBoundsException。我試過調試,進一步閱讀,並檢查stackoverflow存檔,但我仍然不知道發生了什麼。

如果有人看到任何明顯的事情,請告訴我。一般來說,我對編程仍然很陌生。

這裏是我的SQLite數據庫處理器類:

package com.detimil.breadcrumbs1; 

import java.util.ArrayList; 
import java.util.List; 

import android.content.ContentValues; 
import android.content.Context; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 

public class DatabaseHandler extends SQLiteOpenHelper { 

// All Static variables 
// Database Version 
private static final int DATABASE_VERSION = 1; 

// Database Name 
private static final String DATABASE_NAME = "breadcrumbsManager"; 

// Contacts table name 
private static final String TABLE_BREADCRUMBS = "breadcrumbs"; 

// Contacts Table Columns names 
private static final String KEY_ID = "id"; 
private static final String KEY_LABEL = "longitude"; 
private static final String KEY_LATITUDE = "latitude"; 
private static final String KEY_LONGITUDE = "longitude"; 


public DatabaseHandler(Context context) { 
    super(context, DATABASE_NAME, null, DATABASE_VERSION); 
} 

// Creating Tables 
@Override 
public void onCreate(SQLiteDatabase db) { 
    String CREATE_BREADCRUMBS_TABLE = "CREATE TABLE " + TABLE_BREADCRUMBS + "(" 
      + KEY_ID + " INTEGER PRIMARY KEY," + KEY_LABEL + " TEXT," + KEY_LATITUDE + " TEXT," 
      + KEY_LONGITUDE + " TEXT" + ")"; 
    db.execSQL(CREATE_BREADCRUMBS_TABLE); 
} 

// Upgrading database 
@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    // Drop older table if existed 
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_BREADCRUMBS); 

    // Create tables again 
    onCreate(db); 
} 

/** 
* All CRUD(Create, Read, Update, Delete) Operations 
*/ 


    // Adding new location/breadcrumb 
public void addBreadcrumb(Breadcrumb breadcrumb) { 
     SQLiteDatabase db = this.getWritableDatabase(); 

     ContentValues values = new ContentValues(); 
     values.put(KEY_LABEL, breadcrumb.getBreadcrumbLabel()); // Label 
     values.put(KEY_LATITUDE, breadcrumb.getBreadcrumbLatitude()); // Latitude 
     values.put(KEY_LONGITUDE, breadcrumb.getBreadcrumbLongitude()); // Longitude 

     // Inserting Row 
     db.insert(TABLE_BREADCRUMBS, null, values); 
     db.close(); // Closing database connection 
    } 


    // Getting single breadcrumb 
public Breadcrumb getBreadcrumb(int id) { 
    SQLiteDatabase db = this.getReadableDatabase(); 

    Cursor cursor = db.query(TABLE_BREADCRUMBS, new String[] { KEY_ID, KEY_LABEL, 
      KEY_LATITUDE, KEY_LONGITUDE }, KEY_ID + "=?", 
      new String[] { String.valueOf(id) }, null, null, null, null); 

//(I just edited this snippet as per advice from comment below. Unfortunately, the code still does not run correctly.) 
if (cursor.getCount() > 0){ 
     cursor.moveToFirst(); 
} 
     Breadcrumb breadcrumb = new Breadcrumb(Integer.parseInt(cursor.getString(0)), cursor.getString(1), 
     cursor.getInt(2), cursor.getInt(3)); 
    // return breadcrumb 
    cursor.close(); 
    return breadcrumb; 
} 


    // Getting All breadcrumbs 
    public List<Breadcrumb> getAllBreadcrumbs() { 
List<Breadcrumb> breadcrumbList = new ArrayList<Breadcrumb>(); 
    // Select All Query 
    String selectQuery = "SELECT * FROM " + TABLE_BREADCRUMBS; 

    SQLiteDatabase db = this.getWritableDatabase(); 
    Cursor cursor = db.rawQuery(selectQuery, null); 

    // looping through all rows and adding to list 
    if (cursor.moveToFirst()) { 
     do { 
      Breadcrumb breadcrumb = new Breadcrumb(); 
      breadcrumb.setId(Integer.parseInt(cursor.getString(0))); 
      breadcrumb.setBreadcrumbLabel(cursor.getString(1)); 
      breadcrumb.setBreadcrumbLatitude(cursor.getInt(2)); 
      breadcrumb.setBreadcrumbLongitude(cursor.getInt(3)); 
      // Adding location to list 
      breadcrumbList.add(breadcrumb); 
     } while (cursor.moveToNext()); 
    } 

    // return locations list 
    cursor.close(); 
    return breadcrumbList; 
} 

// Getting All breadcrumb labels (leaving out the Lats and Langs) 
public List<Breadcrumb> getAllBreadcrumbLabels() { 
List<Breadcrumb> breadcrumbLabelList = new ArrayList<Breadcrumb>(); 
// Select All Query 
String selectQuery = "SELECT * FROM " + TABLE_BREADCRUMBS; 

SQLiteDatabase db = this.getWritableDatabase(); 
Cursor cursor = db.rawQuery(selectQuery, null); 

// looping through all rows and adding to list 
if (cursor.moveToFirst()) { 
    do { 
     Breadcrumb breadcrumb = new Breadcrumb(); 
     breadcrumb.setId(Integer.parseInt(cursor.getString(0))); 
     breadcrumb.setBreadcrumbLabel(cursor.getString(2)); 
     // Adding label to list 
     breadcrumbLabelList.add(breadcrumb); 
    } while (cursor.moveToNext()); 
} 

// return locations list 
cursor.close(); 
return breadcrumbLabelList; 
} 

// Getting breadcrumbs/locations Count 
    public int getBreadcrumbsCount() { 
     String countQuery = "SELECT * FROM " + TABLE_BREADCRUMBS; 
     SQLiteDatabase db = this.getReadableDatabase(); 
     Cursor cursor = db.rawQuery(countQuery, null); 
     cursor.close(); 

     // return count 
     return cursor.getCount(); 
    } 


     //Updating single location 
    public int updateBreadcrumbs(Breadcrumb breadcrumb) { 
     SQLiteDatabase db = this.getWritableDatabase(); 

     ContentValues values = new ContentValues(); 
     values.put(KEY_LABEL, breadcrumb.getBreadcrumbLabel()); 
     values.put(KEY_LATITUDE, breadcrumb.getBreadcrumbLatitude()); 
     values.put(KEY_LONGITUDE, breadcrumb.getBreadcrumbLongitude()); 

     //updating row 
     return db.update(TABLE_BREADCRUMBS, values, KEY_ID + " = ?", 
       new String[] { String.valueOf(breadcrumb.getId()) }); 
    } 

    // Deleting single location 
     public void deleteBreadcrumb(Breadcrumb breadcrumb) { 
     SQLiteDatabase db = this.getWritableDatabase(); 
     int id = breadcrumb.getId(); 
     System.out.println("Comment deleted with id: " + id); 
     db.delete(TABLE_BREADCRUMBS, KEY_ID 
       + " = " + id, null); 
     db.close(); 
      } 

} 

這裏是我使用ListView活動:

package com.detimil.breadcrumbs1; 

import java.util.List; 

import android.app.Activity; 
import android.app.AlertDialog; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.net.Uri; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.view.Window; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemClickListener; 
import android.widget.AdapterView.OnItemLongClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.ListView; 


public class CollectedBreadcrumbsActivity extends Activity { 

private ListView listview; 
private DatabaseHandler db; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    setContentView(R.layout.activity_collected_breadcrumbs); 

    db = new DatabaseHandler(this); 
    List<Breadcrumb> breadcrumbs = db.getAllBreadcrumbLabels(); 

    listview = (ListView) findViewById(R.id.list); 
    ArrayAdapter<Breadcrumb> adapter = new ArrayAdapter<Breadcrumb>(this, 
      android.R.layout.simple_list_item_1, breadcrumbs); 
     listview.setAdapter(adapter); 

this.listview.setOnItemClickListener(new OnItemClickListener() { 

public void onItemClick(AdapterView<?> l, View v, int position, long id) { 

ArrayAdapter<Breadcrumb> adapter = (ArrayAdapter<Breadcrumb>) listview.getAdapter(); 
if (listview.getAdapter().getCount() > 0) { 
    Breadcrumb breadcrumb = db.getBreadcrumb(position); 

    final Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http://maps.google.com/maps" + "&daddr=" + breadcrumb.getBreadcrumbLatitude()/1e6 + "," + breadcrumb.getBreadcrumbLongitude()/1e6)); 
    intent.setClassName("com.google.android.apps.maps","com.google.android.maps.MapsActivity"); 
    startActivity(intent);}}}); 

this.listview.setOnItemLongClickListener(new OnItemLongClickListener() { 

public boolean onItemLongClick(AdapterView<?> l, View v, final int position, long id) { 
    Log.d("HelloListView", "You clicked Item: " + id + " at position:" + position); 
    Log.d("HelloListView", "Number of items in adapter:" + listview.getAdapter().getCount()); 

    AlertDialog.Builder alertbox = new AlertDialog.Builder(CollectedBreadcrumbsActivity.this); 

    // set the message to display 
    alertbox.setMessage("Delete Breadcrumb?"); 

    // set a positive/yes button and create a listener 
    alertbox.setPositiveButton("Delete", new DialogInterface.OnClickListener() { 

     // do something when the button is clicked 
     public void onClick(DialogInterface arg0, int arg1) {     
      @SuppressWarnings("unchecked") 
      ArrayAdapter<Breadcrumb> adapter = (ArrayAdapter<Breadcrumb>) listview.getAdapter(); 
      if (listview.getAdapter().getCount() > 0) { 
       Breadcrumb listedBreadcrumb = (Breadcrumb) listview.getAdapter().getItem(position); 
       Breadcrumb breadcrumb = db.getBreadcrumb(position); 
       db.deleteBreadcrumb(breadcrumb); 
       adapter.remove(listedBreadcrumb); 
       } 
      adapter.notifyDataSetChanged(); 



     } 
    }); 

    // set a negative/no button and create a listener 
    alertbox.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 

     // do something when the button is clicked 
     public void onClick(DialogInterface arg0, int arg1) { 
     } 
    }); 

    alertbox.show(); 

    return true; 
    } 
}); 

listview.setEmptyView(findViewById(R.id.empty)); 
} 
} 

SQLite數據庫通過點擊在MainActivity按鈕人口擺在首位。下面是一段代碼,顯示按下按鈕時會發生什麼:它啓動另一個活動,並且(在理論上?)創建一個SQLite行,其中包含一個String標籤,一個表示爲int的Latitude和一個表示爲INT。

public void dropBreadcrumb(View view) { 
    Intent intent = new Intent(this, DroppedCrumb.class); 
    DatabaseHandler db = new DatabaseHandler(this); 
    String label = "Breadcrumb"+db.getBreadcrumbsCount()+1; 
    BREADCRUMB_LATITUDE = (BREADCRUMB_LATITUDE * 1e6); 
    int lat = (int)BREADCRUMB_LATITUDE; 
    BREADCRUMB_LONGITUDE = (BREADCRUMB_LONGITUDE * 1e6); 
    int lng = (int)BREADCRUMB_LONGITUDE; 
    db.addBreadcrumb(new Breadcrumb(label, lat, lng)); 
    startActivity(intent); 
} 

這是實際的錯誤讀取,當我拿着一個listView項目,並確認我想刪除它時得到的。該應用程序崩潰...

05-19 14:05:25.512: D/HelloListView(2086): You clicked Item: 0 at position:0 
05-19 14:05:25.512: D/HelloListView(2086): Number of items in adapter:4 
05-19 14:05:25.602: I/Adreno200-EGLSUB(2086): <ConfigWindowMatch:2087>: Format RGBA_8888. 
05-19 14:05:26.653: W/dalvikvm(2086): threadid=1: thread exiting with uncaught exception ((group=0x40e4c438) 
05-19 14:05:26.663: E/AndroidRuntime(2086): FATAL EXCEPTION: main 
05-19 14:05:26.663: E/AndroidRuntime(2086): android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at android.database.AbstractCursor.checkPosition(AbstractCursor.java:418) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at com.detimil.breadcrumbs1.DatabaseHandler.getBreadcrumb(DatabaseHandler.java:84) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at com.detimil.breadcrumbs1.CollectedBreadcrumbsActivity$2$1.onClick(CollectedBreadcrumbsActivity.java:72) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at android.os.Handler.dispatchMessage(Handler.java:99) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at android.os.Looper.loop(Looper.java:137) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at android.app.ActivityThread.main(ActivityThread.java:4950) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at java.lang.reflect.Method.invokeNative(Native Method) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at java.lang.reflect.Method.invoke(Method.java:511) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771) 
05-19 14:05:26.663: E/AndroidRuntime(2086):  at dalvik.system.NativeStart.main(Native Method) 

如果您有任何想法,我會很感激。請讓我知道是否有任何其他信息/代碼對您有用。

非常感謝。

編輯/更新:

我剛纔編輯按照以下用戶Nikhil的初步建議,我getBreadcrumb方法,但主要的問題依然存在。這裏是我得到的錯誤信息...

05-20 17:48:48.966: D/HelloListView(15738): You clicked Item: 2 at position:2 
05-20 17:48:48.966: D/HelloListView(15738): Number of items in adapter:4 
05-20 17:48:49.056: I/Adreno200-EGLSUB(15738): <ConfigWindowMatch:2087>: Format RGBA_8888. 
05-20 17:48:50.297: W/dalvikvm(15738): threadid=1: thread exiting with uncaught exception (group=0x414db438) 
05-20 17:48:50.297: E/AndroidRuntime(15738): FATAL EXCEPTION: main 
05-20 17:48:50.297: E/AndroidRuntime(15738): android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0 
05-20 17:48:50.297: E/AndroidRuntime(15738): at android.database.AbstractCursor.checkPosition(AbstractCursor.java:418) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at com.detimil.breadcrumbs1.DatabaseHandler.getBreadcrumb(DatabaseHandler.java:86) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at com.detimil.breadcrumbs1.CollectedBreadcrumbsActivity$2$1.onClick(CollectedBreadcrumbsActivity.java:72) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at android.os.Handler.dispatchMessage(Handler.java:99) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at android.os.Looper.loop(Looper.java:137) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at android.app.ActivityThread.main(ActivityThread.java:4950) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at java.lang.reflect.Method.invokeNative(Native Method) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at java.lang.reflect.Method.invoke(Method.java:511) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771) 
05-20 17:48:50.297: E/AndroidRuntime(15738): at dalvik.system.NativeStart.main(Native Method) 

回答

0

問題出在你的getBreadCrumb方法。 當您長按第一行時,位置變量爲0(零),所以當您將此值傳遞給getBreadCrumb方法時,sql查詢失敗(這意味着它不返回數據),因爲id(主鍵)總是以1.由於以下聲明,此問題即將到來: public Breadcrumb getBreadcrumb(int id){ SQLiteDatabase db = this.getReadableDatabase();

Cursor cursor = db.query(TABLE_BREADCRUMBS, new String[] { KEY_ID, KEY_LABEL, 
     KEY_LATITUDE, KEY_LONGITUDE }, KEY_ID + "=?", 
     new String[] { String.valueOf(id) }, null, null, null, null); 
if (cursor.getCount() > 0) 
    cursor.moveToFirst(); 

    Breadcrumb breadcrumb = new Breadcrumb(Integer.parseInt(cursor.getString(0)), cursor.getString(1), 

} 的,如果你爲何光標不移動指向第一行,所以你在logcat中得到的錯誤條件不滿足,多數民衆贊成。 修改後的代碼是:

public Breadcrumb getBreadcrumb(int id) { 
SQLiteDatabase db = this.getReadableDatabase(); 

Cursor cursor = db.query(TABLE_BREADCRUMBS, new String[] { KEY_ID, KEY_LABEL, 
     KEY_LATITUDE, KEY_LONGITUDE }, KEY_ID + "=?", 
     new String[] { String.valueOf(id) }, null, null, null, null); 
if (cursor.getCount() > 0) 
    { 
     cursor.moveToFirst(); 
     Breadcrumb breadcrumb = new Breadcrumb(Integer.parseInt(cursor.getString(0), 
     cursor.getString(1),cursor.getInt(2),cursor.getInt(3)); 
// return breadcrumb 
    } 
     cursor.close(); 
     return breadcrumb; 

}

通知圍繞如果條件paranthesis。

+0

不幸的是這並沒有解決問題。我將代碼更改爲'if(cursor.getCount()> 0) {0} {0} cursor.moveToFirst(); } 麪包屑麪包屑=新麪包屑(的Integer.parseInt(cursor.getString(0), cursor.getString(1),cursor.getInt(2),cursor.getInt(3)); // 返回麪包屑 光標.close(); 回報麪包屑;' 按你的建議 (不能完成新的麪包屑的呼叫括號,否則將不承認麪包屑變量初始化後)。 我仍然得到同樣的問題 – peopletrees

+0

Ofcourse在if條件之外聲明BreadCrumb參考爲: BreadCrumb breadCrumb = null; 然後if條件。 –

+0

是的,我也試過這個。看來問題不僅僅是getBreadcrumb方法。 (雖然這種方法也需要一些修復,所以謝謝。) 如果你看看我的原始問題,我添加了一個更新/編輯,顯示了當我嘗試長按/刪除listView的另一部分時得到的錯誤信息,即使在修復getBreadcrumb方法。 – peopletrees

1

你有2列具有相同名稱的經度

private static final String KEY_ID = "id"; 
private static final String KEY_LABEL = "longitude"; 
private static final String KEY_LATITUDE = "latitude"; 
private static final String KEY_LONGITUDE = "longitude"; 
+0

哦,我的上帝,我不敢相信我沒有看到! (必須一直盯着這種方式太長時間。)我將無法重新測試幾天的代碼,但我會再次發佈以通知您是否所有事情都可以解決。 – peopletrees

+0

它看起來仍然是核心問題,但顯然你發現了另一個大問題,所以謝謝你! (因爲我沒有足夠的聲望,所以我還無法支持你。) – peopletrees

相關問題