चूंकि (आप कहते हैं) यह सुपर ऑनक्रीट को सबसे पहले कॉल करने के लिए समझ में आता है: इसके बारे में सोचें।
जब मैं बनाना चाहता हूं, मेरा सुपर अपने संसाधन बनाता है> मैं अपने संसाधन बनाता हूं।
विपरीत: (एक ढेर की तरह)
जब मैं नष्ट करना चाहता हूं, तो मैं अपने संसाधनों को नष्ट कर देता हूं> मेरा सुपर उसके संसाधनों को नष्ट कर देता है।
इस अर्थ में, यह किसी भी प्रकार के कार्यों (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;
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;
}
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();
}
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) {
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 में है।