[英]Update / Refresh Listview From Custom Adapter Dialog Possitive Button After Updating Sqlite Database
我有一个从数据库填充的列表视图。 在同一个活动中,我在列表视图上方还有一个 EditTExt 和一个添加类别按钮。
类别名称1 | 编辑按钮 | 删除按钮类别名称2 | 编辑按钮 | 删除按钮类别名称3 | 编辑按钮 | 删除按钮
如果我添加类别,列表视图会更新。
如果我单击删除,打开对话框(您确定吗?),当您单击是时,它会从数据库中删除它,然后使用已删除的行更新列表视图。
如果我单击编辑按钮(位于列表视图布局的自定义适配器中),它会打开对话框并显示带有类别名称的编辑文本,您可以更改它,当您单击保存按钮时,它会将其保存到数据库,但不更新列表视图。
所以我解决了这个问题,而不是尝试重新轮询数据库以再次更新列表视图,我抓住了 position 和该行类别的编辑文本并以这种方式更新。
一次只能编辑 1 个项目,我认为这没什么大不了的,直到我通过使用此解决方法遇到另一个问题。 那就是:
如果单击类别名称 1 的编辑按钮并在对话框中将其重命名为有意义的类别名称。 它会更新数据库,它会立即反映在列表视图中,但是当您在执行任何其他操作之前删除该项目时,当我将消息发送到不同的列表视图让我知道它已被删除时,它反映的是原始类别名称而不是编辑过的。
现在解决这个问题的方法是,当我想删除它时,不要依赖列表视图中的类别名称,而是在删除之前从数据库中获取类别名称,然后删除它,然后发送带有类别名称的消息数据库。
我真正想要的是以下流程,而不是使用这两种解决方法:
使用自定义列表视图加载活动->单击编辑->从自定义适配器打开对话框编辑->单击保存按钮->更新数据库。 -> Listview 已更新/刷新。
除了更新/刷新 Listview 之外,我已经完成了所有工作。
我搜索了高低,可以找到各种可以用来刷新列表视图的方法,但是它们都不起作用,而且它们都不能用于从自定义适配器的对话框中更新数据库。
我可以发布代码,但我认为这非常简单。 如果没有,我很乐意发布代码。
也许考虑使用 CursorAdapter 消除对中间数组的需要并且刷新是轻而易举的。
这是一个使用 SimpleCursorAdapter 的示例,除了编辑之外,它只做所有的事情(但是您可能需要一个自定义 Cursor 适配器)。 但是,刷新方面与特定适配器类型没有什么不同。
布局activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
/>
<EditText
android:id="@+id/categoryname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</EditText>
<Button
android:id="@+id/addcategorybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ADD CATEGORY"
>
</Button>
<ListView
android:id="@+id/categorylist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</ListView>
</LinearLayout>
数据库助手DBHelper
class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "category.db";
public static final int DBVERSION = 1;
public static final String TB_CATEGORY = "category";
public static final String COl_ID_CATEGORY = BaseColumns._ID;
public static final String COl_CATEGORYNAME_CATEGORY = "category_name";
private SQLiteDatabase db;
private static volatile DBHelper instance;
private DBHelper(@Nullable Context context) {
super(context, DBNAME, null, DBVERSION);
db = this.getWritableDatabase();
}
public static DBHelper getInstance(Context context) {
if (instance == null) {
instance = new DBHelper(context);
}
return instance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TB_CATEGORY + "(" +
COl_ID_CATEGORY + " INTEGER PRIMARY KEY" +
"," + COl_CATEGORYNAME_CATEGORY + " TEXT UNIQUE " +
")");
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
}
public long insertCategory(String categoryName) {
ContentValues cv = new ContentValues();
cv.put(COl_CATEGORYNAME_CATEGORY,categoryName);
return db.insert(TB_CATEGORY,null,cv);
}
public int deleteCategory(long id) {
return db.delete(TB_CATEGORY,COl_ID_CATEGORY + "=?", new String[]{String.valueOf(id)});
}
public int deleteCategory(String categoryName) {
return db.delete(TB_CATEGORY,COl_CATEGORYNAME_CATEGORY + "=?",new String[]{categoryName});
}
public int updateCategory(Long id, String categoryName) {
ContentValues cv = new ContentValues();
cv.put(COl_CATEGORYNAME_CATEGORY,categoryName);
return db.update(TB_CATEGORY,cv,COl_ID_CATEGORY+"=?", new String[]{String.valueOf(id)});
}
public int updateCategory(String oldCatgeoryName, String newCategoryName) {
ContentValues cv = new ContentValues();
cv.put(COl_CATEGORYNAME_CATEGORY,newCategoryName);
return db.update(TB_CATEGORY,cv,COl_CATEGORYNAME_CATEGORY + "=?",new String[]{oldCatgeoryName});
}
public Cursor getCategories() {
return db.query(TB_CATEGORY,null,null,null,null,null,COl_CATEGORYNAME_CATEGORY + " ASC");
}
}
_id INTEGER PRIMARY KEY
定义 rowid 列 aka 列的别名(带或不带 AUTOINCREMENT(不带更有效,很少需要带,因此最好不要使用))。活动MainActivity :-
public class MainActivity extends AppCompatActivity {
EditText categoryName;
Button addCategory;
ListView categoryList;
SimpleCursorAdapter sca;
DBHelper db;
Cursor csr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
categoryName = this.findViewById(R.id.categoryname);
addCategory = this.findViewById(R.id.addcategorybutton);
categoryList = this.findViewById(R.id.categorylist);
db = DBHelper.getInstance(this);
setupAddCategoryButton();
setOrRefreshCategoryListView();
}
public void setOrRefreshCategoryListView() {
csr = db.getCategories();
if (sca == null) {
sca = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_1,
csr, //<<<<<<<< The Cursor
new String[]{DBHelper.COl_CATEGORYNAME_CATEGORY}, //<<<<<<<< The list of columns to be displayed
new int[]{android.R.id.text1}, //<<<<<<<< The corresponding view id's in the layout that is to display the data from the column
0
);
categoryList.setAdapter(sca);
categoryList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
DBHelper dbx = DBHelper.getInstance(view.getContext());
if (dbx.deleteCategory(l) > 0) {
setOrRefreshCategoryListView();
}
return true;
}
});
} else {
sca.swapCursor(csr);
}
}
public void setupAddCategoryButton() {
addCategory.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (categoryName.getText().toString().length() > 0) {
if (db.insertCategory(categoryName.getText().toString()) > 0) {
setOrRefreshCategoryListView();
}
categoryName.setText("");
}
}
});
}
}
setOrRefreshCategoryListView
,所有需要刷新(并最初设置 ListView)都在这里完成。 你只需要调用该方法。当上面运行时。 可以通过输入文本然后单击添加类别按钮来添加类别。 可以通过长按类别来删除类别。
结果
在添加几个类别 (1-3) 之后和添加第 4 个类别之前:-
点击添加:-
长按类别 2:-
补充评论
我只是想在从警报对话框更新后,有一种方法可以从自定义适配器本身内刷新列表视图。
也许考虑以下显示从适配器内部刷新(即热 DLT 按钮和项目被删除和刷新)
以及通过 EDIT 按钮调用的活动(不只编辑 toasts)。
首先是用于 CustomAdapter 的布局
CursorAdapter 的子类,我仍然会推荐它而不是 ArrayAdapter(即 CursorAdapter 的存在是有原因的)。
<LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/categoryname" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="6"> </TextView> <Button android:id="@+id/categoryedit" android:layout_width="0dp" android:layout_weight="2" android:layout_height="match_parent" android:text="EDIT" android:onClick="onClickEditCategoryButton" android:layout_marginRight="2dp" > </Button> <Button android:id="@+id/categorydelete" android:layout_width="0dp" android:layout_weight="2" android:layout_height="match_parent" android:text="DLT" > </Button> </LinearLayout>
注意EDIT 按钮指定了 onCLick,因此 onClicklistener 代码代表您进行编码。
DBHelper与上面没有变化。
MainActivity现在是:-
public class MainActivity extends AppCompatActivity {
EditText categoryName;
Button addCategory;
ListView categoryList;
CustomAdapter ca;
DBHelper db;
Cursor csr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
categoryName = this.findViewById(R.id.categoryname);
addCategory = this.findViewById(R.id.addcategorybutton);
categoryList = this.findViewById(R.id.categorylist);
db = DBHelper.getInstance(this);
setupAddCategoryButton();
setOrRefreshCustomCategoryListView();
}
public void setOrRefreshCustomCategoryListView() {
csr = db.getCategories();
if (ca == null) {
ca = new CustomAdapter(this,csr);
categoryList.setAdapter(ca);
} else {
ca.swapCursor(csr);
}
}
public void onClickEditCategoryButton(View v) {
switch (v.getId()) {
case R.id.categoryedit: {
Toast.makeText(this, "You Clicked Edit for Category with ID of " + v.getTag(), Toast.LENGTH_SHORT).show();
setOrRefreshCustomCategoryListView();
}
break;
}
}
public void setupAddCategoryButton() {
addCategory.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (categoryName.getText().toString().length() > 0) {
if (db.insertCategory(categoryName.getText().toString()) > 0) {
setOrRefreshCustomCategoryListView();
}
categoryName.setText("");
}
}
});
}
}
最后一个CustomAdapter :-
class CustomAdapter extends CursorAdapter {
CustomAdapter(Context context, Cursor csr) {
super(context,csr, android.widget.CursorAdapter.IGNORE_ITEM_VIEW_TYPE);
}
@Override
public View newView(Context context, Cursor csr, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.categorylist,parent,false);
}
@Override
public void bindView(View view, Context context, Cursor csr) {
TextView categoryName = view.findViewById(R.id.categoryname);
categoryName.setText(csr.getString(csr.getColumnIndex(DBHelper.COl_CATEGORYNAME_CATEGORY)));
// Set Button tags with id of current row
// NOTE button onClick listener set in layout
String id = csr.getString(csr.getColumnIndex(DBHelper.COl_ID_CATEGORY));
view.findViewById(R.id.categoryedit).setTag(id);
view.findViewById(R.id.categorydelete).setTag(id);
view.findViewById(R.id.categorydelete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(context,"You Clicked Delete",Toast.LENGTH_SHORT).show();
DBHelper.getInstance(context).deleteCategory(Long.parseLong(view.getTag().toString()));
refreshListView(context);
}
});
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return super.getView(position, convertView, parent);
}
public void refreshListView(Context context) {
this.swapCursor(DBHelper.getInstance(context).getCategories());
}
}
结果
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.