ऑनपॉज़, ऑनटॉप और ऑनडेस्ट्रॉय विधियों में सुपरक्लास विधियों को कॉल करने का सही क्रम क्या है? और क्यों?


89

मैं सिर्फ एंड्रॉइड डेवलपर साइट के माध्यम से जा रहा था, गतिविधि जीवन चक्र पर ताज़ा कर रहा था, और प्रत्येक कोड उदाहरण में, सुपर क्लास विधियों के बगल में एक टिप्पणी है जो कहती है "हमेशा सुपरक्लास पद्धति को पहले कॉल करें"।

हालांकि यह रचना आधे चक्र में समझ में आता है: onCreate, onStart और onResume, मैं थोड़ा उलझन में हूं कि विनाश आधे चक्र पर सही प्रक्रिया क्या है: onPause, onStop, onDestroy।

उदाहरण विशिष्ट संसाधनों को नष्ट करने से पहले, सुपरक्लास संसाधनों को नष्ट करने से पहले, उदाहरण विशिष्ट संसाधन किसी अन्य तरीके से नहीं, समझ में आता है। मैं क्या खो रहा हूँ?

संपादित करें : चूंकि लोग इस सवाल के इरादे से भ्रमित हो रहे हैं, इसलिए मैं जानना चाहता हूं कि निम्नलिखित में से कौन सा सही है? और क्यों ?

1.गूगल सुझाव देता है

    @Override
    protected void onStop() {
      super.onStop();  // Always call the superclass method first

      //my implementation here
    }

2. दूसरा तरीका

    @Override
    protected void onStop() {
       //my implementation here

       super.onStop();  
    }

1
मैं शटडाउन विधियों के लिए शिविर दो में हूँ। मैं स्टार्टअप विधियों के लिए शिविर में हूं।
danny117

1
यह बहुत ज्यादा बात है। बस यह नहीं समझ सका कि शटडाउन विधियों के लिए विधि 1 का उपयोग कैसे किया जाता है।
अनुदीप बुल्ला

जवाबों:


107

उदाहरण के विशिष्ट संसाधनों को नष्ट करना, पहले सुपरक्लास संसाधनों को नष्ट करने से पहले, जो कि विशिष्ट संसाधनों पर निर्भर हो सकता है, समझ में आता है, दूसरे तरीके से नहीं। लेकिन टिप्पणियाँ अन्यथा सुझाव देते हैं। मैं क्या खो रहा हूँ?

मेरी राय में: एक भी बात नहीं।

मार्क (उर्फ कॉमन्सवेयर ऑन एसओ) का यह जवाब इस मुद्दे पर प्रकाश डालता है: लिंक - क्या सुपरक्लास पद्धति पर कॉल पहला बयान होना चाहिए? । लेकिन फिर, आप उनके जवाब पर निम्नलिखित टिप्पणी देख सकते हैं:

लेकिन आधिकारिक डॉक क्यों कहता है: ऑनपॉज़ () में "हमेशा सबसे पहले सुपरक्लास पद्धति को कॉल करें"?

एक वर्ग को वापस। ठीक है, इसे दूसरे कोण से देखते हैं। हम जानते हैं कि जावा भाषा विनिर्देश एक आदेश निर्दिष्ट नहीं करता है जिसमें कॉल को super.overridenMethod()रखा जाना चाहिए (या यदि कॉल बिल्कुल रखा जाना चाहिए)।

कक्षा गतिविधि के मामले में, super.overridenMethod()कॉल की आवश्यकता होती है और इसे लागू किया जाता है :

if (!mCalled) {
    throw new SuperNotCalledException(
        "Activity " + mComponent.toShortString() +
            " did not call through to super.onStop()");
}

mCalledमें सच करने के लिए सेट है Activity.onStop()

अब, आदेश पर बहस करने के लिए एकमात्र विवरण बचा है।

I also know that both work

ज़रूर। Activity.onPause () के लिए विधि निकाय को देखें:

protected void onPause() {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);

    // This is to invoke 
    // Application.ActivityLifecyleCallbacks.onActivityPaused(Activity)
    getApplication().dispatchActivityPaused(this);

    // The flag to enforce calling of this method
    mCalled = true;
}

जिस भी तरीके से आप कॉल को सैंडविच super.onPause()करेंगे, आप ठीक हो जाएंगे। Activity.onStop () में एक समान विधि बॉडी है। लेकिन Activity.onDestroy () पर एक नज़र डालें:

protected void onDestroy() {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
    mCalled = true;

    // dismiss any dialogs we are managing.
    if (mManagedDialogs != null) {
        final int numDialogs = mManagedDialogs.size();
        for (int i = 0; i < numDialogs; i++) {
            final ManagedDialog md = mManagedDialogs.valueAt(i);
            if (md.mDialog.isShowing()) {
                md.mDialog.dismiss();
            }
        }
        mManagedDialogs = null;
    }

    // close any cursors we are managing.
    synchronized (mManagedCursors) {
        int numCursors = mManagedCursors.size();
        for (int i = 0; i < numCursors; i++) {
            ManagedCursor c = mManagedCursors.get(i);
            if (c != null) {
                c.mCursor.close();
            }
        }
        mManagedCursors.clear();
    }

    // Close any open search dialog
    if (mSearchManager != null) {
        mSearchManager.stopSearch();
    }

    getApplication().dispatchActivityDestroyed(this);
}

