En mi solicitud, después de bastante clic alrededor, me sale este error:StaleDataException: Area cursor
06-08 19:47:59.967: ERROR/AndroidRuntime(2429): java.lang.RuntimeException: Unable to pause activity {com.MYAPP.app/com.MYAPP.app.MainActivity}: android.database.StaleDataException: Access closed cursor
Lo que tengo es una actividad Tab (mi MainActivity), que tiene una ListActivity como el contenido de cada lengüeta. Dentro de onCreate para cada ListActivity, obtengo un cursor que representa los datos que se mostrarán en esa lista.
El onListItemClick para cada lista también crea otra actividad, por lo que al hacer clic en un elemento de la lista se mostrará más información sobre ese elemento en una nueva pantalla. No es consistente, pero después de hacer clic en estas nuevas actividades o volver al ListView de una nueva actividad, el programa se bloquea.
Al buscar una solución a mi problema, tropecé con registerDataSetObserver, pero no parece ser la respuesta completa. También tengo problemas para encontrar documentación al respecto, por lo que no estoy seguro de entenderlo por completo. Tengo un ListAdapter personalizado que mis ListViews usan y han llamado a registerDataSetObservers en los cursores allí.
He adjuntado el código correspondiente de una de mis ListActivities y de mi clase de ListAdapter personalizada.
ListActivity. Tengo dos de estos, casi idéntico, excepto que ambos tienen diferentes cursores creados a partir de diferentes consultas de bases de datos:
import com.MYAPP.app.listmanager.DeviceListAdapter;
public class AllSensorsActivity extends ListActivity{
private DeviceListAdapter AllList;
private DbManager db;
protected Cursor AllCur;
protected Cursor AllSensors;
private static final String TAG = "AllSensorsActivity";
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.e(TAG, "Calling All onCreate");
db = new DbManager(this);
db.open();
AllCur = db.fetchAllDevices();
startManagingCursor(AllCur);
AllSensors = db.fetchAllSensors();
startManagingCursor(AllSensors);
AllList = new DeviceListAdapter(this, AllCur, AllSensors);
setListAdapter(AllList);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id){
String device_name = (String) ((DeviceListAdapter)getListAdapter()).getItem(position);
String sensor_string = ((DeviceListAdapter)getListAdapter()).getSensors(id);
Intent i = new Intent(this, SensorActivity.class);
Bundle bundle = new Bundle();
bundle.putString("NAME", device_name);
i.putExtras(bundle);
bundle.putString("SENSORS", sensor_string);
i.putExtras(bundle);
this.startActivity(i);
}
El ListAdapter personalizado:
public class DeviceListAdapter extends BaseAdapter {
private static final String TAG = "DeviceListAdapter";
private Context mContext;
private Cursor mSensors;
private Cursor mDevices;
protected MyDataSetObserver sensors_observer;
protected MyDataSetObserver devices_observer;
public DeviceListAdapter(Context context, Cursor devices, Cursor sensors){
mContext = context;
mDevices = devices;
mSensors = sensors;
sensors_observer = new MyDataSetObserver();
mSensors.registerDataSetObserver(sensors_observer);
devices_observer = new MyDataSetObserver();
mDevices.registerDataSetObserver(devices_observer);
}
// ... more functions and stuff that are not relevant go down here...
}
private class MyDataSetObserver extends DataSetObserver {
public void onChanged(){
Log.e(TAG, "CHANGED CURSOR!");
}
public void onInvalidated(){
Log.e(TAG, "INVALIDATED CURSOR!");
}
}
¿Debo tener MyDataSetObserver detectar la excepción y seguir adelante ? Me gustaría una solución más sólida que eso si es posible. ¿O hay alguna otra forma en que pueda reorganizar mi programa para que la excepción staleDataException no ocurra (como a menudo)? Creo que está sucediendo porque estoy lanzando la nueva actividad en mi onListItemClick.
Cuando puse cursor.requery() en onInvalidated(), no pude bloquearlo, no importa cuánto lo intenté. ¡Horray! Pero pensé que startManagingCursor() se ocuparía de las consultas para mí, ¿es porque pause la actividad en la que se llama startManagingCursor()? – Aurora
No estoy seguro, pero si lo desea, probablemente encuentre dónde se invalida imprimiendo un seguimiento de pila en onInvalidated. –
requery está en desuso http://developer.android.com/reference/android/database/Cursor.html#requery() – AndroidGecko