从附加到 SQLite 的 Listview 中删除 ListItem

Remove ListItem from Listview attached to SQLite

[ACTIVITY][1] <-------------- 观看 ACTIVITY

我一直在尝试从 ListView[=] 中的 SQLite 中删除 上的项目时遇到问题50=] 到目前为止,我已经能够成功删除列表中的第一项。每当我在 ListView.

上单击 删除按钮

如果您有任何意见或反馈,请不要犹豫,欢迎我!

这里是相关代码

DBHelper

public class DBHelper extends SQLiteOpenHelper {

private static final String DB_NAME = "ListappDB";
private static final int DB_VERSION = 1;
public static final String DB_TABLE = "List";
public static final String DB_COLUMN = "Item";

public DBHelper(Context context) {
    super(context, DB_NAME, null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
    String query = String.format("CREATE TABLE %s(ID INTEGER PRIMARY KEY AUTOINCREMENT, %s TEXT NOT NULL)", DB_TABLE, DB_COLUMN);
    db.execSQL(query);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    String query = String.format("DELETE TABLE IF EXISTS %s", DB_TABLE);
    db.execSQL(query);
    onCreate(db);
}

public void insertNewItem(String item){
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues values = new ContentValues();
    values.put(DB_COLUMN, item);
    db.insertWithOnConflict(DB_TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
    db.close();
}

public void deleteItem(String item){
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(DB_TABLE, DB_COLUMN + "=?", new String[]{ item });
    db.close();
}

public ArrayList<String> getItemList(){
    ArrayList<String> itemList = new ArrayList<String>();
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(DB_TABLE, new String[]{DB_COLUMN},null,null,null,null,null);
    while (cursor.moveToNext()){
        int index = cursor.getColumnIndex(DB_COLUMN);
        itemList.add(cursor.getString(index));
    }
    cursor.close();
    db.close();
    return itemList;
}

}

主要Activity

public class MainActivity extends AppCompatActivity {

private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DBHelper mDBHelper;
private ArrayAdapter<String> mAdapter;
private ListView mListView;
private Button mButton;
private Button mDeleteButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_ACTION_BAR);
    setContentView(R.layout.activity_main);

    mDBHelper = new DBHelper(this);
    mAuth = FirebaseAuth.getInstance();

    mListView = (ListView) findViewById(R.id.list);
    mButton = (Button) findViewById(R.id.buttonQR);


    mButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ArrayList<String> itemList = mDBHelper.getItemList();
            MultiFormatWriter multiFW = new MultiFormatWriter();
            try {
                BitMatrix bitMatrix = multiFW.encode(String.valueOf(itemList), BarcodeFormat.QR_CODE, 200, 200);
                BarcodeEncoder enconder = new BarcodeEncoder();
                Bitmap bitmap =  enconder.createBitmap(bitMatrix);
                Intent intent = new Intent(getApplicationContext(), QR.class);
                intent.putExtra("qrcode", bitmap);
                startActivity(intent);

            } catch (WriterException e) {
                e.printStackTrace();
            }
        }
    });

    mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {

            if (firebaseAuth.getCurrentUser() == null){
                goAuthenticate();
            }
        }
    };


    loadItemList();
}

private void loadItemList() {
    ArrayList<String> itemList = mDBHelper.getItemList();
    if (mAdapter==null){
        mAdapter = new ArrayAdapter<String>(this, R.layout.row, R.id.item_name, itemList);
        mListView.setAdapter(mAdapter);
    } else {
        mAdapter.clear();
        mAdapter.addAll(itemList);
        mAdapter.notifyDataSetChanged();
    }
}

public void goAuthenticate(){
    Intent mLogin = new Intent(MainActivity.this, Authentication.class);
    mLogin.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(mLogin);
    finish();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater=getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()){
        case R.id.logout:
            mAuth.signOut();
            LoginManager.getInstance().logOut();
            break;
        case R.id.addNewItem:
            final EditText itemEditText = new EditText(this);
            AlertDialog alertDialog = new AlertDialog.Builder(this)
                    .setTitle("Add New Item")
                    .setView(itemEditText)
                    .setPositiveButton("Add", new DialogInterface.OnClickListener(){

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            String item = String.valueOf(itemEditText.getText());
                            if(item.length() <= 0|| item.equals("")){
                                Toast.makeText(MainActivity.this, "Item Cant Be Blank",
                                        Toast.LENGTH_LONG).show();
                            } else {
                                mDBHelper.insertNewItem(item);
                                loadItemList();
                            }
                        }
                    })
                    .setNegativeButton("Cancel", null)
                    .create();
            alertDialog.show();
            break;
    }


    return super.onOptionsItemSelected(item);
}