यहां, आपकी गतिविधि सेटअप करने के तरीके के आधार पर आदेश देने से संभवतः कोई फर्क पड़ सकता है, और कॉलिंग super.onDestroy()उस कोड के साथ हस्तक्षेप करेगी जो निम्न प्रकार है।

अंतिम शब्द के रूप में, कथन के Always call the superclass method firstपास इसे वापस लेने के लिए अधिक सबूत नहीं हैं। क्या बुरा है (बयान के लिए) निम्नलिखित कोड से लिया गया है android.app.ListActivity:

public class ListActivity extends Activity {

    ....

    @Override
    protected void onDestroy() {
        mHandler.removeCallbacks(mRequestFocus);
        super.onDestroy();
    }
    ....    
}

और, LunarLander नमूना आवेदन से एंड्रॉयड एसडीके में शामिल:

public class LunarLander extends Activity {

    ....

    @Override
    protected void onPause() {
        mLunarView.getThread().pause(); // pause game when Activity pauses
        super.onPause();
    }
    ....
}

सारांश और योग्य उल्लेख:

उपयोगकर्ता फिलिप श्राद : एक ऐसा परिदृश्य प्रदान करता है जहां super.onPause()किसी गतिविधि के उपयोग में देरी होने पर कॉल को बंद करना होगा startActivityForResult(Intent)। काम करने के setResult(...) बाद परिणाम सेट करना super.onPause()काम नहीं करेगा। बाद में उन्होंने अपने जवाब में टिप्पणियों में इस पर स्पष्टीकरण दिया।

उपयोगकर्ता शेरिफ इल्हातिब : बताते हैं कि क्यों सुपरक्लास ने पहले अपने संसाधनों को शुरू करने और अपने संसाधनों को नष्ट करने के लिए तर्क से अंतिम बार नष्ट किया:

चलिए हम आपके द्वारा डाउनलोड की गई लाइब्रेरी पर विचार करते हैं, जिसमें एक स्थान-स्थान है जिसमें एक स्थानान्तरण () फ़ंक्शन होता है जो स्थान प्रदान करता है। सबसे शायद, इस गतिविधि को ऑनक्रिएट () में अपने सामान को इनिशियलाइज़ करने की आवश्यकता होगी जो आपको सुपर.ऑनक्रिट को कॉल करने के लिए मजबूर करेगा । आप पहले से ही ऐसा करते हैं क्योंकि आपको लगता है कि यह समझ में आता है। अब, आपके onDestroy में, आप तय करते हैं कि आप साझा किए गए सम्मेलनों में कहीं और स्थान बचाना चाहते हैं। यदि आप पहले super.onDestroy को कॉल करते हैं, तो यह एक निश्चित सीमा तक संभव है कि getLocation इस कॉल के बाद एक शून्य मान लौटाएगा क्योंकि LocationActivity का कार्यान्वयन ऑनडेस्ट्रो में स्थान मान को अशक्त करता है। विचार यह है कि ऐसा होने पर आप उसे दोष नहीं देंगे।इसलिए, आप अपने स्वयं के onDestroy के साथ काम करने के बाद अंत में super.onDestroy कहेंगे।

वह इस ओर इशारा करता है: यदि माता-पिता वर्ग से बाल वर्ग को अलग-थलग (संसाधन निर्भरता के मामले में) अलग-थलग किया जाता है, तो super.X()कॉल को किसी भी आदेश विनिर्देश का पालन करने की आवश्यकता नहीं है।

एक परिदृश्य के माध्यम से पढ़ने के लिए जहां की नियुक्ति इस पृष्ठ पर अपना जवाब देखें super.onDestroy()कॉल करता कार्यक्रम तर्क प्रभावित करते हैं।

मार्क द्वारा एक उत्तर से :

उन तरीकों को आप ओवरराइड करते हैं जो घटक निर्माण का हिस्सा हैं (onCreate (), onStart (), onResume (), आदि), आपको पहले कथन के रूप में सुपरक्लास को चेन करना चाहिए , यह सुनिश्चित करने के लिए कि एंड्रॉइड के पास आपके काम करने से पहले अपना काम करने का मौका है। कुछ ऐसा करने का प्रयास जो उस कार्य पर निर्भर करता है।

आपके द्वारा ओवरराइड किए गए तरीके जो घटक विनाश (onPause (), onStop (), onDestroy (), आदि) का हिस्सा हैं, आपको अपना काम पहले करना चाहिए और अंतिम चीज़ के रूप में सुपरक्लास को चेन करना चाहिए । इस तरह, यदि एंड्रॉइड कुछ साफ करता है, जो आपके काम पर निर्भर करता है, तो आपने अपना काम पहले किया होगा।

शून्य (onCreateOptionsMenu (), आदि) के अलावा कुछ और लौटाने वाले तरीके, कभी-कभी आप रिटर्न स्टेटमेंट में सुपरक्लास को चेन करते हैं, यह मानते हुए कि आप विशेष रूप से ऐसा कुछ नहीं कर रहे हैं जो किसी विशेष रिटर्न वैल्यू को मजबूर करने की आवश्यकता है।

बाकी सब कुछ - जैसे onActivityResult () - आप पर है, पूरे पर। मैं पहली चीज़ के रूप में सुपरक्लास की श्रृंखला में हूं, लेकिन जब तक आप समस्याओं में नहीं चल रहे हैं, बाद में जंजीर ठीक होनी चाहिए।

इस धागे से बॉब कर्न्स :

