2013-05-19 62 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

相关问题