大家好,我是 android SQLiteDatabase 的新手。我正在关注此网站 ORIGINAL CODE 的教程。下面的代码是关于从数据库中添加、更新、删除名称。
一切正常。我可以在数据库中添加、更新和删除名称。
问题: 例如我添加了 4 个名字。
ID name
1 A
2 B
3 C
4 D
当我删除 A 时,它会从 ListView 和数据库中删除。它在 ListView 中更新。 现在数据库看起来像这样
ID name
1 null
2 B
3 C
4 D
Listview 看起来像这样
B
C
D
因此,当我单击 B 进行删除或编辑时,它在编辑和删除 View 中不显示任何内容,但当我单击 C 时,它在删除 View 中显示 B。
我浏览了 stackoverflow 中提供的所有解决方案,我知道这是重复的问题,但是这个示例有任何解决方案吗? 我希望当我单击 B 时,它应该显示 B 不为空,当我单击 C 时,它应该显示 C,删除 A 后。
注意:任何人都可以修复代码吗?我非常确定有很多开发人员正在寻求解决这个问题。特别是像我这样的初学者。这将是很大的帮助。提前谢谢您。
DBHelper
public Integer deleteContact (Integer id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete("contacts",
"id = ? ",
new String[] { Integer.toString(id) });
}
public ArrayList<String> getAllCotacts() {
ArrayList<String> array_list = new ArrayList<String>();
//hp = new HashMap();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery( "select * from contacts", null );
res.moveToFirst();
while(res.isAfterLast() == false){
array_list.add(res.getString(res.getColumnIndex(CONTACTS_COLUMN_NAME)));
res.moveToNext();
}
return array_list;
}
设备详细信息 Activity
public class devicedetailsActivity extends AppCompatActivity {
public final static String EXTRA_MESSAGE = "MESSAGE";
private ListView obj;
DBHelper mydb;
ArrayList array_list ;
public ArrayAdapter arrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.devicedetails_layout);
mydb = new DBHelper(this);
}
public void onResume() {
refreshList();
super.onResume();
}
public void refreshList() {
array_list = mydb.getAllCotacts();
arrayAdapter=new ArrayAdapter(this,R.layout.simple_list_item_1, array_list);
obj = (ListView)findViewById(R.id.listView1);
obj.setAdapter(arrayAdapter);
obj.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
// TODO Auto-generated method stub
int id_To_Search = arg2 + 1;
Bundle dataBundle = new Bundle();
dataBundle.putInt("id", id_To_Search);
Intent intent = new Intent(getApplicationContext(),DetailsActivity.class);
intent.putExtras(dataBundle);
startActivity(intent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
getMenuInflater().inflate(R.menu.home, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item){
super.onOptionsItemSelected(item);
switch(item.getItemId()) {
case R.id.item1:Bundle dataBundle = new Bundle();
dataBundle.putInt("id", 0);
Intent intent = new Intent(getApplicationContext(),DetailsActivity.class);
intent.putExtras(dataBundle);
startActivity(intent);
return true;
case R.id.item2: dataBundle = new Bundle();
dataBundle.putInt("id", 0);
intent = new Intent(getApplicationContext(),MainActivity.class);
intent.putExtras(dataBundle);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
详细 Activity
public class DetailsActivity extends AppCompatActivity {
private DBHelper mydb ;
ArrayAdapter arrayAdapter;
TextView name ;
int id_To_Update = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details);
name = (TextView) findViewById(R.id.editTextName);
mydb = new DBHelper(this);
Bundle extras = getIntent().getExtras();
if(extras !=null) {
int Value = extras.getInt("id");
if(Value>0){
//means this is the view part not the add contact part.
Cursor rs = mydb.getData(Value);
if(rs.moveToFirst()) {
id_To_Update = Value;
rs.moveToFirst();
String nam = rs.getString(rs.getColumnIndex(DBHelper.CONTACTS_COLUMN_NAME));
Button b = (Button)findViewById(R.id.button1);
b.setVisibility(View.INVISIBLE);
name.setText((CharSequence)nam);
name.setFocusable(false);
name.setClickable(false);
}
if (!rs.isClosed()) {
rs.close();
}
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Bundle extras = getIntent().getExtras();
if(extras !=null) {
int Value = extras.getInt("id");
if(Value>0){
getMenuInflater().inflate(R.menu.display_contact, menu);
} else{
getMenuInflater().inflate(R.menu.back, menu);
}
}
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch(item.getItemId()) {
case R.id.Edit_Contact:
Button b = (Button)findViewById(R.id.button1);
b.setVisibility(View.VISIBLE);
name.setEnabled(true);
name.setFocusableInTouchMode(true);
name.setClickable(true);
return true;
case R.id.Delete_Contact:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.deleteContact)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mydb.deleteContact(id_To_Update);
Toast.makeText(getApplicationContext(), "Deleted Successfully",
Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getApplicationContext(),devicedetailsActivity.class);
startActivity(intent);
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
AlertDialog d = builder.create();
d.setTitle("Are you sure");
d.show();
return true;
case R.id.back:
Intent intent = new Intent(getApplicationContext(),devicedetailsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void run(View view) {
Bundle extras = getIntent().getExtras();
if(extras !=null) {
int Value = extras.getInt("id");
if(Value>0){
if(mydb.updateContact(id_To_Update,name.getText().toString()
)){
Toast.makeText(getApplicationContext(), "Updated", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getApplicationContext(),devicedetailsActivity.class);
startActivity(intent);
} else{
Toast.makeText(getApplicationContext(), "not Updated", Toast.LENGTH_SHORT).show();
}
} else{
if(mydb.insertContact(name.getText().toString())){
Toast.makeText(getApplicationContext(), "done",
Toast.LENGTH_SHORT).show();
} else{
Toast.makeText(getApplicationContext(), "not done",
Toast.LENGTH_SHORT).show();
}
Intent intent = new Intent(getApplicationContext(),devicedetailsActivity.class);
startActivity(intent);
}
}
}
}
最佳答案
问题
onItemClickListener 的第三个参数 (arg2) 是位置(除非您使用游标适配器,否则将是第四个参数)。
位置永远不会等于id(除非您强制 id 具有特定值),这是因为第一个项目的位置为 0。第一行将为 1。如果您开始删除行,那么正如您所发现的那样,生活会变得更加复杂。
灵魂(理论上)
您要做的就是获取正确的id。
您可以使用免费的 Long ArrayList ArrayList<Long>
或一个 long 数组 long[]
(您需要两种方法来构建 ArrayList<String>
和 ArrayList<long>
或 long[]
)。但是,如果您使用过滤器,那么这也可能不同步。 因此,不推荐这种方法。
您可以使用游标适配器和游标作为 ListView 的源,然后第四个参数将是 id(需要名为 _id 的列,它应该是行的 id )。 我建议使用游标,因为不需要中间对象
您可以使用对象的ArrayList ArrayList<your_object>
,在这种情况下,该对象将至少有两个成员 id 和 name。然后您可以使用适配器的 getItem(arg2)
方法来检索对象,然后从对象中获取 id。
使用 2 个解决方案的工作示例
以下是一个应用程序的代码,该应用程序显示 3 个 ListView ,第一个由字符串 ArrayList(您当前拥有的)提供,第二个由对象 ArrayList(适当的对象,即 MyTableObject ArrayList)提供,第三个由游标提供。显示的数据是相同的。
单击某个项目会显示可以获得的值(可以传递到删除的值)。
- 第一个ListView只能获取位置并显示出来(就好像它是ID一样),
- 第二个ListView显示从对象获取的ID和从位置获取的ID(它们不会匹配)
第3个ListView显示的是通过Cursor获取的ID(相当于对象)和从第4个参数获取的ID,它们总是匹配的。
请注意,每次运行应用程序时都会添加更多数据。
MainActivity.java
public class MainActivity extends AppCompatActivity {
DatabaseHelper mDBHlpr;
ListView mListView01,mListVeiw02,mListView03;
ArrayAdapter<String> mAdapterStringArrayList;
ArrayAdapter<MyTableObject> mAdapterMyTableObjectArrayList;
SimpleCursorAdapter mAdapterCursor;
ArrayList<String> mMyTableListAsStrings;
ArrayList<MyTableObject> mMyTableAsObjects;
Cursor mMyTableListAsCursor;
Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
mListView01 = this.findViewById(R.id.listview01);
mListVeiw02 = this.findViewById(R.id.listview02);
mListView03 = this.findViewById(R.id.listview03);
mDBHlpr = new DatabaseHelper(this);
mDBHlpr.addRow("Fred");
mDBHlpr.addRow("Bert");
mDBHlpr.addRow("Harry");
mDBHlpr.addRow("Fred");
//String Array List
mMyTableListAsStrings = mDBHlpr.getAllAsStringArrayList();
mAdapterStringArrayList = new ArrayAdapter<>(
this,
android.R.layout.simple_list_item_1,
mMyTableListAsStrings
);
mListView01.setAdapter(mAdapterStringArrayList);
//Object Array List
mMyTableAsObjects = mDBHlpr.getAllAsMyTableObjectArrayList();
mAdapterMyTableObjectArrayList = new ArrayAdapter<>(
this,
android.R.layout.simple_list_item_1,
mMyTableAsObjects
);
mListVeiw02.setAdapter(mAdapterMyTableObjectArrayList);
// Cursor
mMyTableListAsCursor = mDBHlpr.getAllAsCursor();
mAdapterCursor = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_1,
mMyTableListAsCursor,
new String[]{DatabaseHelper.COL_MYTABLE_NAME},
new int[]{android.R.id.text1},
0
);
mListView03.setAdapter(mAdapterCursor);
mListView01.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
String name = mAdapterStringArrayList.getItem(position);
Toast.makeText(
mContext,
"Name is " + name +
". ID is " + String.valueOf(id) +
" (note may not match)",
Toast.LENGTH_SHORT
).show();
}
});
mListVeiw02.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
MyTableObject mytable = mAdapterMyTableObjectArrayList.getItem(position);
String name = mytable.getName();
long id_in_object = mytable.getId();
Toast.makeText(
mContext,
"Name is " + name +
". ID from object is " + String.valueOf(id_in_object) +
". ID from adapter is " + String.valueOf(id),
Toast.LENGTH_SHORT
).show();
}
});
mListView03.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Cursor csr = mAdapterCursor.getCursor(); // already positioned
String name = csr.getString(csr.getColumnIndex(DatabaseHelper.COL_MYTABLE_NAME));
long id_in_cursor = csr.getLong(csr.getColumnIndex(DatabaseHelper.COl_MYTABLE_ID));
Toast.makeText(
mContext,
"Name is " + name +
". ID from object is " + String.valueOf(id_in_cursor) +
". ID from adapter is " + String.valueOf(id),
Toast.LENGTH_SHORT
).show();
}
});
}
}
DatabaseHelper.java
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TB_MYTABLE = "mytable";
public static final String COl_MYTABLE_ID = BaseColumns._ID; //<<<< use standard android id column name
public static final String COL_MYTABLE_NAME = "_name";
private static final String mytable_crtsql =
"CREATE TABLE IF NOT EXISTS " + TB_MYTABLE +
"(" +
COl_MYTABLE_ID + " INTEGER PRIMARY KEY, " +
COL_MYTABLE_NAME + " TEXT " +
")";
SQLiteDatabase mDB;
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(mytable_crtsql);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
public long addRow(String name) {
ContentValues cv = new ContentValues();
cv.put(COL_MYTABLE_NAME,name);
return mDB.insert(TB_MYTABLE,null,cv);
}
public ArrayList<String> getAllAsStringArrayList() {
ArrayList<String> rv = new ArrayList<>();
Cursor csr = mDB.query(
TB_MYTABLE,
null,
null,
null,
null,
null,
null
);
while (csr.moveToNext()) {
rv.add(csr.getString(csr.getColumnIndex(COL_MYTABLE_NAME)));
}
csr.close();
return rv;
}
public ArrayList<MyTableObject> getAllAsMyTableObjectArrayList() {
ArrayList<MyTableObject> rv = new ArrayList<>();
Cursor csr = mDB.query(
TB_MYTABLE,
null,
null,
null,
null,
null,
null
);
while (csr.moveToNext()) {
rv.add(new MyTableObject(
csr.getLong(csr.getColumnIndex(COl_MYTABLE_ID)),
csr.getString(csr.getColumnIndex(COL_MYTABLE_NAME))
)
);
}
csr.close();
return rv;
}
public Cursor getAllAsCursor() {
return mDB.query(
TB_MYTABLE,
null,
null,
null,
null,
null,
null
);
}
}
MyTableObject.java
public class MyTableObject {
private long id;
private String name;
public MyTableObject(long id, String name) {
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/*
NOTE toString method returns just the name
*/
@Override
public String toString() {
return name;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="ArrayList-String"
/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="ArrayList-object"
/>
<TextView
android:text="Cursor"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ListView
android:id="@+id/listview01"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:background="#ffffaaaa">
</ListView>
<ListView
android:id="@+id/listview02"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:background="#ffaaffaa">
</ListView>
<ListView
android:id="@+id/listview03"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:background="#ffaaaaff">
</ListView>
</LinearLayout>
</LinearLayout>
更新工作示例并添加删除
以下是上面的内容,但能够通过长按删除行(仅适用于第二个和第三个 ListView)。
MainActivity 已更改为
- 包含第二个和第三个 ListView 的 OnItemLongClick 监听器
- 新增
delete
使用传递的 id 调用方法 refreshAllListViews
然后调用刷新所有ListView
- 新增
- 注意没有可靠的方法从第一个ListView中删除
更改后的 MainActivity.java :-
public class MainActivity extends AppCompatActivity {
DatabaseHelper mDBHlpr;
ListView mListView01,mListVeiw02,mListView03;
ArrayAdapter<String> mAdapterStringArrayList;
ArrayAdapter<MyTableObject> mAdapterMyTableObjectArrayList;
SimpleCursorAdapter mAdapterCursor;
ArrayList<String> mMyTableListAsStrings;
ArrayList<MyTableObject> mMyTableAsObjects;
Cursor mMyTableListAsCursor;
Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
mListView01 = this.findViewById(R.id.listview01);
mListVeiw02 = this.findViewById(R.id.listview02);
mListView03 = this.findViewById(R.id.listview03);
mDBHlpr = new DatabaseHelper(this);
mDBHlpr.addRow("Fred");
mDBHlpr.addRow("Bert");
mDBHlpr.addRow("Harry");
mDBHlpr.addRow("Fred");
//String Array List
mMyTableListAsStrings = mDBHlpr.getAllAsStringArrayList();
mAdapterStringArrayList = new ArrayAdapter<>(
this,
android.R.layout.simple_list_item_1,
mMyTableListAsStrings
);
mListView01.setAdapter(mAdapterStringArrayList);
//Object Array List
mMyTableAsObjects = mDBHlpr.getAllAsMyTableObjectArrayList();
mAdapterMyTableObjectArrayList = new ArrayAdapter<>(
this,
android.R.layout.simple_list_item_1,
mMyTableAsObjects
);
mListVeiw02.setAdapter(mAdapterMyTableObjectArrayList);
// Cursor
mMyTableListAsCursor = mDBHlpr.getAllAsCursor();
mAdapterCursor = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_1,
mMyTableListAsCursor,
new String[]{DatabaseHelper.COL_MYTABLE_NAME},
new int[]{android.R.id.text1},
0
);
mListView03.setAdapter(mAdapterCursor);
mListView01.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
String name = mAdapterStringArrayList.getItem(position);
Toast.makeText(
mContext,
"Name is " + name +
". ID is " + String.valueOf(id) +
" (note may not match)",
Toast.LENGTH_SHORT
).show();
}
});
mListVeiw02.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
MyTableObject mytable = mAdapterMyTableObjectArrayList.getItem(position);
String name = mytable.getName();
long id_in_object = mytable.getId();
Toast.makeText(
mContext,
"Name is " + name +
". ID from object is " + String.valueOf(id_in_object) +
". ID from adapter is " + String.valueOf(id),
Toast.LENGTH_SHORT
).show();
}
});
mListVeiw02.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
mDBHlpr.delete(mAdapterMyTableObjectArrayList.getItem(i).getId());
refreshAllListViews();
return true;
}
});
mListView03.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Cursor csr = mAdapterCursor.getCursor(); // already positioned
String name = csr.getString(csr.getColumnIndex(DatabaseHelper.COL_MYTABLE_NAME));
long id_in_cursor = csr.getLong(csr.getColumnIndex(DatabaseHelper.COl_MYTABLE_ID));
Toast.makeText(
mContext,
"Name is " + name +
". ID from object is " + String.valueOf(id_in_cursor) +
". ID from adapter is " + String.valueOf(id),
Toast.LENGTH_SHORT
).show();
}
});
mListView03.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
mDBHlpr.delete(l);
refreshAllListViews();
return true;
}
});
}
public void refreshAllListViews() {
mMyTableListAsStrings.clear();
ArrayList<String> newStringArray = mDBHlpr.getAllAsStringArrayList();
mMyTableListAsStrings.addAll(newStringArray);
mAdapterStringArrayList.notifyDataSetChanged();
mMyTableAsObjects.clear();
ArrayList<MyTableObject> newObjectArray = mDBHlpr.getAllAsMyTableObjectArrayList();
mMyTableAsObjects.addAll(newObjectArray);
mAdapterMyTableObjectArrayList.notifyDataSetChanged();
mMyTableListAsCursor = mDBHlpr.getAllAsCursor();
mAdapterCursor.swapCursor(mMyTableListAsCursor);
}
}
DatabaseHelper.java 已更改为包含根据 id 删除行的新方法
即添加了以下方法:-
public int delete(long id) {
String whereclause = COl_MYTABLE_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
return mDB.delete(TB_MYTABLE,whereclause,whereargs);
}
关于java - Android SQLiteDatabase - 从数据库中删除值后 ListView 和数据库 ID 不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52022794/