2010-06-08 72 views
5

在我的应用程序,足够的点击左右后,我得到这个错误:StaleDataException:访问关闭的游标

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 

我已经是一个选项卡活动(我的MainActivity),其中有一个ListActivity为每个内容标签。在每个ListActivity的onCreate内部,我得到一个表示要在该列表中显示的数据的游标。

的onListItemClick每个列表也创造了另一项活动,所以点击列表中的项目将显示有关的新屏幕项目的更多信息。这是不一致的,但是在足够的点击这些新的活动之后,或者从一个新的活动返回到ListView之后,程序就会崩溃。

在搜索绕了解决我的问题,我没有在registerDataSetObserver绊倒,但它似乎并没有被全部答案。我也很难找到关于它的文档,所以我不确定我完全理解它。我有一个自定义的ListAdapter,它们都是我的ListView使用的,并在那里的游标上调用了registerDataSetObservers。

我从ListActivities之一,从我的自定义ListAdapter类连接相关的代码。


ListActivity。我有两个的这些,几乎是相同的,只是它们都具有不同的数据库查询创建不同的游标:

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

    } 

定制ListAdapter:

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!"); 
    } 
} 

我是不是应该有MyDataSetObserver捕获异常,并继续前进?如果可能的话,我想要一个更强大的解决方案。还是有其他方式可以重新安排我的程序,使staleDataException不会发生(通常)?我相信这是因为我在我的onListItemClick中启动了新的活动。

回答

6

我相信,当它是无效的,你要调用requery()上的光标。你可以在onInvalidated()中做到这一点。

+1

当我把在cursor.requery()在onInvalidated(),我不能崩溃了,不管我如何努力。 Horray! 但我虽然startManagingCursor()会照顾我的请求 - 是因为我暂停了startManagingCursor()被调用的活动? – Aurora 2010-06-08 21:21:00

+0

我不确定,但是如果你想要的话,你可以通过在onInvalidated中打印堆栈跟踪来找到无效的地方。 – 2010-06-09 03:33:34

+4

重新查询已被弃用http://developer.android.com/reference/android/database/Cursor.html#requery() – AndroidGecko 2012-09-19 15:39:27