2011-12-14 9 views
8

उपयोगकर्ता द्वारा चुने गए आइटम की सामग्री के साथ एक नई गतिविधि खोलने के बाद मूल ListActivity पर लौटने पर मुझे यह अपवाद मिल रहा है। यह केवल आइस क्रीम सैंडविच पर होता है।इस अपवाद उदाहरण को ट्रिगर कर रहा है: "java.lang.IllegalArgumentException: पर्यवेक्षक शून्य है।" और यह कैसे बच सकता है?

यह पता लगाने है:

java.lang.IllegalArgumentException: The observer is null. 
    at android.database.Observable.unregisterObserver(Observable.java:59) 
    at android.widget.BaseAdapter.unregisterDataSetObserver(BaseAdapter.java:42) 
    at android.widget.AbsListView.onDetachedFromWindow(AbsListView.java:2373) 
    at android.view.View.dispatchDetachedFromWindow(View.java:9756) 
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2274) 
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) 
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) 
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) 
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) 
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) 
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) 
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) 
    at android.view.ViewRootImpl.dispatchDetachedFromWindow(ViewRootImpl.java:2227) 
    at android.view.ViewRootImpl.doDie(ViewRootImpl.java:3679) 
    at android.view.ViewRootImpl.die(ViewRootImpl.java:3667) 
    at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:320) 
    at android.view.WindowManagerImpl$CompatModeWrapper.removeViewImmediate(WindowManagerImpl.java:139) 
    at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3144) 
    at android.app.ActivityThread.access$1200(ActivityThread.java:122) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1179) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:137) 
    at android.app.ActivityThread.main(ActivityThread.java:4340) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:511) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
    at dalvik.system.NativeStart.main(Native Method) 

मेरी कोड में से कोई भी ढेर में बताया गया है, तो यह वास्तव में मुझे puzzling है और मैं घटना एक गंदा पकड़ नहीं कर सकता: मैं एक दर्ज की कर रहा हूँ/

गुमनाम DataSetObserver केवल तभी जब गतिविधि बनाई जाती है। इसके अलावा गतिविधि को एक गतिविधि समूह के अंदर एम्बेड किया गया है (जिसे 4.0 में बहिष्कृत किया गया है लेकिन अभी भी इसे अनुरक्षित करना चाहिए, मैं उम्मीद कर रहा था)।

क्या किसी को भी नए ओएस के साथ यह समस्या है?

अग्रिम धन्यवाद।


अद्यतन:

ठीक है, लगता है, हालांकि यकीन नहीं है कि यह कैसे हल करने के लिए मैं समस्या के स्रोत मिल गया।

AbsListView.onDetachedFromWindow() अंदर हम इस राशि:

if (mAdapter != null) { // Android code added on ICS 
    mAdapter.unregisterDataSetObserver(mDataSetObserver); 
    mDataSetObserver = null; 
} 

कौन सा, एक बार पर्यवेक्षक अपंजीकृत है, यह निरस्त माना जाता है। समस्या यह है कि, किसी कारण से, आईसीएस में इसे दो बार बुलाया जाता है। मुझे लगता है कि यह एक हटाने आपरेशन अंदर अशक्त मापदंडों के लिए जाँच करने के लिए के रूप में वे Observable वर्ग में क्या थोड़ा पागल है:

public void unregisterObserver(T observer) { // Android code 
    if (observer == null) { 
     throw new IllegalArgumentException("The observer is null."); 
    } 
    synchronized(mObservers) { 
     int index = mObservers.indexOf(observer); 
     if (index == -1) { 
      throw new IllegalStateException("Observer " + observer + " was not registered."); 
     } 
     mObservers.remove(index); 
    } 
} 

क्यों वे सिर्फ इसे अनदेखा नहीं है ¬¬ वे सिर्फ ऐसा कर सकता है और काम करेगा साथ ही (या बेहतर):

public void unregisterObserver(T observer) { // Android code 
    synchronized(mObservers) { 
     mObservers.remove(observer); 
    } 
} 
+0

क्या आप अपना गतिविधि कोड पोस्ट कर सकते हैं और जब आप कहें कि वापस लौटने का मतलब है कि बैक बटन दबाकर? – zode64

+0

हाँ, लौटने से मेरा मतलब है कि बैक बटन दबाकर। गतिविधि के लिए कोड यहां दिया गया है (http://pastebin.com/68BzJcc1), लेकिन जैसा कि मैंने उल्लेख किया है, स्टैक में मेरे कोड में से कोई भी नहीं दिखाया गया है। – pablisco

+0

मैंने एक बग रिपोर्ट भर दी है: http://code.google.com/p/android/issues/detail?id=22946 हालांकि समाधान होना चाहिए: / – pablisco

उत्तर

11

यह समस्या एंड्रॉयड 4.0.3 में पेश किया गया था, और प्रत्यक्ष वर्ग जब एक पर्यवेक्षक एक अपवाद फेंक में बदल गया था एक बार से अधिक जारी किया गया था। इसे एक बग के रूप में रिपोर्ट किया गया है और यहां पढ़ा जा सकता है: http://code.google.com/p/android/issues/detail?id=22946

इस समस्या के आसपास काम करने का सबसे आसान तरीका अंतर्निहित एडाप्टर को लपेटना और एकाधिक रिलीज़ से बचना है।

@Override 
public void unregisterDataSetObserver(DataSetObserver observer) { 
    if (observer != null) { 
    super.unregisterDataSetObserver(observer); 
    } 
} 

लेकिन यह सभी मामलों में काम नहीं करेगा, उदाहरण के लिए ExpandableListView में एक आंतरिक एडाप्टर है जिसे एक्सेस नहीं किया जा सकता है। यहां एक वैकल्पिक समाधान ExpandableListView को लपेटना और अपवाद पकड़ना है। यह समाधान मेरे लिए काम करता है, और मुझे अभी तक कोई दुष्प्रभाव नहीं मिला है।

public class PatchedExpandableListView extends ExpandableListView { 

    public PatchedExpandableListView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    } 

    @Override 
    protected void onDetachedFromWindow() { 
    try { 
     super.onDetachedFromWindow(); 
    } catch(IllegalArgumentException iae) { 
     // Workaround for http://code.google.com/p/android/issues/detail?id=22751 
    } 
    } 
} 
3

मैं सोच रहा हूँ कि मेरी कक्षाओं में से कोई भी पता लगाने में उल्लेख किया गया था की मूर्खतापूर्ण गलती की है, लेकिन LoadingDataView उनमें से एक है। यह मूल ट्रेस में नहीं दिखाया जाता है लेकिन दूसरा जो संबंधित था।

उस वर्ग के अंदर एक गुमनाम ArrayAdapter कि था, जहां घटना तो हो रहा है मैं चारों ओर एक काम के रूप में इस जोड़ा है:

@Override 
public void unregisterDataSetObserver(DataSetObserver observer) { 
    if (observer != null) { 
     super.unregisterDataSetObserver(observer); 
    } 
} 

और यह अब काम करने के लिए लगता है, हालांकि मैं अभी भी यकीन है कि क्यों यह नहीं कर रहा हूँ विधि दो बार बुलाया गया था।

हालांकि, मैं के रूप में ज्यादा के रूप में मैं कर सकते हैं टुकड़े का उपयोग करने के लिए जा रहा हूँ पर अभी के लिए;)

संबंधित मुद्दे