5

私のアプリケーションでは、十分にクリックした後、次のエラーが発生します。

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

私が持っているのは、各タブのコンテンツとして ListActivity を持つタブ アクティビティ (私の MainActivity) です。各 ListActivity の onCreate 内で、そのリストに表示されるデータを表すカーソルを取得します。

各リストの onListItemClick も別のアクティビティを作成するため、リスト内の項目をクリックすると、その項目に関する詳細情報が新しい画面に表示されます。一貫性がありませんが、これらの新しいアクティビティを十分にクリックした後、または新しいアクティビティから ListView に戻ると、プログラムがクラッシュします。

私の問題の解決策を探し回っているときに、registerDataSetObserver に出くわしましたが、それがすべての答えではないようです。また、ドキュメントを見つけるのに苦労しているため、完全に理解しているとは言えません。私は、両方の ListViews が使用し、そこのカーソルで registerDataSetObservers を呼び出したカスタム ListAdapter を持っています。

ListActivities の 1 つとカスタム ListAdapter クラスから関連するコードを添付しました。


リスト アクティビティ。私はこれらのうちの 2 つを持っていますが、異なるデータベース クエリから作成された異なるカーソルを持っていることを除いて、ほとんど同じです。

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 で新しいアクティビティを起動しているため、それが起こっていると思います。

4

1 に答える 1

6

requery()無効になったときにカーソルを呼び出したいと思います。でそれを行うことができますonInvalidated()

于 2010-06-08T21:06:05.347 に答える