Android:如何在删除数据库行后重新查询Cursor以刷新ListView?

时间:2013-06-05 10:43:30

标签: android listview cursor android-sqlite simplecursoradapter

这可能是一个noob问题,但我对所有这些SQLite-Database-Cursor-Adapter-ListView-Do-It-Properly-Stuff都很新。

我有什么:

在我的MainActivity我有一个ListView。我使用SQLite database并使用扩展ListView的自定义适配器填充SimpleCursorAdapter。通过点击ActionBar中的项目,我激活了Contextual Action Mode。到目前为止一切正常。

我想要的是什么:

点击ListView item中的某个图标,应删除相应的数据库行,并刷新ListView

我的问题:

如何正确刷新CursorListView?当我在cursor.requery()中不使用OnClickListener并使用cursor = dbm.getIOIOSensorsCursor()时,我会在行下面的几行中找到CursorIndexOutOfBoundsException

int state = cursor.getInt(cursor.getColumnIndex(IOIOSensorSchema.STATE));

我的应用程序崩溃,但重新加载后,数据库已被删除,相应的ListView item已消失。

我认为崩溃必须与get _position方法中的getView有关,因为_positionfinal。但是,当我使用cursor.requery()时,一切正常。

但是这个方法已被弃用,它的文档说“不要使用它......”。我是正确编码的朋友(我还是一个初学者,想要学习正确的编码而不是快速和肮脏),并想知道如何正确编码。我不知道它是否重要,但我只在我的(非常快)Nexus 4上测试我的应用程序。Cursor刷新public class IOIOSensorCursorAdapterCam extends SimpleCursorAdapter { static class ViewHolder { ImageView stateIV, removeIV; TextView nameTV, pinNumberTV, feedIDTV, freqTV; } private Context ctx; private Cursor cursor; private IodDatabaseManager dbm; public IOIOSensorCursorAdapterCam(Context _context, int _layout, Cursor _cursor, String[] _from, int[] _to, int _flags) { super(_context, _layout, _cursor, _from, _to, _flags); ctx = _context; cursor = _cursor; dbm = new IodDatabaseManager(_context); } @Override public View getView(final int _position, View _convertView, ViewGroup _parent) { ViewHolder holder = null; LayoutInflater inflater = (LayoutInflater) ctx .getSystemService(Context.LAYOUT_INFLATER_SERVICE); // There is no view at this position, we create a new one. In this case // by inflating an xml layout. if (_convertView == null) { // Inflate a layout _convertView = inflater.inflate(R.layout.listview_item_sensor_cam, null); holder = new ViewHolder(); holder.stateIV = (ImageView) _convertView .findViewById(R.id.stateImageView); holder.nameTV = (TextView) _convertView .findViewById(R.id.sensorNameTextView); holder.pinNumberTV = (TextView) _convertView .findViewById(R.id.sensorPinNumberTextView); holder.feedIDTV = (TextView) _convertView .findViewById(R.id.sensorFeedIDTextView); holder.freqTV = (TextView) _convertView .findViewById(R.id.sensorFrequencyTextView); holder.removeIV = (ImageView) _convertView .findViewById(R.id.removeImageView); _convertView.setTag(holder); } // We recycle a View that already exists. else { holder = (ViewHolder) _convertView.getTag(); } // Set an OnClickListener to the "Delete Icon" holder.removeIV.setOnClickListener(new OnClickListener() { @SuppressWarnings("deprecation") @Override public void onClick(View _view) { cursor.moveToPosition(_position); // Delete sensor from database here int sensorID = cursor.getInt(cursor .getColumnIndex(IOIOSensorSchema.SENSOR_ID)); dbm.deleteIOIOSensor(sensorID); // This leads to a "CursorIndexOutOfBoundsException" and cannot // be used to refresh the ListView // cursor = dbm.getIOIOSensorsCursor(); // Refresh ListView cursor.requery(); notifyDataSetChanged(); } }); cursor.moveToPosition(_position); if (cursor.getCount() > 0) { int state = cursor.getInt(cursor .getColumnIndex(IOIOSensorSchema.STATE)); if (state == 0) { holder.stateIV.setImageResource(R.drawable.av_play_over_video); holder.stateIV.setColorFilter(ctx.getResources().getColor( R.color.hint_lighter_gray)); // _convertView.setAlpha((float) 0.5); holder.nameTV.setTextColor(ctx.getResources().getColor( R.color.hint_darker_gray)); } else { holder.stateIV.setImageResource(R.drawable.av_pause_over_video); holder.stateIV.setColorFilter(ctx.getResources().getColor( android.R.color.holo_green_light)); // _convertView.setAlpha((float) 1); holder.nameTV.setTextColor(ctx.getResources().getColor( android.R.color.black)); } // Set the sensor's name to the according TextView String sensorName = cursor.getString(cursor .getColumnIndex(IOIOSensorSchema.NAME)); holder.nameTV.setText(sensorName); // Set the sensor's pin number to the according TextView int pinNumber = cursor.getInt(cursor .getColumnIndex(IOIOSensorSchema.PIN_NUMBER)); holder.pinNumberTV.setText("" + pinNumber); // Set the sensor's feed ID to the according TextView int feedID = cursor.getInt(cursor .getColumnIndex(IOIOSensorSchema.FEED_ID)); holder.feedIDTV.setText("" + feedID); // Set the sensor's frequency to the according TextView int frequency = cursor.getInt(cursor .getColumnIndex(IOIOSensorSchema.FREQUENCY)); int timeUnit = cursor.getInt(cursor .getColumnIndex(IOIOSensorSchema.TIME_UNIT)); String frequencyTextViewText = ""; switch (timeUnit) { case IodIOIOSensor.TIME_UNIT_MINUTES: frequencyTextViewText = frequency + " min"; break; case IodIOIOSensor.TIME_UNIT_HOURS: frequencyTextViewText = frequency + " h"; break; default: frequencyTextViewText = frequency + " sec"; break; } holder.freqTV.setText(frequencyTextViewText); } return _convertView; } } 似乎没有任何问题,但我不知道它是否会起作用设备较慢。如果它对您很重要,我的数据库将包含大约10-20行,大约12列。我想这是一个非常小的数据库。

以下是我的自定义适配器的相关代码:

// Set an OnClickListener to the "Delete Icon"
holder.removeIV.setOnClickListener(new OnClickListener()
{
    @Override
    public void onClick(View _view)
    {
    cursor.moveToPosition(_position);

    // Delete sensor from database here
    int sensorID = cursor.getInt(cursor
        .getColumnIndex(IOIOSensorSchema.SENSOR_ID));
    dbm.deleteIOIOSensor(sensorID);

    Toast.makeText(ctx, R.string.toast_sensor_deleted,
        Toast.LENGTH_SHORT).show();

    // Refresh ListView
    cursor = dbm.getIOIOSensorsCursor();
    swapCursor(cursor);

    notifyDataSetChanged();
    }
});

修改

这是我在实施解决方案后来自OnCickListener的相关代码:

{{1}}

1 个答案:

答案 0 :(得分:15)

  

如何正确刷新我的光标和ListView?

通过再次运行代码获取Cursor,使用您用于创建原始Cursor的代码(请在后台线程中),“刷新[your] Cursor”。您可以通过调用ListView上的changeCursor()swapCursor()来刷新CursorAdapter

相关问题