【问题标题】:changeCursor() doesn't refresh ListViewchangeCursor() 不刷新 ListView
【发布时间】:2017-12-06 20:46:53
【问题描述】:

我有一个简单的应用来管理学生列表。

在 MainActivity 中,我们可以将学生添加到列表中。点击添加的ListView 项目,打开一个新活动,我们可以在其中编辑学生成绩。

我在列表中使用自定义 CursorAdapter,并使用自定义 SQLiteOpenHelper DB 来处理 DB。

MainActivity:onResume() 上,我检查数据库是否已更改,如果是,请致电changeCursor()

调试时,似乎设置了 DB 更改标志,但对 changeCursor() 的调用不会用新数据刷新 ListView

示例

  1. 添加Adi,10
  2. 单击列表项 -> 新活动 -> grade 编辑为 20 -> 点击返回按钮
  3. 期待看到Adi,20,仍然看到Adi,10

这是我的相关代码:

主要活动:

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);
            }
        });
    }
}

【问题讨论】:

  • 尝试将changeCursor更改为swapCursor
  • swapCursor 只是返回旧的光标,试试这个。发现问题,感谢尝试:)

标签: android cursor android-sqlite android-cursoradapter sqliteopenhelper


【解决方案1】:

问题出在ListItemActivity 中的mButton onClick() 方法中。

我没有使用在 EditText 框中输入的新等级来更新数据库,而是使用了旧的 grade 变量,它保存了在 onCreate() 中获得的等级的旧值。

花了一些时间才弄明白,这是因为该活动中屏幕上的成绩确实更改为新成绩,尽管数据库已更新为旧成绩。

解决方案:

LastItemActivity::onClick,更改

db.editStudent(mIntent.getLongExtra(KEY_ID, -1), grade);

db.editStudent(mIntent.getLongExtra(KEY_ID, -1), Integer.parseInt(etGrade.getText().toString()))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多