我曾经试图通过一个片段在Android中通过一个SQLite更新行,但是它不更新表,我也没有得到任何错误。这是我的代码..也许我遗漏了一些东西。谢谢
public class MySQLiteHelper extends SQLiteOpenHelper {
public static final String MYDATABASE = "myDataBase";
public static final String MYTABLE = "myTable";
public static final String USERNAME = "myUser";
public static final String PASSWORD = "myPass";
public static final String EMAIL = "myEmail";
public static final int VERSION = 1;
public static final String KEY_ID = "_id";
public MySQLiteHelper(Context context) {
super(context, MYDATABASE, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_TABLE = "CREATE TABLE " + MYTABLE + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + USERNAME + " TEXT," + PASSWORD + " TEXT,"
+ EMAIL + " TEXT" + ")";
db.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//any upgrade can update the version and if newV > oldV then upgrade will be exected
db.execSQL("DROP TABLE IF EXISTS " + MYTABLE);
onCreate(db);
}
public Integer deleteData(String id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(MYTABLE, "_id = ?", new String[] {id});
}
public boolean updateData(String id, String user, String pass, String email) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(USERNAME, user);
cv.put(PASSWORD, pass);
cv.put(EMAIL, email);
db.update(MYTABLE, cv, "_id = ?", new String[] {id});
return true;
}
}
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
EditText etUser, etPass, etEmail;
Button btSave, btShow;
MySQLiteHelper mySQLiteHelper;
SQLiteDatabase sqLiteDatabase;
ListView lvRecords;
ArrayList<String> userDataList;
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate: started");
etUser = findViewById(R.id.etUser);
etPass = findViewById(R.id.etPass);
etEmail = findViewById(R.id.etEmail);
btSave = findViewById(R.id.btSave);
btShow = findViewById(R.id.btShow);
lvRecords = findViewById(R.id.lvRecords);
userDataList = new ArrayList<String>();
mySQLiteHelper = new MySQLiteHelper(this);
sqLiteDatabase = mySQLiteHelper.getWritableDatabase(); //write and read
adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, userDataList);
lvRecords.setAdapter(adapter);
showList();
lvRecords.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
String selectedData = userDataList.get(position);
String rowId = selectedData.substring(0,1);
Log.d(TAG, "onItemLongClick: *******id " + rowId);
Integer deleteRow = mySQLiteHelper.deleteData(rowId);
adapter.remove(adapter.getItem(position));
adapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this, "Position: " + rowId, Toast.LENGTH_SHORT).show();
return false;
}
});
lvRecords.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
UpdateFragment updateFragment = new UpdateFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container, updateFragment).addToBackStack(null).commit();
String selectedData = userDataList.get(position);
String[] userData = selectedData.split("\\s+");
String userId = userData[0];
String userName = userData[1];
String userPass = userData[2];
String userEmail = userData[3];
Bundle b = new Bundle();
b.putInt("position", position);
b.putString("id", userId);
b.putString("user", userName);
b.putString("pass", userPass);
b.putString("email", userEmail);
updateFragment.setArguments(b);
Toast.makeText(MainActivity.this, "id", Toast.LENGTH_SHORT).show();
}
});
btShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showList();
}
});
btSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//content values to put the data in the database
//same order as table creation fields order
ContentValues contentValues = new ContentValues();
String user = etUser.getText().toString();
String pass = etPass.getText().toString();
String email = etEmail.getText().toString();
contentValues.put(mySQLiteHelper.USERNAME, user);
contentValues.put(mySQLiteHelper.PASSWORD, pass);
contentValues.put(mySQLiteHelper.EMAIL, email);
sqLiteDatabase.insert(mySQLiteHelper.MYTABLE, null, contentValues);
hideKeyboard();
showList();
etUser.setText("");
etPass.setText("");
etEmail.setText("");
}
});
}
public void hideKeyboard() {
InputMethodManager imm = (InputMethodManager) getSystemService(
Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}
private void showList() {
Cursor cursor = sqLiteDatabase.rawQuery("SELECT * FROM " + mySQLiteHelper.MYTABLE, null);
cursor.moveToFirst();
userDataList.clear();
//to read the first iteration use a do while
do {
if(cursor != null) {
int id = cursor.getInt(cursor.getColumnIndex(mySQLiteHelper.KEY_ID));
String user = cursor.getString(cursor.getColumnIndex(mySQLiteHelper.USERNAME));
String pass = cursor.getString(cursor.getColumnIndex(mySQLiteHelper.PASSWORD));
String email = cursor.getString(cursor.getColumnIndex(mySQLiteHelper.EMAIL));
userDataList.add(id + " " + user + " " + pass + " " + email);
adapter.notifyDataSetChanged();
Log.d(TAG, "onClick: ******rows: " + mySQLiteHelper.KEY_ID + ":" + id + " user: " + user + " pass: " + pass + " email: " + email);
Toast.makeText(MainActivity.this,
"id: " + id + " user: " + user + " pass: " + pass + " email: " + email, Toast.LENGTH_SHORT)
.show();
}
} while(cursor.moveToNext());
}
}
public class UpdateFragment extends Fragment {
private static final String TAG = "UpdateFragment";
Button btUpdate, btClose;
EditText etUser, etPass, etEmail;
Fragment me = this;
MySQLiteHelper mySQLiteHelper;
SQLiteDatabase sqLiteDatabase;
String userId, username, password, email;
int position, e;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_update, container, false);
etUser = v.findViewById(R.id.etUserFrag);
etPass = v.findViewById(R.id.etPassFrag);
etEmail = v.findViewById(R.id.etEmailFrag);
btUpdate = v.findViewById(R.id.btUpdateFrag);
btClose = v.findViewById(R.id.btCloseFrag);
Bundle b = getArguments();
position = b.getInt("position");
position = position -1;
userId = b.getString("id");
e = Integer.parseInt(userId);
//e = e - 1;
//userId = userId -1 ;
Log.d(TAG, "onCreateView: **********userID: " + userId);
username = b.getString("user");
password = b.getString("pass");
email = b.getString("email");
etUser.setText(username);
etPass.setText(password);
etEmail.setText(email);
mySQLiteHelper = new MySQLiteHelper(getContext());
sqLiteDatabase = mySQLiteHelper.getWritableDatabase(); //write and read
btClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
closeFragment();
}
});
btUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {//
boolean isUpdate = mySQLiteHelper.updateData(userId, username, password, email);
if(isUpdate==true)
Toast.makeText(getContext(),"Data Update",Toast.LENGTH_LONG).show();
else
Toast.makeText(getContext(),"Data not Updated",Toast.LENGTH_LONG).show();
}
});
return v;
}
private void closeFragment() {
getActivity().getSupportFragmentManager().beginTransaction().remove(me).commit();
}
}
答案 0 :(得分:0)
从不认为空光标为空。
返回Cursor的 SQLiteDatabase方法将返回有效的Cursor,而不是null。光标为空时,其计数为0(即cursor.getCount() == 0
)。
因此,如果您只是这样做(按照您的 showlist 方法)
cursor.moveToFirst();
if (cursor == null) {
do you stuff here
}
如果游标为空,则会出现索引错误。相反,您应该检查cursor.moveToFirst()
的结果,如果现在提取了行,则结果为false。但是,使用 while 循环更容易(请参见下面的代码)。
完成操作后,您还应该关闭游标。
更正/更好的 showList 方法:-
private void showList() {
Cursor cursor = sqLiteDatabase.rawQuery("SELECT * FROM " + mySQLiteHelper.MYTABLE, null);
userDataList.clear();
//<<<<<<<<<< simpler while loop >>>>>>>>>>
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex(mySQLiteHelper.KEY_ID));
String user = cursor.getString(cursor.getColumnIndex(mySQLiteHelper.USERNAME));
String pass = cursor.getString(cursor.getColumnIndex(mySQLiteHelper.PASSWORD));
String email = cursor.getString(cursor.getColumnIndex(mySQLiteHelper.EMAIL));
userDataList.add(id + " " + user + " " + pass + " " + email);
adapter.notifyDataSetChanged();
Log.d(TAG, "onClick: ******rows: " + mySQLiteHelper.KEY_ID + ":" + id + " user: " + user + " pass: " + pass + " email: " + email);
Toast.makeText(MainActivity.this,
"id: " + id + " user: " + user + " pass: " + pass + " email: " + email, Toast.LENGTH_SHORT)
.show();
}
cursor.close();
}
如果单击“保存”按钮,但尚未在字段中输入任何数据,则将添加新行。如果在ListView中单击该项目,则会导致由于数组中的索引错误而导致崩溃,因为 split 不会提取4个项目(只有 id 保证)。
以下内容将纠正此问题(请看commenets):-
btSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//<<<<<<<<<< Start of Extra Code >>>>>>>>>>
if (
etUser.getText().toString().length() < 1 ||
etEmail.getText().toString().length() < 1 ||
etPass.getText().toString().length() < 1
) {
Toast.makeText(MainActivity.this,"WHOA ENTER DATA IN ALL FIELDS!!!!!!!!!!",Toast.LENGTH_SHORT).show();
return;
}
//<<<<<<<<<< End of Extra Code >>>>>>>>>>
//content values to put the data in the database
//same order as table creation fields order
ContentValues contentValues = new ContentValues();
String user = etUser.getText().toString();
String pass = etPass.getText().toString();
String email = etEmail.getText().toString();
contentValues.put(mySQLiteHelper.USERNAME, user);
contentValues.put(mySQLiteHelper.PASSWORD, pass);
contentValues.put(mySQLiteHelper.EMAIL, email);
sqLiteDatabase.insert(mySQLiteHelper.MYTABLE, null, contentValues);
hideKeyboard();
showList();
etUser.setText("");
etPass.setText("");
etEmail.setText("");
}
});
SQliteDatabase update 方法返回受影响的行数,因此,如果没有行被更新(将行更改为与更新相同的值),则将返回0。您的 updateData 方法不检查结果,因此始终返回true。
也许将其更改为:-
public boolean updateData(String id, String user, String pass, String email) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(USERNAME, user);
cv.put(PASSWORD, pass);
cv.put(EMAIL, email);
if (db.update(MYTABLE, cv, "_id = ?", new String[] {id}) > 0) {
return true;
}
return false;
}
为了提供更准确的反馈(并突出显示您的主要问题),可以添加以下方法来根据ID获取数据:-
public Cursor getDataById(String id) {
SQLiteDatabase db = this.getWritableDatabase();
String whereclause = KEY_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
return db.query(MYTABLE,null,whereclause,whereargs,null,null,null);
}
导致没有更新的主要问题是因为您将旧值传递给了更新,而不是按照EditTexts传递值。
以下代码更改了更新按钮的 onClickListener 以解决此问题,并且还通过发布的Toast提供了更好的反馈:-
btUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {//
//boolean isUpdate = mySQLiteHelper.updateData(userId, username, password, email);
boolean isUpdate = mySQLiteHelper.updateData(
userId,
etUser.getText().toString(),
etPass.getText().toString(),
etEmail.getText().toString()
);
Cursor csr = mySQLiteHelper.getDataById(userId);
String newUser = "not found";
String newEmail = "not found";
String newPass = "not found";
if (csr.moveToFirst()) {
newUser = csr.getString(csr.getColumnIndex(MySQLiteHelper.USERNAME));
newEmail = csr.getString(csr.getColumnIndex(MySQLiteHelper.EMAIL));
newPass = csr.getString(csr.getColumnIndex(MySQLiteHelper.PASSWORD));
}
csr.close();
if(isUpdate==true)
Toast.makeText(getContext(),
"Data Updated - User now " + newUser +
" Email now " + newEmail +
" Password now " + newPass,
Toast.LENGTH_LONG
).show();
else
Toast.makeText(getContext(),"Data not Updated - User is " + newUser +
" Email is " + newEmail +
" Password is " + newPass,
Toast.LENGTH_LONG
).show();
}
});
btUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//boolean isUpdate = mySQLiteHelper.updateData(userId, username, password, email); //<<<<<<<<<< Commented out (old)
//<<<<<<<<<< NEW (gets values from the edit texts)
boolean isUpdate = mySQLiteHelper.updateData(
userId,
etUser.getText().toString(),
etPass.getText().toString(),
etEmail.getText().toString()
);
//<<<<<<<<<< ADDED to get current stored data for Toast
Cursor csr = mySQLiteHelper.getDataById(userId);
String newUser = "not found";
String newEmail = "not found";
String newPass = "not found";
if (csr.moveToFirst()) {
newUser = csr.getString(csr.getColumnIndex(MySQLiteHelper.USERNAME));
newEmail = csr.getString(csr.getColumnIndex(MySQLiteHelper.EMAIL));
newPass = csr.getString(csr.getColumnIndex(MySQLiteHelper.PASSWORD));
}
csr.close();
//<<<<<<<<< CHANGES so more info is provided by Toasts
if(isUpdate==true)
Toast.makeText(getContext(),
"Data Updated - User now " + newUser +
" Email now " + newEmail +
" Password now " + newPass,
Toast.LENGTH_LONG
).show();
else
Toast.makeText(getContext(),"Data not Updated - User is " + newUser +
" Email is " + newEmail +
" Password is " + newPass,
Toast.LENGTH_LONG
).show();
}
});