2013-06-05 121 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

相關問題