Vì (bạn nói) nên gọi super onCreate trước: Hãy nghĩ về nó.
Khi tôi muốn tạo, Cấp cao của tôi tạo tài nguyên của nó> Tôi tạo tài nguyên của tôi.
Ngược lại: (loại một ngăn xếp)
Khi tôi muốn phá hủy, tôi phá hủy tài nguyên của tôi> Siêu của tôi phá hủy tài nguyên của anh ta.
Theo nghĩa này, nó áp dụng cho bất kỳ hàm nào (onCreate / onDestroy, onResume / onPause, onStart / onStop). Đương nhiên, onCreate sẽ tạo ra các tài nguyên và onDestroy sẽ giải phóng các tài nguyên này. Nhân tiện, chứng minh tương tự cũng áp dụng cho các cặp đôi khác.
Hãy để chúng tôi xem xét thư viện bạn đã tải xuống có LocationActivity chứa hàm getLocation () cung cấp vị trí. Rất có thể, hoạt động này sẽ cần khởi tạo nội dung của nó trong onCreate (), điều này sẽ buộc bạn phải gọi super.onCreate trước. Bạn đã làm điều đó bởi vì bạn cảm thấy nó có ý nghĩa. Bây giờ, trong onDestroy của bạn, bạn quyết định muốn lưu Vị trí ở đâu đó trong SharedPreferences. Nếu bạn gọi super.onDestroy đầu tiên, thì ở một mức độ nhất định có thể getLocation sẽ trả về giá trị null sau lệnh gọi này vì việc triển khai LocationActivity sẽ vô hiệu hóa giá trị vị trí trong onDestroy. Ý tưởng là bạn sẽ không đổ lỗi nếu điều này xảy ra. Do đó, bạn sẽ gọi super.onDestroy ở cuối sau khi hoàn tất với onDestroy của riêng mình. Tôi hy vọng điều này có ý nghĩa một chút.
Nếu điều trên hợp lý, hãy xem xét rằng tại bất kỳ thời điểm nào chúng ta có một hoạt động tuân theo khái niệm trên. Nếu tôi muốn mở rộng hoạt động này, tôi có thể sẽ cảm thấy như vậy và tuân theo cùng một thứ tự vì cùng một đối số chính xác.
Bằng cách cảm ứng, bất kỳ hoạt động nào cũng nên làm điều tương tự. Đây là một lớp trừu tượng tốt cho một hoạt động buộc phải tuân theo các quy tắc sau:
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);
}
}
Cuối cùng, điều gì sẽ xảy ra nếu hoạt động của bạn được gọi là AnudeepBullaActivity
mở rộng BaseActivity và sau này, tôi muốn tạo SherifElKhatibActivity
hoạt động đó mở rộng hoạt động của bạn? Tôi nên gọi các super.do
hàm theo thứ tự nào? Nó cuối cùng là một điều giống nhau.
Đối với câu hỏi của bạn:
Tôi nghĩ rằng ý định của Google là muốn nói với chúng tôi rằng: Hãy gọi cho siêu cấp dù ở đâu. Tất nhiên, như một thông lệ chung, hãy gọi nó vào đầu. Tất nhiên, Google có những kỹ sư và nhà phát triển sáng giá nhất nên họ có thể đã làm rất tốt việc cô lập các cuộc gọi cấp cao của mình và không can thiệp vào các cuộc gọi con.
Tôi đã thử một chút và có lẽ không dễ dàng (vì Google chúng tôi đang cố gắng chứng minh là sai) để tạo một hoạt động có thể gặp sự cố đơn giản vì When is super được gọi.
Tại sao?
Mọi thứ được thực hiện trong các hàm này thực sự là riêng tư đối với lớp Activity và sẽ không bao giờ gây ra bất kỳ xung đột nào với lớp con của bạn. Ví dụ (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 và mManagedDialogs và mSearchManager đều là các trường riêng tư. Và không có api công khai / được bảo vệ nào sẽ bị ảnh hưởng bởi những gì được thực hiện ở đây.
Tuy nhiên, trong API 14, sendActivityDestroyed đã được thêm vào để gửi một onActivityDestroyed đến ActivityLifecycleCallbacks đã đăng ký với Ứng dụng của bạn. Do đó, bất kỳ mã nào phụ thuộc vào một số logic trong ActivityLifecycleCallbacks của bạn sẽ có một kết quả khác dựa trên thời điểm bạn đang gọi super. Ví dụ:
Tạo một Lớp ứng dụng đếm số lượng hoạt động hiện đang chạy:
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) {}
}
Những điều sau đây có thể không có ý nghĩa hoặc không phải là một thông lệ tốt nhưng nó chỉ để chứng minh một quan điểm (Người ta có thể tìm thấy một tình huống thực tế hơn). Tạo MainActivity được cho là chuyển đến hoạt động GoodBye khi nó kết thúc và khi nó là hoạt động cuối cùng:
@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));
}
}
Nếu bạn gọi super.onDestroy ở đầu onDestroy, hoạt động GoodBye sẽ được khởi chạy. Nếu bạn gọi super.onDestroy ở cuối onDestroy, hoạt động GoodBye sẽ không được khởi chạy.
Tất nhiên, một lần nữa, đây không phải là ví dụ tối ưu. Tuy nhiên, điều này cho thấy Google đã làm sai một chút ở đây. Bất kỳ biến nào khác sẽ không ảnh hưởng đến hành vi của ứng dụng của bạn. Tuy nhiên, việc thêm các công văn này vào onDestroy đã khiến cấp trên bằng cách nào đó can thiệp vào lớp con của bạn.
Tôi nói rằng họ đã nhầm lẫn vì một lý do khác. Họ không chỉ (trước api 14) chỉ chạm vào các lệnh gọi siêu cấp là cuối cùng và / hoặc riêng tư, mà họ còn gọi các chức năng nội bộ khác nhau (riêng tư) thực sự sau đó gửi các chức năng onPause ...
Ví dụ, performStop
hàm là hàm được gọi mà lần lượt gọi hàm 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;
}
Lưu ý rằng họ gọi OnStop của Activity ở đâu đó trong hàm này. Do đó, họ cũng có thể đặt tất cả mã (bao gồm trong super.onStop) trước hoặc sau lệnh gọi đến onStop và sau đó chỉ cần thông báo cho các lớp con về onStop bằng cách sử dụng các siêu chức năng onStop trống và thậm chí không cần thêm SuperNotCalledException hoặc kiểm tra điều này được gọi.
Đối với điều này, nếu họ gọi công văn này đến ActivityLifeCycle trong performanceDestroy thay vì gọi nó ở cuối super.onDestroy, thì hoạt động của chúng ta sẽ giống nhau bất kể khi nào chúng ta gọi super.
Dù sao đây là điều đầu tiên họ làm (hơi sai) và nó chỉ có trong API 14.