Java Android SQLiteDatabase-从数据库中删除值后Listview和数据库ID不匹配
大家好,我是android数据库的新手。我遵循这个网站的教程。下面的代码是关于添加、更新、删除数据库中的名称。Java Android SQLiteDatabase-从数据库中删除值后Listview和数据库ID不匹配,java,android,database,sqlite,listview,Java,Android,Database,Sqlite,Listview,大家好,我是android数据库的新手。我遵循这个网站的教程。下面的代码是关于添加、更新、删除数据库中的名称。 一切正常。我可以从数据库中添加、更新和删除姓名。 问题: 例如,我添加了4个名称 ID name 1 A 2 B 3 C 4 D 当我删除一个文件时,它会从listview和数据库中删除。它在listview中更新。 现在数据库看起来像这样 ID name 1 null 2 B 3 C 4 D B C D Listview是这样的 ID name
一切正常。我可以从数据库中添加、更新和删除姓名。
问题: 例如,我添加了4个名称
ID name
1 A
2 B
3 C
4 D
当我删除一个文件时,它会从listview和数据库中删除。它在listview中更新。
现在数据库看起来像这样
ID name
1 null
2 B
3 C
4 D
B
C
D
Listview是这样的
ID name
1 null
2 B
3 C
4 D
B
C
D
因此,当我点击B删除或编辑时,它在我的编辑和删除视图中不显示任何内容,但当我点击C时,它在删除视图中显示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;
}
问题
onItemClickListener的第三个参数(arg2)是位置(第四个参数也是位置,除非使用光标适配器)
位置永远不会等同于id(除非您强制id具有某些值),这是因为第一项的位置为0。第一行的id将为1。如果您开始删除行,那么生活就会变得更加复杂,正如您所发现的那样
解析(理论上)
您需要做的是获得正确的id
您可以使用一个免费的long数组列表ArrayList
或一个long数组long[]
(您需要两种方法来构建ArrayList
和ArrayList
或long[]
)。但是,如果您使用了过滤器,那么这也可能是不同步的因此,不建议使用这种方法。
您可以使用游标适配器和游标作为ListView的源,然后第四个参数将是id(需要一个名为\u id的列,它应该是行的id)我建议使用游标,因为不需要中间对象
您可以使用对象的ArrayListArrayList
,在这种情况下,对象将至少有两个成员id和name。然后,您可以使用适配器的getItem(arg2)
方法检索对象,然后从对象中获取id
使用2个解决方案的工作示例
以下是显示3个列表视图的应用程序的代码:第一个由字符串ArrayList(您当前拥有的内容)生成,第二个由对象ArrayList(适当的对象,即MyTableObject ArrayList)生成,第三个通过光标生成。显示的数据相同
单击项目显示可获得的值(可传递给删除的值)
- 第一个ListView只能获取并显示位置(就好像它是ID一样)
- 第二个列表视图显示从对象获得的ID和从位置获得的ID(它们不匹配)
- 第三个列表视图显示通过光标获得的ID(相当于对象)和从第四个参数获得的ID,它们始终匹配
- 注意每次运行应用程序时都会添加更多数据。
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();
}
});
}
}
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
);
}
}
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;
}
}
活动\u 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>
DatabaseHelper.java已更改为包含一个新方法,用于根据id
i、 e.增加了以下方法:-
public int delete(long id) {
String whereclause = COl_MYTABLE_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
return mDB.delete(TB_MYTABLE,whereclause,whereargs);
}
问题
onItemClickListener的第三个参数(arg2)是位置(第四个参数也是位置,除非使用光标适配器)
位置永远不会等同于id(除非您强制id具有某些值),这是因为第一项的位置为0。第一行的id将为1。如果您开始删除行,那么生活就会变得更加复杂,正如您所发现的那样
解析(理论上)
您需要做的是获得正确的id
您可以使用一个免费的long数组列表ArrayList
或一个long数组long[]
(您需要两种方法来构建ArrayList
和ArrayList
或long[]
)。但是,如果您使用了过滤器,那么这也可能是不同步的因此,不建议使用这种方法。
您可以使用游标适配器和游标作为ListView的源,然后第四个参数将是id(需要一个名为\u id的列,它应该是行的id)我建议使用游标,因为不需要中间对象
您可以使用对象的ArrayListArrayList
,在这种情况下,对象将至少有两个成员id和name。然后,您可以使用适配器的getItem(arg2)
方法检索对象,然后从对象中获取id
使用2个解决方案的工作示例
以下是显示3个列表视图的应用程序的代码:第一个由字符串ArrayList(您当前拥有的内容)生成,第二个由对象ArrayList(适当的对象,即MyTableObject ArrayList)生成,第三个通过光标生成。显示的数据相同
单击项目显示可获得的值(可传递给删除的值)
- 第一个ListView仅显示位置ca
public int delete(long id) { String whereclause = COl_MYTABLE_ID + "=?"; String[] whereargs = new String[]{String.valueOf(id)}; return mDB.delete(TB_MYTABLE,whereclause,whereargs); }