public void deleteItemH(View view){

    TextView itemTextView = (TextView) view.findViewById(R.id.item_name);
    String item = String.valueOf(itemTextView.getText());
    mDBHelper.deleteItem(item);
    loadItemList();

}

@Override
public void onStart() {
    super.onStart();
    mAuth.addAuthStateListener(mAuthListener);
}

@Override
public void onStop() {
    super.onStop();
    if (mAuthListener != null){
        mAuth.removeAuthStateListener(mAuthListener);
    }
}

}

Row.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:id="@+id/item_name"
    android:text="Example"
    android:textSize="20dp"
    android:layout_alignParentStart="true"
    />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btnDelete"
    android:layout_alignParentEnd="true"
    android:layout_alignParentRight="true"
    android:text="DELETE"
    android:onClick="deleteItemH"
    android:layout_centerVertical="true"/>

Activity Main.xml

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="tech.destinum.listapp.MainActivity"
android:layout_centerVertical="true">


<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/list"
    android:clipChildren="false"
    android:layout_weight="1"/>


<RelativeLayout
    android:id="@+id/footer"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:gravity="center">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/buttonQR"
            android:text="Generate"/>
</RelativeLayout>

您在问题中提到的解决问题的方法不正确。 用下面的解决方案提到问题

问题 1

You should use Custom Adapter instead of using basic ArrayAdapter.

ItemAdapter.class

 public class ItemAdapter extends BaseAdapter {

    private final LayoutInflater layoutInflater;
    private ArrayList<ItemClass> itemList;
    private final DBHelper dbHelper;

    public ItemAdapter(Context context, DBHelper dbHelper, ArrayList<ItemClass> itemList) {
        this.itemList = itemList;
        this.layoutInflater = LayoutInflater.from(context);
        this.dbHelper = dbHelper;
    }

    @Override
    public int getCount() {
        return itemList != null ? itemList.size() : 0;
    }

    @Override
    public Object getItem(int i) {
        return itemList.get(i);
    }

    @Override
    public long getItemId(int i) {
        return itemList.get(i)._id;
    }

    //use this function to assign list of items
    public void setItemList(ArrayList<ItemClass> itemList) {
        this.itemList.clear();
        this.itemList = itemList;
        notifyDataSetChanged();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {

        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.row, null);
            viewHolder = new ViewHolder(convertView);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        final ItemClass itemClass = itemList.get(position);

        viewHolder.btn_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                deleteItemH(itemClass);
            }
        });
        viewHolder.tv_item.setText(itemClass.detail);
        return convertView;
    }

    private void deleteItemH(ItemClass item) {
        dbHelper.deleteItemById(item._id);
        setItemList(dbHelper.getItemList());
    }

    private static class ViewHolder {
        final Button btn_delete;
        final TextView tv_item;

        ViewHolder(View view) {
            btn_delete = (Button) view.findViewById(R.id.btnDelete);
            tv_item = (TextView) view.findViewById(R.id.item_name);
        }
    }
}

问题二:-

You were trying to delete the row data using the item column which will delete all the row with same name, as you haven't put the unique constraint in the item column.

因此,根据您的使用情况,您应该对 项目列 设置唯一约束,或者通过 _ID 列 删除项目。

修改了您的 DBHelper 代码以通过 _ID column.

删除行
public class DBHelper extends SQLiteOpenHelper {

    private static final String DB_NAME = "ListappDB";
    private static final int DB_VERSION = 1;
    public static final String DB_TABLE = "List";
    public static final String DB_COLUMN = "Item";
    //added this variable to use it while deleting the record
    public static final String DB_COLUMN_ID = "_id";

    public DBHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String query = String.format("CREATE TABLE %s( %s INTEGER PRIMARY KEY AUTOINCREMENT, %s TEXT NOT NULL)", DB_TABLE, DB_COLUMN_ID, DB_COLUMN);
        db.execSQL(query);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        String query = String.format("DELETE TABLE IF EXISTS %s", DB_TABLE);
        db.execSQL(query);
        onCreate(db);
    }

    public void insertNewItem(String item) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(DB_COLUMN, item);
        db.insertWithOnConflict(DB_TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
        db.close();
    }


    public void deleteItem(String item) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(DB_TABLE, DB_COLUMN + "=?", new String[]{item});
        db.close();
    }

    //Function to delete item using ID
    public void deleteItemById(long id) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(DB_TABLE, DB_COLUMN_ID + "=?", new String[]{id + ""});
        db.close();
    }

    public ArrayList<ItemClass> getItemList() {
        ArrayList<ItemClass> itemList = new ArrayList<>();
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.query(DB_TABLE, new String[]{DB_COLUMN_ID, DB_COLUMN}, null, null, null, null, null);
        while (cursor.moveToNext()) {
            final String name = cursor.getString(cursor.getColumnIndex(DB_COLUMN));
            final long id = cursor.getLong(cursor.getColumnIndex(DB_COLUMN_ID));
            itemList.add(new ItemClass(id, name));
        }
        cursor.close();
        db.close();
        return itemList;
    }
}

