เนื่องจาก (คุณพูด) มันสมเหตุสมผลแล้วที่จะเรียก super onCreate ก่อน: ลองคิดดูสิ
เมื่อฉันต้องการสร้าง super ของฉันจะสร้างทรัพยากร> ฉันสร้างทรัพยากรของฉัน
ผกผัน: (เรียงซ้อน)
เมื่อฉันต้องการทำลายฉันทำลายทรัพยากรของฉัน> ซุปเปอร์ของฉันทำลายทรัพยากรของเขา
ในแง่นี้จะใช้กับสองฟังก์ชัน (onCreate / onDestroy, onResume / onPause, onStart / onStop) ตามธรรมชาติแล้ว onCreate จะสร้างทรัพยากรและ onDestroy จะปลดปล่อยทรัพยากรเหล่านี้ อย่างไรก็ตามหลักฐานเดียวกันนี้ใช้กับคู่อื่น ๆ
ให้เราพิจารณาไลบรารีที่คุณดาวน์โหลดซึ่งมี LocationActivity ที่มีฟังก์ชัน getLocation () ที่ระบุตำแหน่ง ส่วนใหญ่แล้วกิจกรรมนี้จะต้องเริ่มต้นสิ่งต่างๆใน onCreate () ซึ่งจะบังคับให้คุณเรียกใช้ super.onCreate ก่อน คุณทำอย่างนั้นอยู่แล้วเพราะคุณรู้สึกว่ามันสมเหตุสมผล ตอนนี้ใน onDestroy คุณตัดสินใจว่าต้องการบันทึกตำแหน่งไว้ที่ใดที่หนึ่งใน SharedPreferences หากคุณเรียก super.onDestroy ก่อนในระดับหนึ่งอาจเป็นไปได้ที่ getLocation จะส่งคืนค่าว่างหลังการเรียกนี้เนื่องจากการใช้งาน LocationActivity ทำให้ค่าตำแหน่งใน onDestroy เป็นโมฆะ แนวคิดก็คือคุณจะไม่ตำหนิหากสิ่งนี้เกิดขึ้น ดังนั้นคุณจะโทรหา super.onDestroy ในตอนท้ายหลังจากที่คุณทำ 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
ขยาย BaseActivity และในภายหลังฉันต้องการสร้างSherifElKhatibActivity
สิ่งนี้เพื่อขยายกิจกรรมของคุณ ฉันควรเรียกใช้super.do
ฟังก์ชันในลำดับใด ในที่สุดมันก็เป็นสิ่งเดียวกัน
สำหรับคำถามของคุณ:
ฉันคิดว่าความตั้งใจของ Google คือต้องการบอกเรา: โปรดโทรหาซุปเปอร์ไม่ว่าจะอยู่ที่ไหน ในฐานะที่เป็นแนวทางปฏิบัติทั่วไปเรียกว่าในตอนต้น แน่นอนว่า 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 สาธารณะ / ที่ได้รับการป้องกันจะไม่ได้รับผลกระทบจากสิ่งที่ทำที่นี่
อย่างไรก็ตามใน API 14 มีการเพิ่ม dispatchActivityDestroyed เพื่อส่ง onActivityDestroyed ไปยัง ActivityLifecycleCallbacks ที่ลงทะเบียนกับแอปพลิเคชันของคุณ ดังนั้นรหัสใด ๆ ที่จะขึ้นอยู่กับตรรกะบางอย่างใน ActivityLifecycleCallbacks ของคุณจะมีผลลัพธ์ที่แตกต่างกันไปตามเวลาที่คุณเรียกใช้ super ตัวอย่างเช่น:
สร้างคลาสแอปพลิเคชันที่นับจำนวนกิจกรรมที่กำลังทำงานอยู่:
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) {}
}
สิ่งต่อไปนี้อาจไม่สมเหตุสมผลหรือไม่ใช่แนวทางปฏิบัติที่ดี แต่เป็นเพียงการพิสูจน์ประเด็นหนึ่ง (อาจพบสถานการณ์จริงมากกว่า) สร้าง MainActivity ที่คาดว่าจะเข้าสู่กิจกรรม GoodBye เมื่อเสร็จสิ้นและเมื่อเป็นกิจกรรมสุดท้าย:
@Override
protected void onDestroy() {
super.onDestroy();
if(((SherifApplication) getApplication()).getCount() == 0) {
startActivity(new Intent(this, GoodBye.class));
}
}
หากคุณโทรหา super.onDestroy ในช่วงเริ่มต้นของ onDestroy กิจกรรม GoodBye จะเปิดตัว หากคุณโทรหา super.onDestroy ในตอนท้ายของ onDestroy กิจกรรม GoodBye จะไม่เปิดตัว
แน่นอนอีกครั้งนี่ไม่ใช่ตัวอย่างที่ดีที่สุด อย่างไรก็ตามนี่แสดงให้เห็นว่า Google ยุ่งเล็กน้อยที่นี่ ตัวแปรอื่น ๆ จะไม่ส่งผลต่อพฤติกรรมของแอปของคุณ อย่างไรก็ตามการเพิ่มการจัดส่งเหล่านี้ไปยัง onDestroy ทำให้ super เข้ามารบกวนคลาสย่อยของคุณ
ฉันบอกว่าพวกเขายุ่งด้วยเหตุผลอื่นเช่นกัน พวกเขาไม่เพียง แต่ (ก่อน api 14) เท่านั้นที่สัมผัสใน super ที่เรียกว่าอะไรสุดท้ายและ / หรือส่วนตัว แต่ยังเรียกฟังก์ชันภายในที่แตกต่างกัน (ส่วนตัว) ซึ่งจะส่งฟังก์ชัน onPause ...
ตัวอย่างเช่นperformStop
ฟังก์ชันคือฟังก์ชันที่เรียกว่าฟังก์ชัน onStop:
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 ที่ไหนสักแห่งในฟังก์ชันนี้ ดังนั้นพวกเขาอาจใส่รหัสทั้งหมด (รวมอยู่ใน super.onStop) ก่อนหรือหลังการเรียกไปที่ onStop จากนั้นเพียงแจ้งคลาสย่อยเกี่ยวกับ onStop โดยใช้ฟังก์ชัน super onStop ที่ว่างเปล่าและไม่ต้องเพิ่ม SuperNotCalledException หรือตรวจสอบการเรียกนี้
สำหรับสิ่งนี้หากพวกเขาเรียกสิ่งนี้ว่าการจัดส่งไปยัง ActivityLifeCycle ใน performDestroy แทนที่จะเรียกมันในตอนท้ายของ super.onDestroy พฤติกรรมของกิจกรรมของเราจะเหมือนเดิมไม่ว่าเมื่อใดที่เราเรียก super
อย่างไรก็ตามนี่เป็นสิ่งแรกที่พวกเขาทำ (ผิดเล็กน้อย) และเป็นเพียงใน API 14