2010-06-08 10 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 है टैब। प्रत्येक सूची एक्टिविटी के लिए ऑनक्रेट के अंदर मुझे एक कर्सर मिलता है जो उस सूची में प्रदर्शित होने वाले डेटा का प्रतिनिधित्व करता है।

ऑनलिस्टस्टेम प्रत्येक सूची के लिए क्लिक करें एक और गतिविधि भी बनाता है, इसलिए सूची में किसी आइटम पर क्लिक करने से उस आइटम के बारे में अधिक जानकारी एक नई स्क्रीन में दिखाई देगी। यह असंगत है, लेकिन इन नई गतिविधियों में पर्याप्त क्लिक करने के बाद, या किसी नई गतिविधि से ListView पर वापस जाने के बाद, प्रोग्राम क्रैश हो जाता है।

मेरी समस्या के समाधान के लिए चारों ओर खोज में, मैं रजिस्टरडेटा ऑब्सर्वर पर ठोकर खाई, लेकिन यह पूरा जवाब प्रतीत नहीं होता है। मुझे दस्तावेज ढूंढने में भी परेशानी हो रही है, इसलिए मुझे यकीन नहीं है कि मैं इसे पूरी तरह से समझता हूं। मेरे पास एक कस्टम सूची एडाप्टर है जो मेरी सूची दृश्य दोनों का उपयोग करता है और वहां कर्सर पर RegisterDataSetObservers कहलाता है।

मैंने अपनी सूची में से एक से प्रासंगिक कोड और मेरी कस्टम सूची एडाप्टर क्लास से प्रासंगिक कोड संलग्न किया है।


सूची सक्रियता। मैं, इनमें से दो, लगभग समान है सिवाय इसके कि वे दोनों अलग डेटाबेस प्रश्नों से बनाए गए विभिन्न कर्सर है:

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

जब मैं कर्सर.रेक्वायरी() में invalidated() में डालता हूं, तो मैं इसे क्रैश नहीं कर सका, इससे कोई फर्क नहीं पड़ता कि मैंने कितनी मेहनत की। Horray! लेकिन हालांकि मैं शुरू करता हूं मैनेजिंग कर्सर() मेरे लिए जरूरी चीजों का ख्याल रखेगा - ऐसा इसलिए है क्योंकि मैंने उस गतिविधि को रोक दिया है जिसमें प्रारंभ करना कर्सर() कहा जाता है? – Aurora

+0

मुझे यकीन नहीं है, लेकिन यदि आप चाहते हैं कि आप शायद यह पता लगा सकें कि इसे अवांछित में एक स्टैक ट्रेस प्रिंट करके अवैध कहां प्राप्त किया जाता है। –

+4

आवश्यकता को बहिष्कृत किया गया है http://developer.android.com/reference/android/database/Cursor.html#requery() – AndroidGecko