从 CursorAdapter/List 视图中移除多个元素

Remove more than one element from CursorAdapter/List View

我正在 Android/Java 做一个项目。我有一个 activity,带有一个显示数据库值的列表视图和一个删除按钮。目前,此列表视图的每一行都包含一个检查文本视图。最后一个显示数据库元素的名称。我想要 select 不同的元素(带有检查文本视图),然后如果我按下删除按钮,所有 selected 元素都必须从列表和数据库中删除。下面我把我的 classes 的重要部分。我已经完成了大部分工作。 这是我的 activity:

public class ShoppingListActivity extends AppCompatActivity {

// Variables for the management of the database
private DBManagerShoppingList dbShoppingList;
private Cursor crs;
// List view for the shopping list elements
private ListView shoppingListListView;
private ShoppingListViewAdapter shoppingListViewAdapter;
// Generic variables
private String selectedShoppingList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shopping_list);

    // Find of the useful widgets
    shoppingListListView = findViewById(R.id.listViewSelShoppingList);
    shoppingListsSpinner = findViewById(R.id.spinnerShoppingLists);
    selectedShoppingList = "List_1";
    populateListView();
}

// Populate list view from database
public void populateListView() {
    // Database management
    dbShoppingList = new DBManagerShoppingList(this, selectedShoppingList);
    crs = dbShoppingList.query();
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            shoppingListViewAdapter = new ShoppingListViewAdapter(ShoppingListActivity.this, crs, 0);
            shoppingListListView.setAdapter(shoppingListViewAdapter);
        }
    });
}

// Remove selected elements
public void removeSelectedElements(View btnRemove) {
    // TODO
}
}

这是我的自定义适配器:

public class ShoppingListViewAdapter extends CursorAdapter {

private LayoutInflater layoutInflater;
private List<Integer> elementsPosArrayList = new ArrayList<>();
private HashMap<String, Integer> elementsMap = new HashMap<>();

public ShoppingListViewAdapter(Context context, Cursor c, int flags) {
    super(context, c, flags);
    layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
    return layoutInflater.inflate(R.layout.list_view_row, viewGroup, false);
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    // CheckBox management
    final CheckBox checkBoxElementName = view.findViewById(R.id.checkBoxElementName);
    String elementName = cursor.getString(cursor.getColumnIndex(DBFieldsShoppingList.FIELD_ELEMENT_NAME));
    checkBoxElementName.setText(elementName);
    elementsMap.put(elementName, cursor.getPosition());
    checkBoxElementName.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            if (isChecked) {
                elementsPosArrayList.add(elementsMap.get(checkBoxElementName.getText().toString()));
            } else {
                elementsPosArrayList.remove(elementsMap.get(checkBoxElementName.getText().toString()));
            }
        }
    });
}

public long getElementId(Cursor crs, int position) {
    crs.moveToPosition(position);
    return crs.getLong(crs.getColumnIndex(DBFieldsShoppingList.FIELD_ID));
}

public List<Integer> getElementsPosArrayList() {
    return elementsPosArrayList;
}
}

Class数据库管理的内容如下: 数据库助手:

public class DBHelperShoppingList extends SQLiteOpenHelper {

private String DBName;

public DBHelperShoppingList(@Nullable Context context, int dbVersion, String dbName) {
    super(context, dbName, null, dbVersion);
    this.DBName = dbName;
}

@Override
public void onCreate(SQLiteDatabase shoppingListDB) {
    String q = "CREATE TABLE " + DBFieldsShoppingList.FIELD_TABLE_NAME +
            " ( _id INTEGER PRIMARY KEY AUTOINCREMENT," +
            DBFieldsShoppingList.FIELD_ELEMENT_NAME + " TEXT," +
            DBFieldsShoppingList.FIELD_ELEMENT_TYPE + " TEXT," +
            DBFieldsShoppingList.FIELD_ELEMENT_QUANT + " TEXT)";
    shoppingListDB.execSQL(q);
}
@Override
public void onUpgrade(SQLiteDatabase shoppingListDB, int oldVersion, int newVersion) {}
}

Class对于数据库的字段:

