StaleDataException:访问关闭的游标

发布于 2024-09-04 09:06:30 字数 3420 浏览 4 评论 0原文

在我的应用程序中,经过足够的点击后,我收到此错误:

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 类的相关代码。


列表活动。我有其中两个,几乎相同,只是它们都具有从不同数据库查询创建的不同游标:

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 中启动新活动。

In my application, after enough clicking around, I get this error:

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

What I have is a Tab Activity (my MainActivity), which has a ListActivity as the contents for each tab. Inside the onCreate for each ListActivity I get a cursor that represents the data to be displayed in that list.

The onListItemClick for each list also creates another activity, so clicking on an item in the list will show more information about that item in a new screen. It's inconsistent, but after enough clicking into these new activities, or going back to the ListView from a new activity, the program crashes.

In searching around for a solution to my problem, I did stumble upon registerDataSetObserver, but it doesn't seem to be the whole answer. I am also having trouble finding documentation on it, so I'm not sure I fully understand it. I have a custom ListAdapter that both my ListViews use and have called registerDataSetObservers on the cursors there.

I have attached the relevant code from one of my ListActivities and from my custom ListAdapter class.


The ListActivity. I have two of these, almost identical, except they both have different cursors created from different database queries:

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

    }

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

Should I just have MyDataSetObserver catch the exception and move on? I'd like a more robust solution than that if possible. Or is there some other way I could rearrange my program so that the staleDataException doesn't occur (as often)? I believe that it is happening because I am launching the new activity in my onListItemClick.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

燃情 2024-09-11 09:06:30

我相信当它失效时你想在游标上调用 requery() 。您可以在 onInvalidated() 中执行此操作。

I believe when it's invalidated you want to call requery() on the cursor. You could possibly do that in onInvalidated().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文