यह एक अच्छा पैटर्न है [(पैटर्न जो मार्क ऊपर बताता है)], लेकिन मुझे कुछ अपवाद मिले हैं। उदाहरण के लिए, जिस विषय को मैं अपनी प्राथमिकता पर लागू करना चाहता था , वह तब तक प्रभावी नहीं होगा जब तक कि मैं इसे सुपरक्लास के ऑनक्रीट () के सामने नहीं डाल देता।

उपयोगकर्ता स्टीव बेनेट भी इस पर ध्यान देता है:

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

उपयोगकर्ता सुनील मिश्रा इस बात की पुष्टि करते हैं कि एक्टिविटी क्लास के तरीकों को कॉल करते समय ऑर्डर (सबसे अधिक संभावना) एक भूमिका नहीं निभाता है। उनका यह भी दावा है कि पहले सुपरक्लास विधियों को कॉल करना सबसे अच्छा अभ्यास माना जाता है । हालाँकि, मैं इस की पुष्टि नहीं कर सका।

उपयोगकर्ता LOG_TAG : बताता है कि सुपरक्लास कंस्ट्रक्टर को कॉल करने से पहले बाकी सब चीजों की आवश्यकता क्यों होती है। मेरी राय में, यह स्पष्टीकरण पूछे जाने वाले प्रश्न से नहीं जुड़ता है।

अंतिम नोट : विश्वास करें, लेकिन सत्यापित करें। इस पृष्ठ पर अधिकांश उत्तर इस दृष्टिकोण का पालन करते हैं कि क्या कथन Always call the superclass method firstमें तार्किक समर्थन है। जैसा कि यह निकला, यह नहीं है; कम से कम, कक्षा गतिविधि के मामले में नहीं। आम तौर पर, किसी को सुपरक्लास स्रोत कोड के माध्यम से पढ़ना चाहिए ताकि यह निर्धारित किया जा सके कि सुपर के तरीकों के लिए कॉलिंग ऑर्डर करना एक आवश्यकता है।


2
वाह। संकेत के लिए धन्यवाद। यह और @ शेरिफ के उत्तर दोनों ही महत्वपूर्ण संदर्भ प्रदान करते हैं। यदि आप में से कोई भी इस पृष्ठ पर उत्तरों को संक्षेप में प्रस्तुत कर सकता है, तो मैं इसे स्वीकार करूँगा। कृपया शामिल करें: इस पृष्ठ पर 1.Answers। 2. @ पर यह पेज 3. @ CommonsWare के जवाब पर फिलिप की जवाब यह पेज 4. इस चर्चा मैं करूंगा, लेकिन मैं अपने अद्भुत जवाब के लिए क्रेडिट नहीं करना चाहती। चीयर्स एंड
थैंक्स

नमस्ते। क्या आप संक्षेप में बता सकते हैं, जैसा कि @Sherif नहीं चाहता है?
अनुदीप बुल्ला

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

@AnudeepBulla मैंने ऊपर एक सारांश जोड़ा है। कृपया मुझे बताएं कि मुझे कुछ भी याद नहीं है।
विक्रम

@ विक्रम टीएल है; डीआर। कि कॉलिंग onDestroyऔर onStopलास्ट एक सुरक्षित डिफॉल्ट है, और यह कि onPauseकुछ मामलों में मुश्किल हो सकती है? क्या आप पहले जोड़ सकते हैं? मुझे स्वयं इस उत्तर को संपादित करने के लिए लुभाया गया था लेकिन मुझे यकीन नहीं है कि यह सारांश सही है।
ब्लेज़ोरब्लेड २ '

13

चूंकि (आप कहते हैं) यह सुपर ऑनक्रीट को सबसे पहले कॉल करने के लिए समझ में आता है: इसके बारे में सोचें।

जब मैं बनाना चाहता हूं, मेरा सुपर अपने संसाधन बनाता है> मैं अपने संसाधन बनाता हूं।

विपरीत: (एक ढेर की तरह)

जब मैं नष्ट करना चाहता हूं, तो मैं अपने संसाधनों को नष्ट कर देता हूं> मेरा सुपर उसके संसाधनों को नष्ट कर देता है।


इस अर्थ में, यह किसी भी प्रकार के कार्यों (onCreate / onDestroy, onResume / onPause, onStart / onStop) पर लागू होता है। स्वाभाविक रूप से, onCreate संसाधन बनाएगा और onDestroy इन संसाधनों को मुक्त करेगा। वैसे, अन्य जोड़ों के लिए भी यही प्रमाण लागू होता है।

चलिए हम आपके द्वारा डाउनलोड की गई लाइब्रेरी पर विचार करते हैं, जिसमें एक स्थान-स्थान है जिसमें एक स्थानान्तरण () फ़ंक्शन होता है जो स्थान प्रदान करता है। सबसे शायद, इस गतिविधि को ऑनक्रिएट () में अपने सामान को इनिशियलाइज़ करने की आवश्यकता होगी जो आपको सुपर.ऑनक्रिट को कॉल करने के लिए मजबूर करेगा। आप पहले से ही ऐसा करते हैं क्योंकि आपको लगता है कि यह समझ में आता है। अब, आपके onDestroy में, आप तय करते हैं कि आप साझा किए गए सम्मेलनों में कहीं और स्थान बचाना चाहते हैं। यदि आप पहले super.onDestroy को कॉल करते हैं, तो यह एक निश्चित सीमा तक संभव है कि getLocation इस कॉल के बाद एक शून्य मान लौटाएगा क्योंकि LocationActivity का कार्यान्वयन ऑनडेस्ट्रो में स्थान मान को अशक्त करता है। विचार यह है कि ऐसा होने पर आप उसे दोष नहीं देंगे। इसलिए, आप अपने स्वयं के onDestroy के साथ किए जाने के बाद अंत में सुपर.ऑनडेस्ट्रॉय कहेंगे। मुझे उम्मीद है कि यह थोड़ा समझ में आता है।

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

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

