I have a simple app to manage students list.
In MainActivity, we can add a student to the list. clicking on an added ListView
item, opens up a new activity, in which we can edit the students grade.
I'm using custom CursorAdapter with my list, and custom SQLiteOpenHelper DB to handle the DB.
On MainActivity:onResume()
I check if the db was changed, and call changeCursor()
if so.
When debugging, it seems the DB change flag is set, but the call to changeCursor()
doesn't refresh the ListView
with new data
EXAMPLE
Adi,10
grade
edited to 20
-> hit back buttonAdi,20
, still sees Adi,10
Here's my relevant code:
Main 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());
}
}
SQLAdapter:
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);
}
});
}
}
Problem was in ListItemActivity
in mButton onClick()
method.
Instead of updating the db with new grade entered on the EditText box, I've used an old grade
variable which holds the old value of the grade, obtained in onCreate()
.
Took some time to figure it out, this since due to the fact that the grade on screen in this activity, did change to the new grade, although db was updated with old one.
Solution:
In LastItemActivity::onClick
, Change
db.editStudent(mIntent.getLongExtra(KEY_ID, -1), grade);
To
db.editStudent(mIntent.getLongExtra(KEY_ID, -1), Integer.parseInt(etGrade.getText().toString()))