2012-11-16 10 views
27

मैंने पढ़ा है कि यूआई प्रस्तुत करने वाले टुकड़ों पर .setOnRetainInstance(true) सेटिंग मेमोरी लीक हो सकती है।यूआई और मेमोरी लीक के साथ बनाए गए टुकड़े

क्या कोई यह बता सकता है कि यह क्यों और कैसे होगा? मुझे कहीं भी विस्तृत स्पष्टीकरण नहीं मिला।

+0

बस विषय दस्तावेज़ के लिए, यहाँ समान सूत्र हैं: http://stackoverflow.com/q/11182180/693752 – Snicolas

+0

http: // stackoverflow। कॉम/क्यू/11160412/693752 – Snicolas

उत्तर

75

यूआई के साथ Fragment में आप अक्सर कुछ View एस को एक्सेस करने के लिए उदाहरण स्थिति के रूप में सहेजते हैं। उदाहरण के लिए आपके EditText का एक लिंक इसलिए आपको हर समय findViewById नहीं होना चाहिए।

समस्या यह है कि ViewActivity संदर्भ का संदर्भ रखता है। अब यदि आप View बनाए रखते हैं तो आप उस संदर्भ का संदर्भ भी बरकरार रखते हैं।

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

उदाहरण के बाद

से पता चलता है कि यह कैसे

public class LeakyFragment extends Fragment { 

    private View mLeak; // retained 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setRetainInstance(true); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     mLeak = inflater.inflate(R.layout.whatever, container, false); 
     return mLeak; 
    } 

    @Override 
    public void onDestroyView() { 
     super.onDestroyView(); 
     // not cleaning up. 
    } 
} 

है कि समस्या से छुटकारा पाने के लिए नहीं करने के लिए, आप onDestroyView में अपने यूआई के सभी संदर्भ स्पष्ट करने की जरूरत है। एक बार Fragment इंस्टेंस का पुन: उपयोग करने के बाद आपको onCreateView पर एक नया यूआई बनाने के लिए कहा जाएगा। यूआई को onDestroyView के बाद रखने में कोई बात नहीं है। यू का उपयोग नहीं किया जा रहा है।

इस उदाहरण में ठीक बस

@Override 
public void onDestroyView() { 
    super.onDestroyView(); 
    mLeak = null; // now cleaning up! 
} 

को onDestroyView बदल रहा है और View रों के लिए संदर्भ रखने के अलावा आपको स्पष्ट रूप से नहीं संदर्भ Activity रखना चाहिए (उदाहरण के लिए onAttach से - स्वच्छ onDetach पर) या किसी Context (जब तक यह Application संदर्भ नहीं है)।

+0

किसी भी विचार, कैसे संभालना है, शून्य पॉइंटर्स के पहाड़ के कारण यह हो सकता है? मेरे पास कई एनीमेशन श्रोताओं, धागे हैं, और प्रत्येक एक संदर्भ का उपयोग कर रहा है, जो DestroyView पर बाहर निकल जाता है। इसलिए जब भी मैं उन संदर्भों में से किसी एक का उपयोग करता हूं, तो मुझे पहले शून्य की जांच करनी पड़ती है। यह बहुत असुविधाजनक है। – Tamas

+1

@ टामास श्रोताओं, थ्रेड, ... जब तक वे 'गतिविधि' का संदर्भ या संदर्भ नहीं देते हैं, तब तक संदर्भित रखने के लिए सभी ठीक हैं। अगर उनके पास कुछ संदर्भ दिया गया है और गतिविधि का उपयोग करके इसे फिर से बनाया गया है, तो इसका कोई भी परिणाम वैध नहीं होगा, इसलिए आपको इसे किसी भी तरह अपडेट करना होगा। – zapl

+1

@ टामा उदाहरण: http://pastebin.com/8A18kMym आपको मूल रूप से 'ऑनएट'/'ऑनडेटा' को संदर्भ में संदर्भित करने वाली किसी भी चीज को प्रचारित करने की आवश्यकता है, और 'ऑनक्रेट व्यू'/'ऑनस्ट्रोयव्यू' को किसी भी चीज़ पर विचार करने के लिए संदर्भित करने की आवश्यकता है। – zapl

2

setRetainInstance(true) एक गतिविधि मनोरंजन के दौरान गतिशील टुकड़ों के उदाहरणों को बनाए रखने के लिए उपयोग किया जाता है, जैसे स्क्रीन रोटेशन या अन्य कॉन्फ़िगरेशन परिवर्तन। इसका मतलब यह नहीं है कि फ्रैगमेंट सिस्टम द्वारा हमेशा के लिए बनाए रखा जाएगा।

जब किसी गतिविधि को अन्य कारणों से समाप्त किया जाता है, जैसे उपयोगकर्ता गतिविधि को पूरा करने (यानी वापस दबाकर), फ्रैगमेंट कचरा संग्रहण के लिए योग्य होना चाहिए।

3

गतिविधि के साथ जोड़े गए कुछ ऑब्जेक्ट्स को बनाए रखने पर सावधान रहें।

सावधानी: यदि आप किसी भी वस्तु लौट सकते हैं करते समय, आपको एक वस्तु इस तरह के एक Drawable के रूप में गतिविधि से जुड़ा हुआ है कि, एक एडाप्टर, एक देखें या किसी अन्य उद्देश्य यह है कि संबद्ध पारित कभी नहीं करना चाहिए एक संदर्भ के साथ। यदि आप करते हैं, तो यह मूल गतिविधि उदाहरण के सभी विचारों और संसाधनों को रिसाव करेगा। (संसाधनों को लीक करने का मतलब है कि आपका आवेदन उन पर एक पकड़ रखता है और वे कचरे से एकत्र नहीं हो सकते हैं, इसलिए बहुत सारी याददाश्त खो सकती है।)

http://developer.android.com/guide/topics/resources/runtime-changes.html#RetainingAnObject

-7

आप onDestroy() overide और कचरा कलेक्टर आह्वान कर सकते हैं।

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    System.gc(); 
    System.gc(); 
} 
+3

20% मौका यह कभी भी काम करेगा: सुरक्षा के लिए पी 2 एक्स 'System.gc()'? कभी भी 'gc() 'पर भरोसा न करें –

0

"setRetainInstance" का उपयोग गतिविधि के पुनर्निर्मित होने पर खंड की स्थिति को बनाए रखने के लिए किया जाता है। आधिकारिक दस्तावेज़ीकरण के अनुसार: यदि हम "setRetainInstance" का उपयोग करते हैं, तो खंड के जीवन चक्र के 2 तरीके निष्पादित नहीं किए जाएंगे (ऑनक्रेट, ऑनस्ट्रोय)। हालांकि, खंड में निहित विचारों को फिर से बनाया जाएगा, और ऐसा इसलिए है क्योंकि जीवन चक्र "ऑनक्रेट व्यू" से निष्पादित किया जाएगा। इन मामलों में, यदि हमने "ऑनसेवस्टेंसस्टेट" में कुछ डेटा सहेजा है, तो हमें इसे "ऑनक्रेट" के बजाय "ऑनएक्टिविटी क्रिएटिव" में पूछना चाहिए।

Oficial जानकारी: https://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)

और जानकारी: https://inthecheesefactory.com/blog/fragment-state-saving-best-practices/en

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

  • कोई संबंधित समस्या नहीं^_^