修改你MainActivity.class以支持上面使用的ItemAdapter.class

public class MainActivity extends AppCompatActivity {

private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DBHelper mDBHelper;
private ItemAdapter mAdapter;
private ListView mListView;
private Button mButton;
private Button mDeleteButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_ACTION_BAR);
    setContentView(R.layout.activity_main);

    mDBHelper = new DBHelper(this);
    mAuth = FirebaseAuth.getInstance();

    mListView = (ListView) findViewById(R.id.list);
    mButton = (Button) findViewById(R.id.buttonQR);


    mButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ArrayList<String> itemList = mDBHelper.getItemList();
            MultiFormatWriter multiFW = new MultiFormatWriter();
            try {
                BitMatrix bitMatrix = multiFW.encode(String.valueOf(itemList), BarcodeFormat.QR_CODE, 200, 200);
                BarcodeEncoder enconder = new BarcodeEncoder();
                Bitmap bitmap =  enconder.createBitmap(bitMatrix);
                Intent intent = new Intent(getApplicationContext(), QR.class);
                intent.putExtra("qrcode", bitmap);
                startActivity(intent);

            } catch (WriterException e) {
                e.printStackTrace();
            }
        }
    });

    mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {

            if (firebaseAuth.getCurrentUser() == null){
                goAuthenticate();
            }
        }
    };


    loadItemList();
}

//only needed once rest of the time it is getting managed inside the ItemAdapter
private void loadItemList() {
    ArrayList<ItemClass> itemList = mDBHelper.getItemList();
    mAdapter = new ItemAdapter(MainActivity.this, mDBHelper, itemList);
    mListView.setAdapter(mAdapter);
}

public void goAuthenticate(){
    Intent mLogin = new Intent(MainActivity.this, Authentication.class);
    mLogin.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(mLogin);
    finish();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater=getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()){
        case R.id.logout:
            mAuth.signOut();
            LoginManager.getInstance().logOut();
            break;
        case R.id.addNewItem:
            final EditText itemEditText = new EditText(this);
            AlertDialog alertDialog = new AlertDialog.Builder(this)
                    .setTitle("Add New Item")
                    .setView(itemEditText)
                    .setPositiveButton("Add", new DialogInterface.OnClickListener(){

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            String item = String.valueOf(itemEditText.getText());
                            if(item.length() <= 0|| item.equals("")){
                                Toast.makeText(MainActivity.this, "Item Cant Be Blank",
                                        Toast.LENGTH_LONG).show();
                            } else {
                                mDBHelper.insertNewItem(item);
                                loadItemList();
                            }
                        }
                    })
                    .setNegativeButton("Cancel", null)
                    .create();
            alertDialog.show();
            break;
    }


    return super.onOptionsItemSelected(item);
}


@Override
public void onStart() {
    super.onStart();
    mAuth.addAuthStateListener(mAuthListener);
}

@Override
public void onStop() {
    super.onStop();
    if (mAuthListener != null){
        mAuth.removeAuthStateListener(mAuthListener);
    }
}
}

添加了额外的 ItemClass.java 以支持适配器传递 id 和 item。

public class ItemClass {
    public final long _id;
    public final String detail;

    public ItemClass(long id, String detail) {
        _id = id;
        this.detail = detail;
    }
}

row.xml 中删除了 android:onClick="deleteItemH" 因为您不能使用单击适配器项。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:id="@+id/item_name"
    android:text="Example"
    android:textSize="20dp"
    android:layout_alignParentStart="true"
    />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btnDelete"
    android:layout_alignParentEnd="true"
    android:layout_alignParentRight="true"
    android:text="DELETE"
    android:layout_centerVertical="true"/>

使用上述更改您的删除将正常工作

首先,请提供布局膨胀的自定义数组适配器的完整代码。

其次,Row.xml中的以下属性不适用于此处。

android:onClick="deleteItemH"

只有当您直接从 Activity 放大视图时才有效(Click here 了解更多详细信息)。您应该在自定义数组适配器中为 btnDelete 使用 setOnClickListener

同样,在查看自定义阵列适配器后可以提供更多帮助。