如何修复“所有单击的 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==0position==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 项目都可以使用相同的数据”的主要内容,如果未能解决你的问题,请参考以下文章

如何修复drv?

如何修复漏洞

如何修复WMI

PHP网站漏洞怎么修复 如何修补网站程序代码漏洞

如何修复这些漏洞? (npm audit fix 无法修复这些漏洞)

如何修复AppScan漏洞