我成功地在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)
不幸的是這並沒有解決問題。我將代碼更改爲'if(cursor.getCount()> 0) {0} {0} cursor.moveToFirst(); } 麪包屑麪包屑=新麪包屑(的Integer.parseInt(cursor.getString(0), cursor.getString(1),cursor.getInt(2),cursor.getInt(3)); // 返回麪包屑 光標.close(); 回報麪包屑;' 按你的建議 (不能完成新的麪包屑的呼叫括號,否則將不承認麪包屑變量初始化後)。 我仍然得到同樣的問題 – peopletrees
Ofcourse在if條件之外聲明BreadCrumb參考爲: BreadCrumb breadCrumb = null; 然後if條件。 –
是的,我也試過這個。看來問題不僅僅是getBreadcrumb方法。 (雖然這種方法也需要一些修復,所以謝謝。) 如果你看看我的原始問題,我添加了一個更新/編輯,顯示了當我嘗試長按/刪除listView的另一部分時得到的錯誤信息,即使在修復getBreadcrumb方法。 – peopletrees