package mobi.sherif.base;

import android.app.Activity;
import android.os.Bundle;

public abstract class BaseActivity extends Activity {
    protected abstract void doCreate(Bundle savedInstanceState);
    protected abstract void doDestroy();
    protected abstract void doResume();
    protected abstract void doPause();
    protected abstract void doStart();
    protected abstract void doStop();
    protected abstract void doSaveInstanceState(Bundle outState);
    @Override
    protected final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        doCreate(savedInstanceState);
    }
    @Override
    protected final void onDestroy() {
        doDestroy();
        super.onDestroy();
    }
    @Override
    protected final void onResume() {
        super.onResume();
        doResume();
    }
    @Override
    protected final void onPause() {
        doPause();
        super.onPause();
    }
    @Override
    protected final void onStop() {
        doStop();
        super.onStop();
    }
    @Override
    protected final void onStart() {
        super.onStart();
        doStart();
    }
    @Override
    protected final void onSaveInstanceState(Bundle outState) {
        doSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
    }
}

अंत में, क्या होगा यदि आपकी गतिविधि को AnudeepBullaActivityबेस एक्टिविटी कहा जाता है और बाद में, मैं बनाना चाहता हूं SherifElKhatibActivityजो आपकी गतिविधि का विस्तार करता है? मुझे किस क्रम में super.doफ़ंक्शन को कॉल करना चाहिए ? यह अंततः एक ही बात है।


अपने प्रश्न के लिए के रूप में:

मुझे लगता है कि Google का इरादा हमें यह बताने का है: कृपया सुपर को बुलाएं जहां कोई बात नहीं है। बेशक एक सामान्य अभ्यास के रूप में, इसे शुरुआत में कहें। बेशक गूगल के पास सबसे तेज इंजीनियर और डेवलपर्स हैं, इसलिए उन्होंने संभवतः अपने सुपर कॉल्स को अलग करने और चाइल्ड कॉल में हस्तक्षेप न करने के लिए एक अच्छा काम किया है।

मैंने थोड़ी कोशिश की और यह शायद आसान नहीं है (क्योंकि यह Google है जिसे हम गलत साबित करने की कोशिश कर रहे हैं) एक ऐसी गतिविधि बनाने के लिए जो सरल होने के कारण सुपर क्रैश हो जाएगी।

क्यों?

इन कार्यों में किया गया कुछ भी वास्तव में गतिविधि वर्ग के लिए निजी है और आपके उपवर्ग के साथ किसी भी संघर्ष का कारण नहीं होगा। उदाहरण के लिए (onDestroy)

protected void onDestroy() {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
    mCalled = true;

    // dismiss any dialogs we are managing.
    if (mManagedDialogs != null) {
        final int numDialogs = mManagedDialogs.size();
        for (int i = 0; i < numDialogs; i++) {
            final ManagedDialog md = mManagedDialogs.valueAt(i);
            if (md.mDialog.isShowing()) {
                md.mDialog.dismiss();
            }
        }
        mManagedDialogs = null;
    }

    // close any cursors we are managing.
    synchronized (mManagedCursors) {
        int numCursors = mManagedCursors.size();
        for (int i = 0; i < numCursors; i++) {
            ManagedCursor c = mManagedCursors.get(i);
            if (c != null) {
                c.mCursor.close();
            }
        }
        mManagedCursors.clear();
    }

    // Close any open search dialog
    if (mSearchManager != null) {
        mSearchManager.stopSearch();
    }

    getApplication().dispatchActivityDestroyed(this);
}

mManagedCursors और mManagedDialogs और mSearchManager सभी निजी क्षेत्र हैं। और यहां जो कुछ भी किया गया है, उससे कोई भी सार्वजनिक / संरक्षित एपी प्रभावित नहीं होगा।

हालाँकि, API 14 में, dispatchActivityDestroyed को एक OnActivityDestroyed को ActivityLifecycleCallbacks में आपके एप्लिकेशन में पंजीकृत करने के लिए जोड़ा गया था। इसलिए, कोई भी कोड जो आपके एक्टिविटी लिफिचकलकॉलबैक में कुछ तर्क पर निर्भर करेगा, जब आप सुपर कॉल कर रहे हों तो उसके आधार पर एक अलग परिणाम होगा। उदाहरण के लिए:

एक एप्लिकेशन क्लास बनाएँ जो वर्तमान में चल रही गतिविधियों की संख्या को गिनाए:

package mobi.shush;

import android.app.Activity;
import android.app.Application;
import android.app.Application.ActivityLifecycleCallbacks;
import android.os.Bundle;

public class SherifApplication extends Application implements ActivityLifecycleCallbacks {
    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(this);
    }
    public int getCount() {
        return count;
    }
    int count = 0;
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        count++;
    }
    @Override
    public void onActivityDestroyed(Activity activity) {
        count--;
    }
    @Override
    public void onActivityPaused(Activity activity) {}
    @Override
    public void onActivityResumed(Activity activity) {}
    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState)           {}
    @Override
    public void onActivityStarted(Activity activity) {}
    @Override
    public void onActivityStopped(Activity activity) {}
}

