這可能是一個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
方法,因爲_position
是final
。但是,當我使用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();
}
});
工程就像一個魅力。非常感謝!所以我只是缺少'swapCursor(cursor);'!我在我的文章中添加了解決方案。 – kaolick
你提到'在後臺線程,請'。我很好奇,如果你對'AsyncTask'和'Loader'有什麼想法? – theblang
@mattblang:如果您因爲其他原因恰好讓您的數據由「ContentProvider」提供服務,請使用「CursorLoader」。否則,只需使用一個'AsyncTask',恕我直言。 – CommonsWare