changeCursor() 不刷新 ListView
changeCursor() doesn't refresh ListView
我有一个简单的应用程序来管理学生名单。
在 MainActivity 中,我们可以将学生添加到列表中。单击添加的 ListView
项目,打开一个新的 activity,我们可以在其中编辑学生成绩。
我在列表中使用自定义 CursorAdapter,并使用自定义 SQLiteOpenHelper 数据库来处理数据库。
在 MainActivity:onResume()
我检查数据库是否已更改,如果是则调用 changeCursor()
。
调试时,似乎设置了数据库更改标志,但对 changeCursor()
的调用不会使用新数据
刷新 ListView
示例
- 添加
Adi,10
- 单击列表项 -> 新建 activity ->
grade
编辑为 20
-> 点击返回按钮
- 期待看到
Adi,20
,仍然看到Adi,10
这是我的相关代码:
主要Activity:
public class MainActivity extends AppCompatActivity {
private SqlDbHelper mDB;
private SQLAdapter mAdapter;
@Override
protected void onResume() {
super.onResume();
if(mDB.isDbChanged()) {
mAdapter.changeCursor(mDB.getAllRows());
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Init fields & needed views */
mDB = new SqlDbHelper(getApplicationContext());
mAdapter = new SQLAdapter(getApplicationContext(), mDB.getAllRows(), false);
final ListView lvStudents = findViewById(R.id.lv_students);
final EditText etName = findViewById(R.id.et_name);
final EditText etGrade = findViewById(R.id.et_grade);
/* Listen to ADD BUTTON clicks */
findViewById(R.id.button_add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
insertNewRecord(etName.getText().toString(), etGrade.getText().toString());
etName.setText("");
etGrade.setText("");
}
});
/* Set adapter to LV, Listen to list item clicks */
lvStudents.setAdapter(mAdapter);
lvStudents.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent listItemIntent = new Intent(getApplicationContext(), ListItemActivity.class);
/* Put needed info in the Intent extra */
listItemIntent.putExtra(SqlDbHelper.KEY_ID, l);
listItemIntent.putExtra(SqlDbHelper.KEY_NAME,
((TextView)view.findViewById(R.id.tv_name)).getText().toString());
listItemIntent.putExtra(SqlDbHelper.KEY_GRADE,
Integer.parseInt( ((TextView)view
.findViewById(R.id.tv_grade))
.getText().toString() ));
startActivity(listItemIntent);
}
});
}
private void insertNewRecord(final String name, final String grade) {
/* Add the new student to the DB */
mDB.addStudent(name, gradeInt);
mAdapter.changeCursor(mDB.getAllRows());
}
}
SQL适配器:
final class SQLAdapter extends CursorAdapter {
private LayoutInflater mInflater;
public SQLAdapter(Context context, Cursor c, boolean autoRequery) {
super(context, c, autoRequery);
mInflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
return mInflater.inflate(R.layout.lv_line, viewGroup, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
final String name = cursor.getString(cursor.getColumnIndex(SqlDbHelper.KEY_NAME));
final int grade = cursor.getInt(cursor.getColumnIndex(SqlDbHelper.KEY_GRADE));
view.findViewById(R.id.ll_line).setBackgroundColor(Color.RED);
((TextView)view.findViewById(R.id.tv_name)).setText(name);
((TextView)view.findViewById(R.id.tv_grade)).setText(String.valueOf(grade));
}
}
SqlDbHelper:
final class SqlDbHelper extends SQLiteOpenHelper {
// some static string variables //
/* Flag indicating DB was changed (by editStudent) -
* For indication to MainActivity to refresh its list onResume */
private static boolean mDbChanged;
public SqlDbHelper(Context context) {
super(context, DB_NAME, null, VERSION);
mDbChanged = false;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
/* Create sql command to create new table */
StringBuilder sql = new StringBuilder();
sql.append("CREATE TABLE " + TABLE_NAME + " (")
.append(KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,")
.append(KEY_NAME + " TEXT,")
.append(KEY_GRADE + " INT")
.append(")");
Log.d(TAG, "Query to form table: " + sql.toString());
sqLiteDatabase.execSQL(sql.toString());
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {}
public void addStudent(final String name, final int grade) {
ContentValues cv = new ContentValues();
cv.put(KEY_NAME, name);
cv.put(KEY_GRADE, grade);
getWritableDatabase().insert(TABLE_NAME, null, cv);
}
public void editStudent(final long id, final int grade) throws IllegalArgumentException {
StringBuilder updateQuery = new StringBuilder();
updateQuery.append("UPDATE " + TABLE_NAME)
.append(" SET " + KEY_GRADE)
.append(" = " + grade)
.append(" WHERE " + KEY_ID)
.append(" = " + id);
Log.d(TAG, "Query to edit: " + updateQuery.toString());
getWritableDatabase().execSQL(updateQuery.toString());
/* Indicate the change */
mDbChanged = true;
}
/**
* Aid method to get all rows in the DB
* @return Cursor pointing to the start of all rows
*/
public Cursor getAllRows() {
/* Turn change flag off, if method was called in order
* to refresh the main listview onResume */
if(mDbChanged) {
mDbChanged = false;
}
return getReadableDatabase().
rawQuery("SELECT * FROM " + TABLE_NAME, null);
}
public boolean isDbChanged() {
return mDbChanged;
}
}
ListItemActivity:
public class ListItemActivity extends AppCompatActivity {
private Intent mIntent;
private Button mButtonEdit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_item);
/* Get needed params for the view */
mIntent = getIntent();
mButtonEdit = findViewById(R.id.button_item_edit);
EditText etGrade = findViewById(R.id.et_item_grade);
/* Set the Student's Name & Grade */
final int grade = mIntent.getIntExtra(KEY_GRADE, -1);
((TextView)findViewById(R.id.tv_item_name)).
setText(mIntent.getStringExtra(KEY_NAME));
etGrade.setText(String.valueOf(grade));
/* Set on click listener for the edit button */
mButtonEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SqlDbHelper db = new SqlDbHelper(getApplicationContext());
db.editStudent(mIntent.getLongExtra(KEY_ID, -1), grade);
}
});
}
}
问题出在 mButton onClick()
方法的 ListItemActivity
中。
我没有使用在 EditText 框中输入的新成绩来更新数据库,而是使用了一个旧的 grade
变量来保存在 onCreate()
中获得的旧成绩值。
花了一些时间才弄明白,这是因为 activity 中屏幕上的等级确实更改为新等级,尽管数据库已更新为旧等级。
解法:
中LastItemActivity::onClick
,改
db.editStudent(mIntent.getLongExtra(KEY_ID, -1), grade);
到
db.editStudent(mIntent.getLongExtra(KEY_ID, -1), Integer.parseInt(etGrade.getText().toString()))
我有一个简单的应用程序来管理学生名单。
在 MainActivity 中,我们可以将学生添加到列表中。单击添加的 ListView
项目,打开一个新的 activity,我们可以在其中编辑学生成绩。
我在列表中使用自定义 CursorAdapter,并使用自定义 SQLiteOpenHelper 数据库来处理数据库。
在 MainActivity:onResume()
我检查数据库是否已更改,如果是则调用 changeCursor()
。
调试时,似乎设置了数据库更改标志,但对 changeCursor()
的调用不会使用新数据
ListView
示例
- 添加
Adi,10
- 单击列表项 -> 新建 activity ->
grade
编辑为20
-> 点击返回按钮 - 期待看到
Adi,20
,仍然看到Adi,10
这是我的相关代码:
主要Activity:
public class MainActivity extends AppCompatActivity {
private SqlDbHelper mDB;
private SQLAdapter mAdapter;
@Override
protected void onResume() {
super.onResume();
if(mDB.isDbChanged()) {
mAdapter.changeCursor(mDB.getAllRows());
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Init fields & needed views */
mDB = new SqlDbHelper(getApplicationContext());
mAdapter = new SQLAdapter(getApplicationContext(), mDB.getAllRows(), false);
final ListView lvStudents = findViewById(R.id.lv_students);
final EditText etName = findViewById(R.id.et_name);
final EditText etGrade = findViewById(R.id.et_grade);
/* Listen to ADD BUTTON clicks */
findViewById(R.id.button_add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
insertNewRecord(etName.getText().toString(), etGrade.getText().toString());
etName.setText("");
etGrade.setText("");
}
});
/* Set adapter to LV, Listen to list item clicks */
lvStudents.setAdapter(mAdapter);
lvStudents.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent listItemIntent = new Intent(getApplicationContext(), ListItemActivity.class);
/* Put needed info in the Intent extra */
listItemIntent.putExtra(SqlDbHelper.KEY_ID, l);
listItemIntent.putExtra(SqlDbHelper.KEY_NAME,
((TextView)view.findViewById(R.id.tv_name)).getText().toString());
listItemIntent.putExtra(SqlDbHelper.KEY_GRADE,
Integer.parseInt( ((TextView)view
.findViewById(R.id.tv_grade))
.getText().toString() ));
startActivity(listItemIntent);
}
});
}
private void insertNewRecord(final String name, final String grade) {
/* Add the new student to the DB */
mDB.addStudent(name, gradeInt);
mAdapter.changeCursor(mDB.getAllRows());
}
}
SQL适配器:
final class SQLAdapter extends CursorAdapter {
private LayoutInflater mInflater;
public SQLAdapter(Context context, Cursor c, boolean autoRequery) {
super(context, c, autoRequery);
mInflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
return mInflater.inflate(R.layout.lv_line, viewGroup, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
final String name = cursor.getString(cursor.getColumnIndex(SqlDbHelper.KEY_NAME));
final int grade = cursor.getInt(cursor.getColumnIndex(SqlDbHelper.KEY_GRADE));
view.findViewById(R.id.ll_line).setBackgroundColor(Color.RED);
((TextView)view.findViewById(R.id.tv_name)).setText(name);
((TextView)view.findViewById(R.id.tv_grade)).setText(String.valueOf(grade));
}
}
SqlDbHelper:
final class SqlDbHelper extends SQLiteOpenHelper {
// some static string variables //
/* Flag indicating DB was changed (by editStudent) -
* For indication to MainActivity to refresh its list onResume */
private static boolean mDbChanged;
public SqlDbHelper(Context context) {
super(context, DB_NAME, null, VERSION);
mDbChanged = false;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
/* Create sql command to create new table */
StringBuilder sql = new StringBuilder();
sql.append("CREATE TABLE " + TABLE_NAME + " (")
.append(KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,")
.append(KEY_NAME + " TEXT,")
.append(KEY_GRADE + " INT")
.append(")");
Log.d(TAG, "Query to form table: " + sql.toString());
sqLiteDatabase.execSQL(sql.toString());
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {}
public void addStudent(final String name, final int grade) {
ContentValues cv = new ContentValues();
cv.put(KEY_NAME, name);
cv.put(KEY_GRADE, grade);
getWritableDatabase().insert(TABLE_NAME, null, cv);
}
public void editStudent(final long id, final int grade) throws IllegalArgumentException {
StringBuilder updateQuery = new StringBuilder();
updateQuery.append("UPDATE " + TABLE_NAME)
.append(" SET " + KEY_GRADE)
.append(" = " + grade)
.append(" WHERE " + KEY_ID)
.append(" = " + id);
Log.d(TAG, "Query to edit: " + updateQuery.toString());
getWritableDatabase().execSQL(updateQuery.toString());
/* Indicate the change */
mDbChanged = true;
}
/**
* Aid method to get all rows in the DB
* @return Cursor pointing to the start of all rows
*/
public Cursor getAllRows() {
/* Turn change flag off, if method was called in order
* to refresh the main listview onResume */
if(mDbChanged) {
mDbChanged = false;
}
return getReadableDatabase().
rawQuery("SELECT * FROM " + TABLE_NAME, null);
}
public boolean isDbChanged() {
return mDbChanged;
}
}
ListItemActivity:
public class ListItemActivity extends AppCompatActivity {
private Intent mIntent;
private Button mButtonEdit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_item);
/* Get needed params for the view */
mIntent = getIntent();
mButtonEdit = findViewById(R.id.button_item_edit);
EditText etGrade = findViewById(R.id.et_item_grade);
/* Set the Student's Name & Grade */
final int grade = mIntent.getIntExtra(KEY_GRADE, -1);
((TextView)findViewById(R.id.tv_item_name)).
setText(mIntent.getStringExtra(KEY_NAME));
etGrade.setText(String.valueOf(grade));
/* Set on click listener for the edit button */
mButtonEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SqlDbHelper db = new SqlDbHelper(getApplicationContext());
db.editStudent(mIntent.getLongExtra(KEY_ID, -1), grade);
}
});
}
}
问题出在 mButton onClick()
方法的 ListItemActivity
中。
我没有使用在 EditText 框中输入的新成绩来更新数据库,而是使用了一个旧的 grade
变量来保存在 onCreate()
中获得的旧成绩值。
花了一些时间才弄明白,这是因为 activity 中屏幕上的等级确实更改为新等级,尽管数据库已更新为旧等级。
解法:
中LastItemActivity::onClick
,改
db.editStudent(mIntent.getLongExtra(KEY_ID, -1), grade);
到
db.editStudent(mIntent.getLongExtra(KEY_ID, -1), Integer.parseInt(etGrade.getText().toString()))