如何修复“所有单击的 Listview 项目都可以使用相同的数据”
Posted
技术标签:
【中文标题】如何修复“所有单击的 Listview 项目都可以使用相同的数据”【英文标题】:How to fix "Same data being made available to all Listview items being clicked" 【发布时间】:2019-05-24 00:59:40 【问题描述】:当单击 Listview 项目时,应从 SQLite 数据库中提供特定于该 Listview 项目的数据,但所有 Listview 项目的数据都可用。我该如何纠正这个问题?
Main2Activity:
position = intent.getIntExtra("position",0);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
String text = listView.getItemAtPosition(position).toString();
Toast.makeText(Main2Activity.this, ""+text, Toast.LENGTH_SHORT).show();
);
add_data.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
String place = editText.getText().toString();
if(!place.equals("")&& databaseHelper1.insertData1(place))
editText.setText("");
listItem.clear();
viewData1();
else
Toast.makeText(Main2Activity.this, "Data not added", Toast.LENGTH_SHORT).show();
);
private void viewData1()
Cursor cursor = databaseHelper1.viewData1(position);
if(cursor.getCount()==0)
Toast.makeText(this, "No data to show", Toast.LENGTH_SHORT).show();
else
while(cursor.moveToNext())
listItem.add(cursor.getString(0));
listView.setAdapter(adapter);
数据库助手: 这些是我的桌子:
private static final String CREATE_TABLE = "CREATE TABLE " + DB_TABLE + " (" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + NAME
+ " TEXT " + ")";
private static final String CREATE_TABLE1 = "CREATE TABLE " + DB_TABLE1 + " (" + ID1 + " INTEGER PRIMARY KEY AUTOINCREMENT, "+
PLACE + " TEXT " + " , " + ID + " INTEGER REFERENCES " + DB_TABLE + ")";
我的 insertData 函数:
public boolean insertData1(String place)
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
ContentValues contentValues1 = new ContentValues();
contentValues1.put(PLACE,place);
long result1 = sqLiteDatabase.insert(DB_TABLE1,null,contentValues1);
return result1 != -1;
我的 viewData 函数:
public Cursor viewData1(int position)
SQLiteDatabase sqLiteDatabase = this.getReadableDatabase();
Cursor cursor = null;
if (position==0)
String query = "Select " + DB_TABLE1 + "." + PLACE + " from " + DB_TABLE1;
cursor= sqLiteDatabase.rawQuery(query, null);
if (position==1)
String query = "Select " + DB_TABLE1 + "." + PLACE + " from " + DB_TABLE1;
cursor= sqLiteDatabase.rawQuery(query, null);
return cursor;
使用此代码,我可以将数据库中的所有数据都提供给 Listitem 位置,无论它是位置 0 还是位置 1。 实际输出应该是每个数据与点击的item一致。
【问题讨论】:
您能告诉我们您在viewData1
中使用的确切SQL 吗?在我看来,position==0
和 position==1
的 SQL 似乎是相同的?
发送完整的适配器代码
我从 Main2Activity 传递“位置”(它出现在上面的 viewData1 函数中),它基本上是点击的位置。我不会使用相同的 SQL,因为它取决于单击的位置但相同的表。 @Corion
我添加了代码@Radesh
看viewData1
函数,不管position
是1还是0,它运行的SQL都是相同的。请告诉我SQL的不同之处。
【参考方案1】:
要从 ListView 中访问项目,您需要设置 ListView 的 onItemClickListener 并调用 onItemClick 方法。
onItemClick 传递了 4 个参数:-
-
被点击的Item的AdapterView,
带有被点击的 AdapterView 的视图,
被点击项目在列表中的位置作为偏移量(即 0 是第一个项目,1 是第二个项目,依此类推)和
如果适配器是光标适配器,则被单击的行的 id () 如果它不是光标适配器,则此值将与位置相同,除了它是 long 而不是 int。李>
由于您没有使用 CursorAdapter 而是 List/ArrayListAdapter ,因此可以使用位置,通过适配器的 getItemAtPositition 方法来检索所选项目的字符串。如果该字符串是唯一的,您可以使用它来检索与该项目关联的行。如果它不是唯一的,那么就没有真正的方法来确定哪一行与该项目相关联。
这是仅使用/提取要显示的字符串的问题之一,它并不理想,另外还需要额外的工作。
您可以在从 Cursor 中提取字符串的同时提取 id 并将其放入一个 long 数组中,然后根据位置访问这个 long 数组。然后,您可以使用 id 查询表以从数据库中获取该行。
你可以有一个类来定义一个代表行的对象,包括行的 id 然后有一个 ArrayList 在这种情况下 getItemAtPosition 方法可以返回包含 的对象id(也许所有值都否定了访问数据库的需要)。
也许最简单的方法是使用光标适配器,在这种情况下光标可用(并且定位适当),第四个参数将是所选项目的 id。但是,这需要为 id 列使用特定的列名,即必须将列命名为 _id。这可以通过重命名 ID1 列或使用 AS 关键字交替提供 ID1 和别名来实现。
工作示例
您的代码似乎存在一些问题和不少遗漏。因此,这是一个基于您的代码的工作示例。
此示例将显示 5 行的 ListView,每行由两个表中的数据按照关系组成。单击一个项目将 Toast 基础值。
DatabaseHelper.java :-
public class DatabaseHelper extends SQLiteOpenHelper
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String DB_TABLE = "dbtable";
public static final String DB_TABLE1 = "dbtable1";
public static final String COL_TABLE_ID = BaseColumns._ID;
public static final String COL_TABLE_NAME = "name";
public static final String COL_TABLE1_ID1 = BaseColumns._ID;
public static final String COL_TABLE1_ID1_ALTERNATIVE = DB_TABLE1 + "_" + COL_TABLE1_ID1; //alternative column name so no ambiguity
public static final String COl_TABLE1_PLACE = "place";
public static final String COL_TABLE1_ID = "id";
SQLiteDatabase mDB;
//Note AUTOINCREMENT removed not needed/inefficient
private static final String CREATE_TABLE = "CREATE TABLE " + DB_TABLE + " (" +
COL_TABLE_ID + " INTEGER PRIMARY KEY, " +
COL_TABLE_NAME + " TEXT " +
")";
private static final String CREATE_TABLE1 = "CREATE TABLE " + DB_TABLE1 + " (" +
COL_TABLE1_ID1 + " INTEGER PRIMARY KEY, " + //(limits 1 to 1 relationship, due to needing to be unique)
COl_TABLE1_PLACE + " TEXT " + " , " +
COL_TABLE1_ID + " INTEGER REFERENCES " + DB_TABLE + "(" +
COL_TABLE_ID +
")" +
")";
public DatabaseHelper(Context context)
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
// Foreign kjey support need to be turned on
@Override
public void onConfigure(SQLiteDatabase db)
super.onConfigure(db);
db.setForeignKeyConstraintsEnabled(true);
@Override
public void onCreate(SQLiteDatabase db)
db.execSQL(CREATE_TABLE);
db.execSQL(CREATE_TABLE1);
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1)
public long insertTableRow(String name)
ContentValues cv = new ContentValues();
cv.put(COL_TABLE_NAME,name);
return mDB.insert(DB_TABLE,null,cv);
public long insertTable1Row(long table_reference, String place)
ContentValues cv = new ContentValues();
cv.put(COL_TABLE1_ID,table_reference);
cv.put(COl_TABLE1_PLACE,place);
return mDB.insert(DB_TABLE1,null,cv);
public Cursor getAllFromBothTables()
String table = DB_TABLE + " JOIN " + DB_TABLE1 + " ON " + DB_TABLE + "." + COL_TABLE_ID + " = " + DB_TABLE1 + "." + COL_TABLE1_ID;
String[] columns = new String[]
DB_TABLE + "." + COL_TABLE_ID,
DB_TABLE + "." + COL_TABLE_NAME,
DB_TABLE1 + "." + COL_TABLE1_ID1 + " AS " + COL_TABLE1_ID1_ALTERNATIVE,
DB_TABLE1 + "." + COl_TABLE1_PLACE,
DB_TABLE1 + "." + COL_TABLE1_ID
;
return mDB.query(table,columns,null,null,null,null,null);
Main2Activity.java
public class Main2Activity extends AppCompatActivity
DatabaseHelper DatabaseHelper1;
ListView listview;
SimpleCursorAdapter mSCA;
Cursor mCsr;
Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
mContext = this;
setContentView(R.layout.activity_main2);
listview = this.findViewById(R.id.mylistview);
DatabaseHelper1 = new DatabaseHelper(this);
addSomeTestData();
handleListView();
private void addSomeTestData()
if (DatabaseUtils.queryNumEntries(DatabaseHelper1.getWritableDatabase(),DatabaseHelper.DB_TABLE) > 0) return;
DatabaseHelper1.insertTableRow("Fred");
DatabaseHelper1.insertTableRow("Mary");
DatabaseHelper1.insertTableRow("Sue");
DatabaseHelper1.insertTable1Row(1,"London");
DatabaseHelper1.insertTable1Row(2,"New York");
DatabaseHelper1.insertTable1Row(3,"Sydney");
DatabaseHelper1.insertTable1Row(1,"Paris");
DatabaseHelper1.insertTable1Row(1,"Toronto");
private void handleListView()
mCsr = DatabaseHelper1.getAllFromBothTables();
DatabaseUtils.dumpCursor(mCsr);
if (mSCA == null)
mSCA = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_2,mCsr,
new String[]
DatabaseHelper.COL_TABLE_NAME,
DatabaseHelper.COl_TABLE1_PLACE
,
new int[]android.R.id.text1,android.R.id.text2,
0
);
listview.setAdapter(mSCA);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
Toast.makeText(
mContext,
"You clicked on name = " + mCsr.getString(mCsr.getColumnIndex(DatabaseHelper.COL_TABLE_NAME)) +
" place = " + mCsr.getString(mCsr.getColumnIndex(DatabaseHelper.COl_TABLE1_PLACE)) +
" id of TABLE is " + String.valueOf(l) +
" id of TABLE from cursor is " + String.valueOf(mCsr.getLong(mCsr.getColumnIndex(DatabaseHelper.COL_TABLE_ID))) +
" id of TABLE1 is " + String.valueOf(mCsr.getLong(mCsr.getColumnIndex(DatabaseHelper.COL_TABLE1_ID1_ALTERNATIVE))),
Toast.LENGTH_SHORT).show();
);
else
mSCA.swapCursor(mCsr);
当上面运行时它看起来像:-
【讨论】:
以上是关于如何修复“所有单击的 Listview 项目都可以使用相同的数据”的主要内容,如果未能解决你的问题,请参考以下文章