从数据库删除项目时,如何使用自定义适配器自动更新ListView
我创建了一个listView,并为其实现了一个自定义适配器。另外,我将其连接到SQLite数据库,该数据库包含ListView的内容。
我有一个带有几个项目的ListView。每个项目都由一个文本视图和一个功能作为按钮的imageView组成。当用户单击ImageView时,我想从数据库中删除该项目,并自动更新ListView。
不幸的是,我只知道如何从数据库中删除项目。从数据库中删除该项目后,我想不出一种方法可以自动更新程序中的ListView。
在下面的版本中,我在MainActivity中为ListView添加了一个OnItemClickListener-但对于用户单击imageView时,它不适(即使ImageView是ListView的一部分)。
MainActivity
public class MainActivity extends AppCompatActivity {
//References to buttons and other controls on the layout
private Button btn_add;
private EditText et_todo;
private Switch sw;
private static ListView lv;
private static DataAdapter todoAdapter;
private DataBaseHelper dbHelper;
/**
* Initialization Method
*
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new DataBaseHelper(MainActivity.this);
assignVariables();
registerClick();
showAllToDos(dbHelper);
}
private void assignVariables() {
//assign values to variables
btn_add = (Button) findViewById(R.id.btn_add);
et_todo = (EditText) findViewById(R.id.et_todo);
lv = (ListView) findViewById(R.id.lv);
}
public void showAllToDos(DataBaseHelper dbHelper) {
todoAdapter = new DataAdapter(MainActivity.this, R.layout.list_item, dbHelper.getAllAsList(), dbHelper);
lv.setAdapter(todoAdapter);
}
private void registerClick() {
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String toDoTitle = et_todo.getText().toString();
if(Pattern.matches("s*", toDoTitle)) {
Toast.makeText(MainActivity.this, "Title is missing", Toast.LENGTH_SHORT).show();
} else if(dbHelper.existsInDB(new DataModel(toDoTitle))) {
Toast.makeText(MainActivity.this, "Already added as ToDo", Toast.LENGTH_SHORT).show();
} else {
DataModel dModel = new DataModel(toDoTitle);
dbHelper.addOne(dModel);
showAllToDos(dbHelper);
}
//empty input field
et_todo.setText("");
}
});
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
DataModel clickedItem = (DataModel) adapterView.getItemAtPosition(position);
dbHelper.deleteOne(clickedItem);
showAllToDos(dbHelper);
}
});
}
}
datamodel
public class DataModel {
//Attributes
private int id;
private String title;
//Constructors
public DataModel(String title) {
this.title = title;
}
public DataModel() {
}
//toString
@Override
public String toString() {
return "DataModel{" +
"id=" + id +
", title='" + title + '\'' +
'}';
}
//Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
dataAdapter
public class DataAdapter extends ArrayAdapter<DataModel> {
/**
* Attributes
*/
private Context mContext;
private int mResource;
private ArrayList<DataModel> mList;
private DataBaseHelper mDbHelper;
public DataAdapter(Context context, int resource, ArrayList<DataModel> list, DataBaseHelper dbHelper) {
super(context, resource, list);
mContext = context;
mResource = resource;
mList = list;
mDbHelper = dbHelper;
}
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
//get the objects information
String title = getItem(position).getTitle();
//create object with the information
DataModel model = new DataModel(title);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
//get TextViews
TextView tvTitle = (TextView) convertView.findViewById(R.id.task);
//set information to TextViews
tvTitle.setText(title);
//delete function
ImageView delView = (ImageView) convertView.findViewById(R.id.delView);
delView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mDbHelper.deleteOne(model);
}
});
return convertView;
}
}
databaseHelper
public class DataBaseHelper extends SQLiteOpenHelper {
public static final String TODO_TABLE = "TODO_TABLE";
public static final String COLUMN_ID = "ID";
public static final String COLUMN_TODO_TITLE = "TODO_TITLE";
private Context mContext;
public DataBaseHelper(@Nullable Context context) {
super(context, "todo.db", null, 1);
mContext = context;
}
/**
* Is called when the app requests or inputs new data.
*
* @param db
*/
@Override
public void onCreate(SQLiteDatabase db) {
String createTableStatement = "CREATE TABLE " + TODO_TABLE
+ " (" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_TODO_TITLE + " TEXT)";
db.execSQL(createTableStatement);
//create new Table
}
/**
* Called whenever the database version number changes.
* Prevents the previous apps from crashing.
*
* @param sqLiteDatabase
* @param i
* @param i1
*/
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
/**
* method to add new database entry
*
* @param dModel
* @return
*/
public boolean addOne(DataModel dModel) {
SQLiteDatabase db = this.getWritableDatabase(); //for insert actions
ContentValues cv = new ContentValues(); //Content values stores data in pairs
cv.put(COLUMN_TODO_TITLE, dModel.getTitle());
long insert = db.insert(TODO_TABLE, null, cv);
//clean up, close connection to database and cursor
db.close();
if(insert == -1) { //if insert is negative number than insert went wrong
return false;
} else { //if insert is positive number than insert succeeded
return true;
}
}
public boolean deleteOne(DataModel dModel) {
//if DataModel is found in the database, delete it and return true
//if it is not found, return false
SQLiteDatabase db = this.getWritableDatabase();
String queryString = "DELETE FROM " + TODO_TABLE
+ " WHERE " + COLUMN_TODO_TITLE + " = " + "\"" + dModel.getTitle() + "\"";;
Cursor cursor = db.rawQuery(queryString, null);
if(cursor.moveToFirst()) {
return true;
} else {
return false;
}
}
public ArrayList<DataModel> getAllAsList() {
//create empty list
ArrayList<DataModel> returnList = new ArrayList<>();
//get data from the database
String queryString = "SELECT * FROM " + TODO_TABLE;
SQLiteDatabase db = this.getReadableDatabase(); //get data from database
Cursor cursor = db.rawQuery(queryString, null);
if(cursor.moveToFirst()) { //returns a true if there were items selected
//loop through results, create new todo objects, put them into return list
do {
String todoTitle = cursor.getString(1);
DataModel newTodo = new DataModel(todoTitle);
returnList.add(newTodo);
} while(cursor.moveToNext());
} else { //returns a false if no items were selected
//failure, to not add anything to the list
}
//clean up, close connection to database and cursor
cursor.close();
db.close();
return returnList;
}
public boolean existsInDB(DataModel dModel) {
SQLiteDatabase db = this.getWritableDatabase(); //for insert actions
String queryString = "SELECT * FROM " + TODO_TABLE
+ " WHERE " + COLUMN_TODO_TITLE + " = " + "\"" + dModel.getTitle() + "\"";
Cursor cursor = db.rawQuery(queryString, null);
if(cursor.moveToFirst()) {
return true;
} else {
return false;
}
}
}
我感谢任何帮助或建议。 让我知道,如果您需要进一步的解释。
妮可
I created a ListView for which I implemented a custom adapter. Additionally I connected it to a SQLite database, which contains the content for the ListView.
I have one ListView with several items. Every item consists of a TextView and an ImageView which functions as a button. When the user clicks the ImageView, I want to delete the item from the database and automatically update the ListView.
Unluckily, I just know how to delete the item from the database. I can't think of a way to automatically update the ListView in my program, after the item got deleted from the database.
In the version below, I added an onItemClickListener for the ListView in the MainActivity - but it doesn't function for when the user clicks the ImageView (even though the ImageView is part of the ListView).
MainActivity
public class MainActivity extends AppCompatActivity {
//References to buttons and other controls on the layout
private Button btn_add;
private EditText et_todo;
private Switch sw;
private static ListView lv;
private static DataAdapter todoAdapter;
private DataBaseHelper dbHelper;
/**
* Initialization Method
*
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new DataBaseHelper(MainActivity.this);
assignVariables();
registerClick();
showAllToDos(dbHelper);
}
private void assignVariables() {
//assign values to variables
btn_add = (Button) findViewById(R.id.btn_add);
et_todo = (EditText) findViewById(R.id.et_todo);
lv = (ListView) findViewById(R.id.lv);
}
public void showAllToDos(DataBaseHelper dbHelper) {
todoAdapter = new DataAdapter(MainActivity.this, R.layout.list_item, dbHelper.getAllAsList(), dbHelper);
lv.setAdapter(todoAdapter);
}
private void registerClick() {
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String toDoTitle = et_todo.getText().toString();
if(Pattern.matches("s*", toDoTitle)) {
Toast.makeText(MainActivity.this, "Title is missing", Toast.LENGTH_SHORT).show();
} else if(dbHelper.existsInDB(new DataModel(toDoTitle))) {
Toast.makeText(MainActivity.this, "Already added as ToDo", Toast.LENGTH_SHORT).show();
} else {
DataModel dModel = new DataModel(toDoTitle);
dbHelper.addOne(dModel);
showAllToDos(dbHelper);
}
//empty input field
et_todo.setText("");
}
});
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
DataModel clickedItem = (DataModel) adapterView.getItemAtPosition(position);
dbHelper.deleteOne(clickedItem);
showAllToDos(dbHelper);
}
});
}
}
DataModel
public class DataModel {
//Attributes
private int id;
private String title;
//Constructors
public DataModel(String title) {
this.title = title;
}
public DataModel() {
}
//toString
@Override
public String toString() {
return "DataModel{" +
"id=" + id +
", title='" + title + '\'' +
'}';
}
//Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
DataAdapter
public class DataAdapter extends ArrayAdapter<DataModel> {
/**
* Attributes
*/
private Context mContext;
private int mResource;
private ArrayList<DataModel> mList;
private DataBaseHelper mDbHelper;
public DataAdapter(Context context, int resource, ArrayList<DataModel> list, DataBaseHelper dbHelper) {
super(context, resource, list);
mContext = context;
mResource = resource;
mList = list;
mDbHelper = dbHelper;
}
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
//get the objects information
String title = getItem(position).getTitle();
//create object with the information
DataModel model = new DataModel(title);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
//get TextViews
TextView tvTitle = (TextView) convertView.findViewById(R.id.task);
//set information to TextViews
tvTitle.setText(title);
//delete function
ImageView delView = (ImageView) convertView.findViewById(R.id.delView);
delView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mDbHelper.deleteOne(model);
}
});
return convertView;
}
}
DataBaseHelper
public class DataBaseHelper extends SQLiteOpenHelper {
public static final String TODO_TABLE = "TODO_TABLE";
public static final String COLUMN_ID = "ID";
public static final String COLUMN_TODO_TITLE = "TODO_TITLE";
private Context mContext;
public DataBaseHelper(@Nullable Context context) {
super(context, "todo.db", null, 1);
mContext = context;
}
/**
* Is called when the app requests or inputs new data.
*
* @param db
*/
@Override
public void onCreate(SQLiteDatabase db) {
String createTableStatement = "CREATE TABLE " + TODO_TABLE
+ " (" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_TODO_TITLE + " TEXT)";
db.execSQL(createTableStatement);
//create new Table
}
/**
* Called whenever the database version number changes.
* Prevents the previous apps from crashing.
*
* @param sqLiteDatabase
* @param i
* @param i1
*/
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
/**
* method to add new database entry
*
* @param dModel
* @return
*/
public boolean addOne(DataModel dModel) {
SQLiteDatabase db = this.getWritableDatabase(); //for insert actions
ContentValues cv = new ContentValues(); //Content values stores data in pairs
cv.put(COLUMN_TODO_TITLE, dModel.getTitle());
long insert = db.insert(TODO_TABLE, null, cv);
//clean up, close connection to database and cursor
db.close();
if(insert == -1) { //if insert is negative number than insert went wrong
return false;
} else { //if insert is positive number than insert succeeded
return true;
}
}
public boolean deleteOne(DataModel dModel) {
//if DataModel is found in the database, delete it and return true
//if it is not found, return false
SQLiteDatabase db = this.getWritableDatabase();
String queryString = "DELETE FROM " + TODO_TABLE
+ " WHERE " + COLUMN_TODO_TITLE + " = " + "\"" + dModel.getTitle() + "\"";;
Cursor cursor = db.rawQuery(queryString, null);
if(cursor.moveToFirst()) {
return true;
} else {
return false;
}
}
public ArrayList<DataModel> getAllAsList() {
//create empty list
ArrayList<DataModel> returnList = new ArrayList<>();
//get data from the database
String queryString = "SELECT * FROM " + TODO_TABLE;
SQLiteDatabase db = this.getReadableDatabase(); //get data from database
Cursor cursor = db.rawQuery(queryString, null);
if(cursor.moveToFirst()) { //returns a true if there were items selected
//loop through results, create new todo objects, put them into return list
do {
String todoTitle = cursor.getString(1);
DataModel newTodo = new DataModel(todoTitle);
returnList.add(newTodo);
} while(cursor.moveToNext());
} else { //returns a false if no items were selected
//failure, to not add anything to the list
}
//clean up, close connection to database and cursor
cursor.close();
db.close();
return returnList;
}
public boolean existsInDB(DataModel dModel) {
SQLiteDatabase db = this.getWritableDatabase(); //for insert actions
String queryString = "SELECT * FROM " + TODO_TABLE
+ " WHERE " + COLUMN_TODO_TITLE + " = " + "\"" + dModel.getTitle() + "\"";
Cursor cursor = db.rawQuery(queryString, null);
if(cursor.moveToFirst()) {
return true;
} else {
return false;
}
}
}
I appreciate any kind of help or suggestion.
Let me know, if you need further explanation.
Nicole
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
根据您的代码考虑以下内容: -
工作示例
以下代码基于您的代码,但在图像(单击紫色的框)时进行了各种更改并删除列表。
list_item.xml 布局(更改为无图像以突出显示项目): -
datamodel 类是不变的。
databasehelper 类已更改为a)不关闭数据库(这是效率低下的,因为它将应用WAL更改,然后必须打开databaset,该数据库相对昂贵,b)使用和c)使用便利方法时所有光标: -
dataAdapter
notifyDataSetchanged
,它告诉适配器重建。和 MainActivity : -
*结果
来自新的安装(空数据库),然后采取以下操作: -
添加test001-test006 so: -
单击项目test003(不是紫色框(图像))
d/clickaction:单击titletest003
的项目
单击删除图像(紫色框)以进行测试003
d/clickAction:图像单击标题= test003位置2
Consider the following based upon your code:-
Working Example
The following code is based upon yours BUT with various changes that does delete and refresh the list when the image (purple box is clicked).
The list_item.xml layout (altered to highlight the items as no image):-
The DataModel class is unchanged.
The DatabaseHelper class has been changed to a) not close the database (this is inefficient as it will apply the WAL changes and then have to subseuqently open the databaset which is relatively resource costly) and b) to close all cursors when done with the and c) utilise the convenience methods :-
DataAdapter
notifyDatasetChanged
that tells the adapter to rebuild.and MainActivity :-
*Results
From a new install (empty Database) then the following actions were taken:-
Add Test001 - Test006 so :-
Click on Item Test003 (NOT the purple box (image))
D/CLICKACTION: Item was clicked for TitleTest003
Click on the Delete image (purple box) for Test003
D/CLICKACTION: Image clicked for title = Test003 position 2
直接使用sqlite可能具有挑战性,也不建议再使用listView。最好的做法是在这里使用RecycleView
是一个很好的教程,全部使用它:
Room - Google的Sqlite包装库
livedata>
="https://developer.android.com/guide/topics/ui/layout/recyclerview?gclid=Cj0KCQjw-pCVBhCFARIsAGMxhAecKzLSA4G5a_hqcD9ZqkSCKhqLIzykl6Gu0GIBtC0UJGJrRMp25eQaArBoEALw_wcB&gclsrc=aw.ds" rel="nofollow noreferrer">RecyclerView - UI widget for建筑有效列表
Using SQLite directly can be challenging, also ListView is outdated not recommended to use anymore. The best practise is to use RecycleView
Here is a good tutorial how to use it all:
Room - wrapper library for SQLite from Google
LiveData - for subscribing for live update
RecyclerView - UI widget for building efficient lists