Android: comment requérir un Cursor pour actualiser ListView après avoir supprimé la ligne de base de données?

Cela pourrait être une question de noob, mais je suis tout à fait nouveau pour tout ce SQLite-Database-Cursor-Adapter-ListView-Do-It-Properly-Stuff.

Ce que j'ai:

  • Longueur de la barre de défilement android avec différentes tailles d'objet
  • Cursor Wrapping / Unwrapping dans ContentProvider
  • Comment vérifier si un curseur est vide?
  • Devrait-il y avoir un SQLiteOpenHelper pour chaque table dans la base de données?
  • Gesture Listener onFling Not Aging Consistant
  • Qu'est ce que android.R.layout.simple_list_item_1?
  • Dans ma MainActivity j'ai un ListView . J'utilise une SQLite database et ListView le ListView avec un adaptateur personnalisé étendant SimpleCursorAdapter . En cliquant sur un élément dans mon ActionBar Contextual Action Mode . Tout fonctionne jusqu'à présent.

    Ce que je veux:

    En cliquant sur une certaine icône dans mon ListView item la ligne de base de données doit être supprimée et ListView doit être actualisée.

    Ma question:

    Comment puis-je actualiser mon Cursor et mon ListView correctement? Lorsque je n'utilise pas cursor.requery() dans mon OnClickListener et que j'utilise cursor = dbm.getIOIOSensorsCursor() je reçois un CursorIndexOutOfBoundsException quelques lignes ci-dessous à la ligne

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

    L'application échoue, mais après le rechargement, la base de données a été supprimée et l' ListView item disparu.

    Je suppose que le crash doit avoir quelque chose à voir avec _position dans get getView method parce que _position est final . Cependant, lorsque j'utilise cursor.requery() tout fonctionne comme il se doit.

    Mais cette méthode est obsolète et sa documentation indique "Ne pas utiliser cette …" . Je suis un ami de codage correctement (je suis toujours un débutant et je veux apprendre à coder le bon chemin et pas rapide et sale) et je veux savoir comment le faire correctement. Je ne sais pas si c'est important, mais je teste mon application uniquement sur mon (très rapide) Nexus 4. Il semble qu'il n'y ait pas de problèmes pour rafraîchir le Cursor assez rapidement, mais je me demande s'il fonctionnera sur des périphériques plus lents. Dans le cas où il est important pour vous, ma base de données contiendra environ 10-20 lignes avec environ 12 colonnes. Je suppose que c'est une très petite base de données.

    Voici le code pertinent de mon adaptateur personnalisé:

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

    Modifier:

    Voici mon code pertinent de OnCickListener après la mise en œuvre de la solution:

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

    One Solution collect form web for “Android: comment requérir un Cursor pour actualiser ListView après avoir supprimé la ligne de base de données?”

    Comment puis-je actualiser mon Cursor et mon ListView correctement?

    Vous "actualisez [votre] Cursor" en exécutant votre code à nouveau pour obtenir le Cursor , en utilisant le code que vous avez utilisé pour créer le Cursor original (sur un fil d'arrière-plan, s'il vous plaît). Vous actualisez votre ListView en appelant changeCursor() ou swapCursor() sur CursorAdapter .

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.