निम्नलिखित समझ में नहीं आता है या यह एक अच्छा अभ्यास नहीं है, लेकिन यह सिर्फ एक बिंदु साबित करने के लिए है (एक और अधिक वास्तविक स्थिति मिल सकती है)। माना जाता है कि मुख्य गतिविधि गुडबाय गतिविधि में जाती है जब यह समाप्त हो जाती है और जब यह अंतिम गतिविधि होती है:

@Override
protected void onDestroy() {
    super.onDestroy();
    if(((SherifApplication) getApplication()).getCount() == 0) {
        //i want to go to a certain activity when there are no other activities
        startActivity(new Intent(this, GoodBye.class));
    }
}

यदि आप अपने onDestroy की शुरुआत में super.onDestroy कहते हैं, तो GoodBye गतिविधि लॉन्च की जाएगी। यदि आप अपने onDestroy के अंत में super.onDestroy कहते हैं, तो GoodBye गतिविधि लॉन्च नहीं की जाएगी।

बेशक, फिर से, यह इष्टतम उदाहरण नहीं है। हालाँकि इससे पता चलता है कि Google ने यहाँ कुछ गड़बड़ की। किसी भी अन्य चर ने आपके ऐप के व्यवहार को प्रभावित नहीं किया होगा। हालाँकि इन डिस्पैच को onDestroy में जोड़ने से सुपर को किसी तरह आपके उपवर्ग में हस्तक्षेप करने का कारण बना।

मैं कहता हूं कि उन्होंने एक अलग कारण के लिए भी गड़बड़ कर दी। न केवल उन्होंने (एपी 14 से पहले) केवल सुपर कॉल्स में टच किया जो कि अंतिम और / या निजी है, लेकिन उन्होंने अलग-अलग आंतरिक कार्यों (निजी) को भी कहा जो वास्तव में तब ऑनपॉज़ ... फ़ंक्शंस को भेजते थे।

उदाहरण के लिए, performStopफ़ंक्शन वह फ़ंक्शन है जिसे कॉल किया जाता है, बदले में ऑनटॉप फ़ंक्शन को कॉल करता है:

final void performStop() {
    if (mLoadersStarted) {
        mLoadersStarted = false;
        if (mLoaderManager != null) {
            if (!mChangingConfigurations) {
                mLoaderManager.doStop();
            } else {
                mLoaderManager.doRetain();
            }
        }
    }

    if (!mStopped) {
        if (mWindow != null) {
            mWindow.closeAllPanels();
        }

        if (mToken != null && mParent == null) {
            WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
        }

        mFragments.dispatchStop();

        mCalled = false;
        mInstrumentation.callActivityOnStop(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onStop()");
        }

        synchronized (mManagedCursors) {
            final int N = mManagedCursors.size();
            for (int i=0; i<N; i++) {
                ManagedCursor mc = mManagedCursors.get(i);
                if (!mc.mReleased) {
                    mc.mCursor.deactivate();
                    mc.mReleased = true;
                }
            }
        }

        mStopped = true;
    }
    mResumed = false;
}

ध्यान दें कि वे इस फ़ंक्शन में कहीं भी गतिविधि के onStop को कॉल करते हैं। इसलिए, वे onStop पर कॉल करने से पहले या बाद में सभी कोड (super.onStop में शामिल) डाल सकते हैं और फिर बस onStop के बारे में उपवर्गों को सूचित कर सकते हैं कि खाली onStop सुपर फ़ंक्शन का उपयोग करें और यहां तक ​​कि SuperNCCededException को जोड़कर या इस के लिए जाँच नहीं की जाती।

इसके लिए, यदि वे सुपरडायरेस्ट के अंत में कॉल करने के बजाय PerformDestroy में एक्टिविटीलाइफ साइकल को यह प्रेषण कहते हैं, तो हमारी गतिविधि का व्यवहार वैसा ही होगा, जब हम सुपर को कॉल करते हैं।

वैसे भी यह पहली चीज है जो वे करते हैं (थोड़ा गलत) और यह केवल एपीआई 14 में है।


यह सवाल कभी नहीं किया गया है कि सुपर.ऑनडेस्ट्रॉय () को अंतिम रूप देना क्यों मायने रखता है। मुझे आपका पुस्तकालय उदाहरण पसंद है। बिल्कुल वही जो मैं भी बताना चाहता था। मैं डेटा के आकस्मिक नुकसान को रोकने के लिए सुपर विधियां अंतिम विनाशकारी चक्र पर अंतिम रूप से कॉल करने पर अधिक सहमत नहीं हो सकता। समस्या यह है कि Google पहले उपरोक्त तरीकों को देखते हुए सुपर तरीकों को कॉल करने पर जोर क्यों देता है? मैंने प्रश्न पूछा क्योंकि मुझे लगा कि शायद मैं, और प्रतीत होता है कि आप भी, शायद यह पूरी तरह से अलग तरीके से आ रहा है। चीयर्स
अनुदीप बुल्ला

