解决方案位于我的帖子底部。
首先,让我为这篇文章的篇幅道歉,但我已经把代码倾注了好几个小时而且我迷失了。我对db方面也非常困惑,因此我的代码重复了一些我能找到的最简单的教程,即使我知道方面已被弃用或者还有其他方法可以减少代码长度。我不确定需要什么,因此下面有大量的代码。
目标:我有一个用户可以填写并保存到数据库表的表单。然后,我将另一个类中的数据显示到ListView(此类在listview上方还有其他功能)。通过单击其中一个列表视图项,将打开另一个与原始表单相同的表单,其中所有信息都已从数据库行填充。此表单有一个保存和删除按钮,可以让您更改某些输入字段(EditText' s和Spinner' s)并保存以更新行,或选择删除。更新或删除后,活动结束并将您带回listview类。
我不打算添加原始表单数据,因为我知道正确保存。我也知道我的数据正在正确地传输到辅助表单(我可以修改/删除),但是当我尝试更新或删除时,我在logcat中得到以下内容:
07-29 04:18:25.771: E/AndroidRuntime(2116): FATAL EXCEPTION: main
07-29 04:18:25.771: E/AndroidRuntime(2116): java.lang.IllegalStateException: Could not execute method of the activity
07-29 04:18:25.771: E/AndroidRuntime(2116): at android.view.View$1.onClick(View.java:3591)
07-29 04:18:25.771: E/AndroidRuntime(2116): at android.view.View.performClick(View.java:4084)
07-29 04:18:25.771: E/AndroidRuntime(2116): at android.view.View$PerformClick.run(View.java:16966)
07-29 04:18:25.771: E/AndroidRuntime(2116): at android.os.Handler.handleCallback(Handler.java:615)
07-29 04:18:25.771: E/AndroidRuntime(2116): at android.os.Handler.dispatchMessage(Handler.java:92)
07-29 04:18:25.771: E/AndroidRuntime(2116): at android.os.Looper.loop(Looper.java:137)
07-29 04:18:25.771: E/AndroidRuntime(2116): at android.app.ActivityThread.main(ActivityThread.java:4745)
07-29 04:18:25.771: E/AndroidRuntime(2116): at java.lang.reflect.Method.invokeNative(Native Method)
07-29 04:18:25.771: E/AndroidRuntime(2116): at java.lang.reflect.Method.invoke(Method.java:511)
07-29 04:18:25.771: E/AndroidRuntime(2116): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
07-29 04:18:25.771: E/AndroidRuntime(2116): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
07-29 04:18:25.771: E/AndroidRuntime(2116): at dalvik.system.NativeStart.main(Native Method)
07-29 04:18:25.771: E/AndroidRuntime(2116): Caused by: java.lang.reflect.InvocationTargetException
07-29 04:18:25.771: E/AndroidRuntime(2116): at java.lang.reflect.Method.invokeNative(Native Method)
07-29 04:18:25.771: E/AndroidRuntime(2116): at java.lang.reflect.Method.invoke(Method.java:511)
07-29 04:18:25.771: E/AndroidRuntime(2116): at android.view.View$1.onClick(View.java:3586)
07-29 04:18:25.771: E/AndroidRuntime(2116): ... 11 more
07-29 04:18:25.771: E/AndroidRuntime(2116): Caused by: java.lang.NullPointerException
07-29 04:18:25.771: E/AndroidRuntime(2116): at com.rone.glucometer.AddDBHelper.updateDetails(AddDBHelper.java:119)
07-29 04:18:25.771: E/AndroidRuntime(2116): at com.rone.glucometer.UpdateDBDetails.clickUpdateDelete(UpdateDBDetails.java:420)
07-29 04:18:25.771: E/AndroidRuntime(2116): ... 14 more
我的AddDBHelper类如下所示:
public class AddDBHelper {
public static final String KEY_ROWID ="_id";
public static final String KEY_CATEG = "Category";
public static final String KEY_CATEGPOS = "Category_Pos";
public static final String KEY_BGL = "BGL";
public static final String KEY_CARBS = "Carbs";
public static final String DB_NAME = "Glucometer.db";
public static final String DB_TABLE = "Journal";
private static final int DB_VERSION = 1;
private DbHelper myDBHelper;
private final Context mContext;
private SQLiteDatabase glucoDB;
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DB_TABLE + " (" +
KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_CATEG + " TEXT NOT NULL, " +
KEY_CATEGPOS + " TEXT NOT NULL, " +
KEY_BGL + " TEXT NOT NULL, " +
KEY_CARBS + " TEXT NOT NULL);"
);}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);
onCreate(db);
}
}
public AddDBHelper(Context c) {
mContext = c;
}
public AddDBHelper open() throws SQLException {
myDBHelper = new DbHelper(mContext);
glucoDB = myDBHelper.getWritableDatabase();
return this;
}
public void close() {
myDBHelper.close();
}
public long createEntry(String Category, String CategoryPos, String BGL, String Carbs) {
ContentValues cv = new ContentValues();
cv.put(KEY_CATEG, Category);
cv.put(KEY_CATEGPOS, CategoryPos);
cv.put(KEY_BGL, BGL);
cv.put(KEY_CARBS, Carbs);
return glucoDB.insert(DB_TABLE, null, cv); }
public Cursor getEntries() {
return glucoDB.query(DB_TABLE, new String[] {
KEY_ROWID,
KEY_CATEG,
KEY_CATEGPOS,
KEY_BGL,
KEY_CARBS}, null, null, null, null, null); }
public void updateDetails(DBDetails dbdetails) {
SQLiteDatabase db = myDBHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(AddDBHelper.KEY_ROWID, UpdateDBDetails.newRow);
cv.put(AddDBHelper.KEY_CATEG, UpdateDBDetails.newCateg);
cv.put(AddDBHelper.KEY_CATEGPOS, UpdateDBDetails.newCategPos);
cv.put(AddDBHelper.KEY_BGL, UpdateDBDetails.newBGL);
cv.put(AddDBHelper.KEY_CARBS, UpdateDBDetails.newCarbs);
db.update(DB_TABLE, cv, KEY_ROWID + "=?", new String[] {String.valueOf(UpdateDBDetails.newRow)});
}
public void deleteDetails(DBDetails dbdetails) {
SQLiteDatabase db = myDBHelper.getWritableDatabase();
db.delete(DB_TABLE, KEY_ROWID +"=?",
new String[] {String.valueOf(UpdateDBDetails.newRow)});
db.close();
}}
我的ListView活动如下:
public class FuncLogbook extends DashMenuActivity implements OnItemClickListener {
private ListView list_LogbookResults;
private ListAdapter list_LogbookAdap;
private ArrayList<DBDetails> LogbookArrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView (R.layout.dash_logbook);
list_LogbookResults = (ListView) findViewById(R.id.list_logbookResults);
list_LogbookResults.setOnItemClickListener(this);
LogbookArrayList = new ArrayList<DBDetails>();
list_LogbookAdap = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
list_LogbookResults.setAdapter(list_LogbookAdap); }
@SuppressWarnings("deprecation")
public List<String> populateList() {
List<String> BGLResultsList = new ArrayList<String>();
AddDBHelper logbook = new AddDBHelper(this);
logbook.open();
Cursor cur = logbook.getEntries();
startManagingCursor(cur);
while (cur.moveToNext()) {
String RowID = cur.getString(0);
String Category = cur.getString(1);
String CategoryPos = cur.getString(2);
String BGL = cur.getString(3);
String Carbs = cur.getString(4);
DBDetails detailsClass = new DBDetails();
detailsClass.setuCateg(Category);
detailsClass.setuCategPos(CategoryPos);
detailsClass.setuBGL(BGL);
detailsClass.setuCarbs(Carbs);
LogbookArrayList.add(detailsClass);
BGLResultsList.add("BGL: " + BGL + "\nRow ID: " + RowID);
}
return BGLResultsList;
}
@Override
protected void onResume() {
super.onResume();
LogbookArrayList = new ArrayList<DBDetails>();
list_LogbookAdap = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
list_LogbookResults.setAdapter(list_LogbookAdap);
}
@Override
protected void onStart() {
super.onStart();
LogbookArrayList = new ArrayList<DBDetails>();
list_LogbookAdap = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
list_LogbookResults.setAdapter(list_LogbookAdap);
}
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Intent UpdateDBDetails = new Intent(this, UpdateDBDetails.class);
DBDetails clickedObject = LogbookArrayList.get(arg2);
Bundle dataBundle = new Bundle();
dataBundle.putString("clickeduCateg", clickedObject.getuCateg());
dataBundle.putString("clickeduCategPos", clickedObject.getuCategPos());
dataBundle.putString("clickeduBGL", clickedObject.getuBGL());
dataBundle.putString("clickeduCarbs", clickedObject.getuCarbs());
UpdateDBDetails.putExtras(dataBundle);
startActivity(UpdateDBDetails);
}}
数据被收集到我的DBDetails类:
public class DBDetails {
private String uCateg;
private String uCategPos;
private String uBGL;
private String uCarbs;
public String getuCateg() {
return uCateg;
}
public void setuCateg(String uCateg) {
this.uCateg = uCateg;
}
public String getuCategPos() {
return uCategPos;
}
public void setuCategPos(String uCategPos) {
this.uCategPos = uCategPos;
}
public String getuBGL() {
return uBGL;
}
public void setuBGL(String uBGL) {
this.uBGL = uBGL;
}
public String getuCarbs() {
return uCarbs;
}
public void setuCarbs(String uCarbs) {
this.uCarbs = uCarbs;
}
最后,我的表单显示数据:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.updatedbdetails);
update_category_spinner = (Spinner) findViewById(R.id.update_category_spinner);
ArrayAdapter<CharSequence> category_adapter = ArrayAdapter.createFromResource(
this, R.array.category_array, android.R.layout.simple_spinner_item);
category_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
update_category_spinner.setAdapter(category_adapter);
update_category_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
newCat = update_category_spinner.getSelectedItem().toString();
newCatPos = (update_category_spinner.getSelectedItemPosition() + " Position");
}
public void onNothingSelected(AdapterView<?> arg0) {
}
});
Bundle takeBundledData = getIntent().getExtras();
bundleduRowId = takeBundledData.getString("clickeduRowId");
bundleduCateg = takeBundledData.getString("clickeduCateg");
bundleduCategPos = takeBundledData.getString("clickeduCategPos");
bundleduBGL = takeBundledData.getString("clickeduBGL");
bundleduCarbs = takeBundledData.getString("clickeduCarbs");
CategoryPosition = String.valueOf(bundleduCategPos.charAt(0));
update_category_spinner.setSelection(Integer.parseInt(CategoryPosition), true);
update_edit_bgl.setText(bundleduBGL);
update_edit_carbs.setText(bundleduCarbs); }
public static double round(double unrounded, int precision, int roundingMode) {
BigDecimal bd = new BigDecimal(unrounded);
BigDecimal rounded = bd.setScale(precision, roundingMode);
return rounded.doubleValue();
}
public void checkNewBGL() {
String checkBGL = update_edit_bgl.getText().toString();
if (checkBGL.matches("")) {
NewBGLValid = "";
} else {
float BGLUnRound = Float.parseFloat(update_edit_bgl.getText().toString());
double BGLRound= round(BGLUnRound, 1, BigDecimal.ROUND_HALF_UP);
NewBGLValid = String.valueOf(BGLRound);
}
return;
}
public void checkNewCarbs() {
String checkCarbs = update_edit_carbs.getText().toString();
if (checkCarbs.matches("")) {
NewCarbsValid = "0";
} else {
NewCarbsValid = update_edit_carbs.getText().toString();
}
return;
}
public void clickUpdateDelete(View v) {
checkNewBGL();
checkNewCarbs();
newCateg = newCat;
newCategPos = newCatPos;
newBGL = NewBGLValid;
newCarbs = NewCarbsValid;
DBDetails dbdetails = new DBDetails();
dbdetails.setuCateg(newCateg);
dbdetails.setuCategPos(newCategPos);
dbdetails.setuBGL(newBGL);
dbdetails.setuCarbs(newCarbs);
if (v.getId() == R.id.update_button_delete) {
AddDBHelper deleteEntry = new AddDBHelper(this);
deleteEntry.deleteDetails(dbdetails);
} else if (v.getId() == R.id.update_button_save) {
AddDBHelper updateEntry = new AddDBHelper(this);
updateEntry.updateDetails(dbdetails);
}
}}
我更新到了
public void updateDetails(DBDetails dbdetails) {
SQLiteDatabase db = myDBHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(AddDBHelper.KEY_CATEG, UpdateDBDetails.newCateg);
cv.put(AddDBHelper.KEY_CATEGPOS, UpdateDBDetails.newCategPos);
cv.put(AddDBHelper.KEY_BGL, UpdateDBDetails.newBGL);
cv.put(AddDBHelper.KEY_CARBS, UpdateDBDetails.newCarbs);
db.update(DB_TABLE, cv, KEY_ROWID + "=?", new String[] {UpdateDBDetails.getRowId});}
并添加到UpdateDBDetails:
getRowId = dbdetails.getuRow();
虽然同样的问题正在发生。此外,在这个阶段,我没有关闭我的光标,因为如果我点击了&#39;返回&#39;按钮而不是保存或删除,它由于尝试查询已经关闭的游标而崩溃;我想我以后会解决这个问题。你是对的,我确实忘了定义UpdateDBDetails,但是我已经将DBDetails上下文传递给了方法,所以我现在改为
public void updateDetails(DBDetails dbdetails) {
SQLiteDatabase db = myDBHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(AddDBHelper.KEY_CATEG, dbdetails.getuCateg());
cv.put(AddDBHelper.KEY_CATEGPOS, dbdetails.getuCategPos());
cv.put(AddDBHelper.KEY_BGL, dbdetails.getuBGL());
cv.put(AddDBHelper.KEY_CARBS, dbdetails.getuCarbs());
db.update(DB_TABLE, cv, KEY_ROWID + "=?", new String[] {dbdetails.getuRow()}); }
但同样的问题。
解决方案:
我的DBDetails.java添加了以下行:
public String getuRow() {
return uRow;
}
public void setuRow(String uRow) {
this.uRow = uRow;
}
我的Listview(FuncLogbook.Java)添加了以下行\ changed:
public List<String> populateList() {
List<String> BGLResultsList = new ArrayList<String>();
AddDBHelper logbook = new AddDBHelper(this);
logbook.open();
Cursor cur = logbook.getEntries();
startManagingCursor(cur);
while (cur.moveToNext()) {
String RowID = cur.getString(0);
String Category = cur.getString(3);
String CategoryPos = cur.getString(4);
String BGL = cur.getString(5);
String Carbs = cur.getString(6);
DBDetails detailsClass = new DBDetails();
detailsClass.setuRow(RowID);
detailsClass.setuCateg(Category);
detailsClass.setuCategPos(CategoryPos);
detailsClass.setuBGL(BGL);
detailsClass.setuCarbs(Carbs);
LogbookArrayList.add(detailsClass);
}
return BGLResultsList; }
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Intent UpdateDBDetails = new Intent(this, UpdateDBDetails.class);
DBDetails clickedObject = LogbookArrayList.get(arg2);
Bundle dataBundle = new Bundle();
dataBundle.putString("clickeduRowId", clickedObject.getuRow());
dataBundle.putString("clickeduCateg", clickedObject.getuCateg());
dataBundle.putString("clickeduCategPos", clickedObject.getuCategPos());
dataBundle.putString("clickeduBGL", clickedObject.getuBGL());
dataBundle.putString("clickeduCarbs", clickedObject.getuCarbs());
UpdateDBDetails.putExtras(dataBundle);
startActivity(UpdateDBDetails);
}
MY DB帮助程序类(AddDBHelper.java)显示以下内容:
public void updateDetails(DBDetails dbdetails) {
ContentValues cv = new ContentValues();
cv.put(AddDBHelper.KEY_CATEG, dbdetails.getuCateg());
cv.put(AddDBHelper.KEY_CATEGPOS, dbdetails.getuCategPos());
cv.put(AddDBHelper.KEY_BGL, dbdetails.getuBGL());
cv.put(AddDBHelper.KEY_CARBS, dbdetails.getuCarbs());
int count = glucoDB.update(DB_TABLE, cv, KEY_ROWID + "=?", new String[] {String.valueOf(dbdetails.getuRow())});
Log.v("AddDbHelper", "Row " + dbdetails.getuRow() + " updated? " + count);
}
public void deleteDetails(DBDetails dbdetails) {
int count = glucoDB.delete(DB_TABLE, KEY_ROWID +"=?",
new String[] {String.valueOf(dbdetails.getuRow())});
Log.v("AddDbHelper", "Row " + dbdetails.getuRow() + " deleted? " + count);
}
最后,我的UpdateDBDetails.java(包含要修改或删除的信息的表单)显示:
onCreate...{
Bundle takeBundledData = getIntent().getExtras();
bundleduRowId = takeBundledData.getString("clickeduRowId");
bundleduCateg = takeBundledData.getString("clickeduCateg");
bundleduCategPos = takeBundledData.getString("clickeduCategPos");
bundleduBGL = takeBundledData.getString("clickeduBGL");
bundleduCarbs = takeBundledData.getString("clickeduCarbs");
}
public void clickUpdateDelete(View v) {
checkNewBGL();
checkNewCarbs();
newCateg = newCat;
newCategPos = newCatPos;
newBGL = NewBGLValid;
newCarbs = NewCarbsValid;
AddDBHelper modifyEntry = new AddDBHelper(this);
modifyEntry.open();
DBDetails dbdetails = new DBDetails();
dbdetails.setuRow(bundleduRowId);
if (v.getId() == R.id.update_button_delete) {
modifyEntry.deleteDetails(dbdetails);
} else if (v.getId() == R.id.update_button_save) {
dbdetails.setuCateg(newCateg);
dbdetails.setuCategPos(newCategPos);
dbdetails.setuBGL(newBGL);
dbdetails.setuCarbs(newCarbs);
modifyEntry.updateDetails(dbdetails);
}
modifyEntry.close();
finish();
}
答案 0 :(得分:1)
我看不到你在哪里定义UpdateDBDetails
。但我对SQLiteDatabase.update()提出了一些建议。
首先将行ID添加到UpdateDBDetails对象并提供get方法。
然后使用这样的更新方法:
public void updateDetails() {
ContentValues cv = new ContentValues();
cv.put(AddDBHelper.KEY_CATEG, UpdateDBDetails.newCateg);
cv.put(AddDBHelper.KEY_CATEGPOS, UpdateDBDetails.newCategPos);
cv.put(AddDBHelper.KEY_BGL, UpdateDBDetails.newBGL);
cv.put(AddDBHelper.KEY_CARBS, UpdateDBDetails.newCarbs);
db.update(DB_TABLE, cv, KEY_ROWID + "=?", new String[] {UpdateDBDetails.getuRow()});
}
更新行时,其ID不应更改,否则您将创建新行或更新其他行...因此,ContentValues对象不应尝试添加有关AddDBHelper.KEY_ROWID
的任何内容,而应添加SQLiteDatabase .update()的WHERE子句应该具有当前行的ID。希望这是有道理的。
只要您使用new AddDBHelper
或myDBHelper.getWritableDatabase()
(或直接使用光标),就应该在完成后关闭这些对象。否则,它们会一直存在,不必要地消耗内存。
从LogCat添加
我看到你的LogCat,我猜测UpdateDBDetails
有问题但我刚刚注意到你调用updateDetails()的地方并推荐:
将行ID添加到DBDetails,以便您可以这样做:
AddDBHelper helper = new AddDBHelper(this);
helper.open();
DBDetails dbdetails = new DBDetails();
dbdetails.setuRow(bundleduRowId);
if (v.getId() == R.id.update_button_delete) {
helper.deleteDetails(dbdetails);
} else if (v.getId() == R.id.update_button_save) {
dbdetails.setuCateg(newCateg);
dbdetails.setuCategPos(newCategPos);
dbdetails.setuBGL(newBGL);
dbdetails.setuCarbs(newCarbs);
helper.updateDetails(dbdetails);
}
helper.close();
最后一次AddDbHepler:
public void updateDetails(DBDetails dbdetails) {
ContentValues cv = new ContentValues();
cv.put(AddDBHelper.KEY_CATEG, dbdetails.newCateg);
cv.put(AddDBHelper.KEY_CATEGPOS, dbdetails.newCategPos);
cv.put(AddDBHelper.KEY_BGL, dbdetails.newBGL);
cv.put(AddDBHelper.KEY_CARBS, dbdetails.newCarbs);
glucoDB.update(DB_TABLE, cv, KEY_ROWID + "=?", new String[] {String.valueOf(dbdetails.getuRow())});
}
<强> logcat的强>
更新和删除都返回一个影响了多少行的整数,你可以这样看到它们:
int count = glucoDB.update(DB_TABLE, cv, KEY_ROWID + "=?", new String[] {String.valueOf(dbdetails.getuRow())});
Log.v("AddDbHelper", "Row " + dbdetails.getuRow() + " updated? " + count);
如果您看到“...已更新?1”,那么它可以正常工作,否则存储在DBDetails中的ID将会关闭。