12

साल पहले, जब मैंने को onActivityResult() कॉलबैक के अंदर करने की कोशिश की तो मैंने अपने ऐप्स में से एक में एक समस्या में भाग लिया। चारों ओर Googling, मैं this question and answer है, जो कहते हैं किक्या एक्टिविटी रिसैट() पर अंदर एक फ्रैगमेंट ट्रांज़ेक्शन को सुरक्षित करना सुरक्षित है?

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

मैं अपने ऐप के लिए एक ही जवाब में सुझाए गए समाधान को अपनाने के लिए घायल हो गया, और जीवन अच्छा था। हालांकि, हालिया प्रयोग से पता चलता है कि शायद चीजें बदल गई हैं, और onActivityResult() के अंदर से FragmentTransaction को सुरक्षित करने के लिए सुरक्षित रहें।

नोट::

The documentation for (support v4) FragmentManager.beginTransaction() के रूप में लेनदेन के लिए सुरक्षित खिड़की को परिभाषित करता है एक टुकड़ा लेनदेन केवल बनाया जा सकता है/एक गतिविधि अपने राज्य को बचाने के लिए पहले प्रतिबद्ध है। आप के बाद FragmentActivity.onSaveInstanceState() (और करने से पहले एक निम्नलिखित FragmentActivity.onStart या FragmentActivity.onResume() आपको एक त्रुटि मिल जाएगा एक सौदे के लिए प्रतिबद्ध करने का प्रयास करें।

पढ़ना the documentation for onActivityResult(), मैं देख

आप onResume() से ठीक पहले इस कॉल आएगी जब आपकी गतिविधि फिर से शुरू हो रही है।

इससे मुझे विश्वास होता है कि onActivityResult() में इन लेन-देन को निष्पादित करना सुरक्षित होना चाहिए onStart() मुझे पहले ही सुरक्षित विंडो के अंदर रखकर बुलाया जाएगा।

मैंने इसे जांचने के लिए एक ऐप बनाया है, और मैं सफलतापूर्वक संवाद खंड देख रहा हूं जो मैं onActivityResult() के अंदर बना और प्रतिबद्ध करता हूं। मेरे पास एक ही ऐप गतिविधि लाइफसाइक्ल कॉलबैक को लॉग करता था, इसलिए मैं उनके ऑर्डर का निरीक्षण कर सकता था, और मैं onStart(), फिर onRestoreInstanceState(), और फिर onActivityResult() हर बार देखता हूं।

क्या मुझे कुछ याद आ रही है? या ढांचा बदल गया है और onActivityResult() अब खंड लेनदेन के लिए एक सुरक्षित जगह होने की गारंटी है? क्या यह व्यवहार एपीआई स्तर से भिन्न होता है?

मुझे another question and answer मिला जो मुझे प्रलेखन को उसी तरह पढ़ता प्रतीत होता है, लेकिन दोनों एक वर्ष से अधिक पुराने हैं और न तो विशेष रूप से लेनदेन के लिए एक सुरक्षित स्थान के रूप में onActivityResult() को संदर्भित करते हैं।

+0

http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html – elmorabea

+0

@elmorabea पर एक नज़र डालें कि ब्लॉग पोस्ट उन सामग्रियों में से एक है जब मैंने पहली बार पाया था इस मुद्दे। हालांकि, जैसा कि नीचे एज़िज़बेकियन के उत्तर द्वारा दिखाया गया है, ऐसा लगता है कि यह अब फ्रैगमेंट ट्रांस्सेक्शन को सुरक्षित करने के लिए सुरक्षित विंडो का सटीक स्पष्टीकरण नहीं है। –

उत्तर

14

सूत्रों

में एक छोटी सी गोता वहाँ FragmentManager वर्ग के भीतर एक बूलियन चर रहा है, mStatedSaved कहा जाता है। यह चर गतिविधि के जीवन चक्र कॉलबैक के आधार पर सहेजे गए राज्य का ट्रैक रखता है।

 

    private void checkStateLoss() { 
     if (mStateSaved) { 
      throw new IllegalStateException(
        "Can not perform this action after onSaveInstanceState"); 
     } 
     ... 
    } 
 

इसका मतलब यह है, जैसे ही इस चर false करने के लिए बदल जाता है, तो टुकड़ा लेनदेन के लिए स्वतंत्र हैं कि निष्पादित करने के लिए: Here's विधि, कि अच्छी तरह से ज्ञात अपवाद फेंकता है।यह चर true बन जाएगा, जब गतिविधि की स्थिति सहेजी जा रही है, यानी onSaveInstanceState()


सवाल

तुमने कहा था पर वापस, जो पहले आपके onActivityResult() से कोई लेन-देन करने से समस्या थी। इसका मतलब यह होना चाहिए कि पहले mStateSaved को false असाइन नहीं किया जा रहा था और वर्तमान में यह है। कार्य में ऐसा है।

 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     mFragments.noteStateNotSaved(); 
     ... 
    } 
 

कहाँ, noteStateNotSaved() निम्नलिखित करना होगा::

यहाँ हे रिलीज से onActivityResult() कार्यान्वयन है

 

    public void noteStateNotSaved() { 
     ... 
     mStateSaved = false; 
     ... 
    } 
 

इसके विपरीत, आप में से Jelly Bean के onActivityResult() जारी कार्यान्वयन देख सकते हैं:

 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     int index = requestCode>>16; 
     if (index != 0) { 
      index--; 
      if (mFragments.mActive == null || index = mFragments.mActive.size()) { 
       Log.w(TAG, "Activity result fragment index out of range: 0x" 
         + Integer.toHexString(requestCode)); 
       return; 
      } 
      Fragment frag = mFragments.mActive.get(index); 
      if (frag == null) { 
       Log.w(TAG, "Activity result no fragment exists for index: 0x" 
         + Integer.toHexString(requestCode)); 
      } else { 
       frag.onActivityResult(requestCode&0xffff, resultCode, data); 
      } 
      return; 
     } 

     super.onActivityResult(requestCode, resultCode, data); 
    } 
 

कुछ भी नहीं बदलेगा वह mStateSaved फ़ील्ड का मान है, जो एक लेनदेन किए जाने पर फेंकने का अपवाद करेगा।

वास्तव में, किट-कैट रिलीज में mFragments.noteStateNotSaved()was introduced पंक्ति। आप commit's comment डायने Hackborn द्वारा किए गए द्वारा देख सकते हैं:

ActivityFragment झंडा जब यह onNewIntent() प्राप्त करता है कि राज्य में सहेजा गया है स्पष्ट करना चाहिए। यह गतिविधि फिर से शुरू होने से पहले हो सकती है, इसलिए हमने इसे अभी तक साफ़ नहीं किया होगा। onActivityResult() के लिए भी चीज़ करने की आवश्यकता है।

योग अप

onActivityResult() अब टुकड़ा लेनदेन के लिए एक सुरक्षित जगह होने की गारंटी है?

मान लें कि आप उन स्रोतों का उपयोग कर रहे हैं जिनमें commit 4ccc001 शामिल है, जो अक्टूबर 2012 में बनाया गया था - हाँ, यह खंड लेनदेन के लिए एक सुरक्षित स्थान है।

+5

इस तरह के जवाब पढ़ना एक शुद्ध खुशी है। धन्यवाद। – Vasiliy

+0

धन्यवाद, @ वासिलि, आपके उत्तरों/वार्ता का भी आनंद ले रहे हैं। – azizbekian

+1

@azizbekian बहुत अंतर्दृष्टि .... सही उत्तर .... –

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