ओह, मैंने नहीं देखा कि Google सुझाव देता है और दूसरा तरीका: पी! सुनो, मैं एक ऐसी गतिविधि बनाने की कोशिश करने जा रहा हूँ जो अगर आप onDestroy को पहले कॉल करेंगे तो दुर्घटनाग्रस्त हो जाएगी। आपको भी यही कोशिश करनी चाहिए। चीयर्स
शेरिफ एलीहाटीब

@AnudeepBulla आप मेरे संपादन की जांच कर सकते हैं। और btw आप कोशिश करना बंद कर सकते हैं। super.onशायद कभी भी आपकी गतिविधि क्रैश नहीं होगी।
शेरिफ इलाक़ीब

वाह। संकेत के लिए धन्यवाद। यह और @ उपयोगकर्ता के उत्तर दोनों महत्वपूर्ण संदर्भ प्रदान करते हैं। यदि आप में से कोई भी इस पृष्ठ पर उत्तरों को संक्षेप में प्रस्तुत कर सकता है, तो मैं इसे स्वीकार करूँगा। कृपया शामिल करें: इस पृष्ठ पर 1.Answers। 2. @ पर यह पेज 3. @ CommonsWare के जवाब पर फिलिप की जवाब यह पेज 4. इस चर्चा मैं करूंगा, लेकिन मैं अपने अद्भुत जवाब के लिए क्रेडिट नहीं करना चाहती। चीयर्स एंड
थैंक्स

@AnudeepBulla आपका स्वागत है। मुझे यकीन नहीं है कि हम यह कैसे तय करने जा रहे हैं कि कौन अंतिम लेखन को पोस्ट करता है।
विक्रम

2

आप कहते हैं कि Google विधि 1 का सुझाव देता है, हालांकि एक प्रसिद्ध एंड्रॉइड फ्रेमवर्क इंजीनियर डायने हैकबॉर्न सुझाव देता है कि Google फ़ोरम लिंक देखें

यह सुपर वर्ग कॉल करने के लिए सहज ज्ञान युक्त समझ में आता है पिछले जब नष्ट करने में एक उदाहरण onPause, onStop और OnDestroy तरीकों और पहले जब बनाने के तरीकों के साथ एक उदाहरण onCreate, onResume और onStart


डायने हैकॉर्न की पोस्ट का लिंक महत्वपूर्ण है और पैटर्न की पुष्टि करता है।
निक वेस्टगेट

1

जावा परिप्रेक्ष्य से इस भ्रम के लिए कुछ समाधान है:

एक निर्माता में यह () और सुपर () का पहला बयान क्यों होता है?

उपवर्ग के कंस्ट्रक्टर से पहले पैरेंट क्लास 'कंस्ट्रक्टर को बुलाया जाना चाहिए। यह सुनिश्चित करेगा कि यदि आप अपने निर्माता में पैरेंट क्लास पर किसी भी तरीके को कॉल करते हैं, तो पैरेंट क्लास पहले ही सही तरीके से सेट हो चुका है।

आप क्या करने की कोशिश कर रहे हैं, सुपर कंस्ट्रक्टर के पास आर्ग्स पूरी तरह से कानूनी है, आपको बस उन आर्ग इनलाइन का निर्माण करने की आवश्यकता है जैसे आप कर रहे हैं, या उन्हें अपने कंस्ट्रक्टर में पास करें और फिर उन्हें सुपर में पास करें:

public MySubClassB extends MyClass {
        public MySubClassB(Object[] myArray) {
                super(myArray);
        }
}

यदि कंपाइलर ने इसे लागू नहीं किया है तो आप ऐसा कर सकते हैं:

public MySubClassB extends MyClass {
        public MySubClassB(Object[] myArray) {
                someMethodOnSuper(); //ERROR super not yet constructed
                super(myArray);
        }
}

यह दर्शाता है कि वास्तव में, सुपरफ़्लैक्स से पहले सबफ़िल्ड को निष्क्रिय करना पड़ता है! इस बीच, जावा आवश्यकता हमें सुपर कंस्ट्रक्टर के तर्क के बारे में बताकर वर्ग की विशेषज्ञता से "बचाव" करती है

ऐसे मामलों में जहां एक पैरेंट क्लास के पास डिफॉल्ट कंस्ट्रक्टर होता है, कॉल टू सुपर आपके लिए कंपाइलर द्वारा स्वचालित रूप से डाला जाता है। चूंकि जावा में हर वर्ग ऑब्जेक्ट से विरासत में मिला है, इसलिए ऑब्जेक्ट कंस्ट्रक्टर को किसी भी तरह से बुलाया जाना चाहिए और इसे पहले निष्पादित किया जाना चाहिए। संकलक द्वारा सुपर () का स्वचालित सम्मिलन इसकी अनुमति देता है। पहले प्रदर्शित होने के लिए सुपर लागू करना, यह बताता है कि कंस्ट्रक्टर निकायों को सही क्रम में निष्पादित किया जाता है जो होगा: ऑब्जेक्ट -> जनक -> बच्चा -> चाइल्डऑफ चिल्ड -> SoOnSoForth

(१) यह जाँचना कि सुपर पहला बयान है, उस समस्या को रोकने के लिए पर्याप्त नहीं है। उदाहरण के लिए, आप "सुपर (someMethodInSuper ());" आपके निर्माता में। यह निर्माण करने से पहले सुपरक्लास में एक विधि तक पहुंचने का प्रयास करता है, भले ही सुपर पहला बयान हो।