public class DBFieldsShoppingList {
    public static final String FIELD_ID = "_Id";
    public static final String FIELD_TABLE_NAME = "Shopping_List";
    public static final String FIELD_ELEMENT_NAME = "Element_Name";
    public static final String FIELD_ELEMENT_TYPE = "Element_Type";
    public static final String FIELD_ELEMENT_QUANT = "Element_Quant";
}

Class 数据库管理员:

public class DBManagerShoppingList {
private DBHelperShoppingList dbHelperShoppingList;

public DBManagerShoppingList(Context ctx, String shoppingListName) {
    dbHelperShoppingList = new DBHelperShoppingList(ctx, 1, shoppingListName);
}

public void dbSave(String elementName, String elementType, String elementQuantity) {
    SQLiteDatabase db = dbHelperShoppingList.getWritableDatabase();
    ContentValues cv = new ContentValues();
    cv.put(DBFieldsShoppingList.FIELD_ELEMENT_NAME, elementName);
    cv.put(DBFieldsShoppingList.FIELD_ELEMENT_TYPE, elementType);
    cv.put(DBFieldsShoppingList.FIELD_ELEMENT_QUANT, elementQuantity);
    try {
        db.insert(DBFieldsShoppingList.FIELD_TABLE_NAME, null, cv);
    } catch (SQLiteException ignored) {}
}

public boolean deleteElement(long id) {
    SQLiteDatabase db = dbHelperShoppingList.getWritableDatabase();
    try {
        return db.delete(DBFieldsShoppingList.FIELD_TABLE_NAME, DBFieldsShoppingList.FIELD_ID + "=?", new String[]{Long.toString(id)})>0;
    } catch(SQLiteException exc) {
        return false;
    }
}

public static void deleteDB(Context ctx, String DBName) {
    ctx.deleteDatabase(DBName);
}

public Cursor query() {
    Cursor crs;
    try {
        SQLiteDatabase db = dbHelperShoppingList.getReadableDatabase();
        crs = db.query(DBFieldsShoppingList.FIELD_TABLE_NAME, null, null, null, null, null, null, null);
    } catch (SQLiteException exc) {
        return null;
    }
    return crs;
}
}

我想在适配器 class 的 bindView 方法中保存元素名称与其位置之间的映射。然后,创建已检查元素的元素名称列表。这样,我可以从地图上知道选中元素的位置。现在,我必须获取已检查元素的索引,以便使用数据库管理器 class 的 delete 方法将它们从数据库中删除。 我怎么解决这个问题?如果我的结构不正确,请告诉我如何更改。 非常感谢您。

马可

大家好, 我找到了解决方案。在数据库管理器 class 中,我按以下方式更改了删除方法:

public boolean deleteElement(String elementName) {
    SQLiteDatabase db = dbHelperShoppingList.getWritableDatabase();
    try {
        return db.delete(DBFieldsShoppingList.FIELD_TABLE_NAME, DBFieldsShoppingList.FIELD_ELEMENT_NAME + "=?", new String[]{(elementName)})>0;
    } catch(SQLiteException exc) {
        return false;
    }
}

这允许在数据库中按名称搜索。 在适配器 class 中,我删除了地图,并写了一个字符串数组列表,其中放置了检查元素的名称:

@Override
public void bindView(View view, Context context, Cursor cursor) {
    // CheckBox management
    final CheckBox checkBoxElementName = view.findViewById(R.id.checkBoxElementName);
    String elementName = cursor.getString(cursor.getColumnIndex(DBFieldsShoppingList.FIELD_ELEMENT_NAME));
    checkBoxElementName.setText(elementName);
    checkBoxElementName.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            if (isChecked) {
                elementNamesArrayList.add(checkBoxElementName.getText().toString());
            } else {
                elementNamesArrayList.remove(checkBoxElementName.getText().toString());
            }
        }
    });
}

最后,在activityclass中,remove方法如下:

public void removeSelectedElements(View btnRemove) {
    List<String> elementNamesArrayList = shoppingListViewAdapter.getElementNamesArrayList();
    for (String item: elementNamesArrayList) {
        dbShoppingList.deleteElement(item);
    }
    populateListView();
}

这样我的问题就解决了

马可