2013-06-05 79 views
9

这可能是一个noob问题,但我对这个SQLite-Database-Cursor-Adapter-ListView-Do-It-Properly-Stuff都很新颖。Android:删除数据库行后如何重新查询游标以刷新ListView?

我有什么:

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

我想要什么:

通过点击特定的图标在我ListView item的根据数据库行应被删除,ListView应该被刷新。

我的问题:

如何刷新我的Cursor和我ListView正常吗?当我没有在我的OnClickListener使用cursor.requery()和使用cursor = dbm.getIOIOSensorsCursor(),而不是我在该行

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

我的应用程序崩溃,但它重装数据库已被删除,并根据后ListView item是得到低于CursorIndexOutOfBoundsException几排不见了。

我想碰撞肯定与_position有关,得到getView方法,因为_positionfinal。但是,当我使用cursor.requery()时,一切正常。

但是这种方法已被弃用,它的文档说“不要使用这个...”。我是一个正确编码的朋友(我仍然是一名初学者,并且希望学会正确的编码方式,而不是快速和肮脏的),并且想知道如何做到这一点。我不知道它是否很重要,但我只在我的(非常快)Nexus 4上测试我的应用程序。似乎没有任何问题快速刷新Cursor,但我不知道它是否可以在较慢的设备上工作。万一它对你很重要,我的数据库将包含大约10-20行,大约12列。我想这是一个非常小的数据库。

这里是我的自定义接口的相关代码:

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

编辑:

下面是从OnCickListener实施解决方案后,我的相关代码:

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

回答

15

如何刷新我的C ursor和我的ListView正确吗?

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

+0

工程就像一个魅力。非常感谢!所以我只是缺少'swapCursor(cursor);'!我在我的文章中添加了解决方案。 – kaolick

+0

你提到'在后台线程,请'。我很好奇,如果你对'AsyncTask'和'Loader'有什么想法? – theblang

+0

@mattblang:如果您因为其他原因恰好让您的数据由“ContentProvider”提供服务,请使用“CursorLoader”。否则,只需使用一个'AsyncTask',恕我直言。 – CommonsWare

相关问题