(२) संकलक इस समस्या को रोकने के लिए पर्याप्त रूप से, एक अलग जाँच लागू करता है। संदेश है "सुपरटेप कंस्ट्रक्टर को बुलाए जाने से पहले xxx का संदर्भ नहीं दिया जा सकता है"। इसलिए, यह जांचना कि सुपर पहला कथन है, आवश्यक नहीं है

कृपया इस http://valjok.blogspot.in/2012/09/super-constructor-must-be-free.html


मैं पूरी तरह से समझता हूं कि आप वहां क्या कर रहे हैं। आप पहले सुपर क्लास कंस्ट्रक्टर्स को बुलाते हैं, 'coz वे संसाधनों की शुरुआत कर सकते हैं जो बच्चे की आवश्यकता हो सकती है; और विध्वंसक पिछले, 'coz तुम नहीं करना चाहते हो सकता है शायद स्थानीय संसाधनों के लिए सभी माता पिता को मिटा, उन्हें व्यर्थ बना रही है। यह मेरी बात ठीक है। और चूंकि onPause, onStop, और onDestroy में जीसी (इसलिए उन्हें नष्ट करने वाले अर्थों में) के लिए राज्य की जानकारी और कम या ज्यादा संसाधन उपलब्ध कराने का काम है, इसलिए मैं उन्हें विध्वंसक के अनुरूप देखता हूं और इसलिए उन्हें अंतिम अर्थ कहना चाहता हूं। नहीं?
अनुदीप बुल्ला

ऊपर आपने जो कुछ कहा था, ठीक वैसा ही है जब मैंने कहा था कि "सुपर तरीकों को कॉल करने से पहले निर्माण आधे चक्र पर समझ में आता है"। मैं चिंतित हूं, और विनाश के आधे चक्र के तरीकों के मामले में भ्रमित हूं, जो विनाशकारियों के लिए अधिक अनुरूप हैं। चीयर्स
अनुदीप बुल्ला

1

ध्यान रखने वाली सबसे महत्वपूर्ण बात यह है कि इसका मतलब है कि super.onPause()कॉलsetResult(Activity.RESULT_CANCELED) । लेकिन setResultकेवल एक बार कॉल किया जा सकता है, और बाद की सभी कॉल को अनदेखा कर दिया जाता है। इसलिए यदि आप किसी भी प्रकार के परिणाम को मूल गतिविधि पर वापस लाना चाहते हैं, तो आपको कॉल करने से पहलेsetResult खुद को कॉल करना होगा । जहां तक ​​मुझे पता है, यह सबसे बड़ा गोच है।super.onPause()


वाह, यह महत्वपूर्ण लगता है। तो एक स्थिति है, जब आपको निश्चित रूप से सुपर तरीकों को कॉल करने में देरी करनी होगी। धन्यवाद।
अनुदीप बुल्ला

super.onPause() implicitly calls setResult(Activity.RESULT_CANCELED)। क्या आप कह सकते हैं कि आपको यह कहां से मिला है?
विक्रम

मैं भ्रमित था। यह वास्तव में खत्म () है जो कॉल सेट करता है ।Result, और super.onBackPressed () कॉल फिनिश ()। तो setResult निश्चित रूप से super.onBackPressed () से पहले कॉल करना होगा। मुझे यकीन नहीं है कि क्या ऐसी कोई परिस्थितियां हैं जिनमें सुपर.ऑन पॉज़ () के कारण सेट किया जा सकता है। कहा जाता है, लेकिन मैं इसे जोखिम में नहीं डालना पसंद करता हूं।
फिलिप शियर

1

दोनों सही IMO हैं

डॉक्स के अनुसार

व्युत्पन्न वर्गों को सुपर क्लास के इस पद्धति के कार्यान्वयन के माध्यम से कॉल करना होगा। यदि वे नहीं करते हैं, तो एक अपवाद फेंक दिया जाएगा।

Super विधि को हमेशा कहा जाना चाहिए जब प्रलेखन स्पष्ट रूप से ऐसा कहता है।

आप हालांकि सुपर विधि को कॉल करने के लिए चुन सकते हैं।

के स्रोत को देखते हुए onPause

protected void onPause() {
    getApplication().dispatchActivityPaused(this);
    mCalled = true;
}

इसलिए इसे बुलाए जाने से पहले या बाद में कोई फर्क नहीं पड़ता। आपको अच्छा होना चाहिए।

लेकिन सर्वोत्तम अभ्यास के लिए, आपको इसे पहले कॉल करना चाहिए।

मैं इसे ज्यादातर एक सुरक्षा तंत्र के रूप में सुझाता हूं: यदि कोई अपवाद है तो superउदाहरण विधि पहले ही कह दी जाएगी।

साथ ही इन कॉल को पहली पंक्ति में रखने से आपको भविष्य में गलतियाँ करने से बचने में मदद मिलेगी जैसे कि विधि में कोड हटाना और गलती से सुपर क्लास को कॉल हटाना।


मुझे क्षमा करें यदि प्रश्न पहली बार के आसपास पूरी तरह से स्पष्ट नहीं था, लेकिन कृपया अब इस पर एक नज़र डालें।
अनुदीप बुल्ला

@AnudeepBulla यही मैंने आपको समझाया है। आप दोनों में से किसी का भी उपयोग कर सकते हैं। दोनों मान्य हैं।
सुनील मिश्रा

यह मेरी समझ है कि onPause, onStop और onDestroy के तरीकों का कस्टम कार्यान्वयन कड़ाई से आवश्यक नहीं है। मैंने उन लोगों के बिना पर्याप्त एप्लिकेशन बनाए हैं। तो सुपर तरीकों से आपका क्या मतलब है हमेशा कहा जाना चाहिए? वे बिना किसी को बताए भी निहित रूप से कहे जाते हैं। मुझे यह भी पता है कि दोनों काम करते हैं। मुझे पता है कि डॉक्स को सुपर क्यों कहा जाना चाहिए। और अगर प्रश्न अभी भी स्पष्ट नहीं है, तो क्या आप कृपया WHY की व्याख्या करेंगे, जब आप कहते हैं कि "लेकिन सर्वोत्तम अभ्यास के लिए, आपको इसे पहले कॉल करना चाहिए"?
अनुदीप बुल्ला

यदि आप ओवरराइड नहीं करते हैं, तो तरीकों को कहा जाता है, Base Classलेकिन यदि आप ओवरराइड करते हैं, तो यह आवश्यक है कि आप उस फोन को कॉल करें जो superआपके पास होगाandroid.app.SuperNotCalledException
सुनील मिश्रा

1
आप गलत समझ रहे हैं। सवाल यह नहीं है कि फोन करना है या नहीं। जैसे आपने बताया, यदि आप उन्हें ओवरराइड करते हैं, तो आप उनके पास हैं। सवाल है, कब?
अनुदीप बुल्ला

0

कॉलबैक के सुपर को सिस्टम के लिए आंतरिक रूप से गतिविधि को सही स्थिति में रखने की आवश्यकता होती है।

मान लीजिए कि आप अपनी गतिविधि शुरू करते हैं और सिस्टम द्वारा ऑनक्रिएट किया जाता है। अब आप इसे ओवरराइड कर सकते हैं और उदाहरण के लिए अपने लेआउट को लोड कर सकते हैं। लेकिन सिस्टम फ्लो के लिए आपको सुपर कॉल करना होगा, ताकि सिस्टम मानक प्रक्रिया के साथ जारी रह सके। इसलिए यदि आप इसे नहीं बुलाते हैं तो एक अपवाद को फेंक दिया जाएगा।

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

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

लेकिन सिस्टम को यह करने के लिए कि यह सबसे अच्छा कॉलबैक की पहली पंक्ति में आपके कोड के बाद सबसे अच्छा क्या कर सकता है, अगर आपके पास इसे तोड़ने का एक अच्छा कारण नहीं है।


OnCreate में अनुक्रम बहुत ज्यादा समझ में आता है। विनाश के तरीकों में क्या होता है? कहो तो onStop। मान लीजिए कि मेरा onStop कार्यान्वयन सुपर-मेथड रिलीज़ करने के लिए कुछ संसाधनों का उपयोग करता है, अगर कहा जाता है। यह मेरे कार्यान्वयन के बाद सुपर विधि को कॉल करने के लिए समझ में आता है।
अनुदीप बुल्ला

आदर्श रूप से, यह मामला होना चाहिए, सही। हमारी गतिविधि में हमेशा ऐसे संसाधन होंगे जो सुपर क्लास के पास हैं, और कुछ और। और जो मेरी गतिविधि के लिए स्वतंत्र हैं, ज्यादातर मामलों में सुपरक्लास संसाधनों पर निर्भर करते हैं, जो कि सामान्य हैं। यह पहले मेरे संसाधनों से निपटने के लिए अधिक समझ में आता है, और फिर आम लोगों से निपटने के लिए सुपरक्लास को बुला रहा है। Google तब हमें "SHOULD" कॉल को सुपरक्लॉस तरीके क्यों कहता है?
अनुदीप बुल्ला

आप किस संसाधन की बात कर रहे हैं, जिसे आप onCreate में एक्सेस कर सकते हैं लेकिन onDestroy में नहीं?
स्टीव बेनेट

मेरे पास उपयोग का मामला नहीं है। मैं बस सोच रहा हूं, यह ओओपी शैली के साथ कैसे बदलता है। सुपर क्लास कंस्ट्रक्टर को आपके कार्यान्वयन से पहले, और सुपर क्लास डिस्ट्रक्टर्स को अंतिम कहा जाता है, आपके कार्यान्वयन के बाद? onPause, onStop, और onDestroy कड़ाई से विनाशकारी नहीं हैं, लेकिन वे एक ही सामान करने के लिए जाते हैं, है ना? कम से कम onDestroy और ज्यादातर onStop .. नहीं?
अनुदीप बुल्ला

राज्य में कॉलबैक को एक निर्माता / विध्वंसक के रूप में नहीं बदलते तरीके से देखें। प्रत्येक कॉलबैक में इसकी आवश्यकता होती है जैसे एक गतिविधि बनाने के लिए तैयार (उपयोग करने के लिए तैयार) / नष्ट (आपका अंतिम मौका) एक गतिविधि या इसे अग्रभूमि या पृष्ठभूमि में रखें। कॉलबैक वहाँ हैं कि आप सिस्टम के प्रवाह में अपने संसाधनों को नियंत्रित कर सकते हैं। सिस्टम सिर्फ यह जाँच करता है कि वह किस स्थिति में है और उसी के अनुसार संभालता है। आपके द्वारा उपयोग किए जाने वाले संसाधन और यह कि सिस्टम नियंत्रण एक दूसरे से स्वतंत्र हैं और कोई अंतरंगता नहीं होगी।
स्टीव बेनेट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.