Android 如何正确的重写 onDestroy() 方法

不知道大家在写 Android 的时候有没有遇到过这样的一个疑惑:当你在重写 onDestry() 的方法时,有没有犹豫过,我们自己的方法,是应该放在 super.onDestroy() 方法的上面呢?还是应该放在 super.onDestroy() 方法的下面呢?如下所示:

@Override
protected void onDestroy() {
    //是将我们的方法放在这呢?
    super.onDestroy();
    //还是将我们的方法放在这呢?
}

带着这样的一个疑惑,我踏上了,解惑之旅!

1. 回头学习一下 super 关键字

super 是 Java 中的一个关键字,指代父类,用于调用父类中的普通方法和构造方法。 在 Java 中子类可以继承父类中所有可访问的数据域和方法,但不能继承父类中的构造方法,所以需要利用 super 来调用父类中的构造方法。

public class Father {	
	public Father() {
		System.out.println("I'm father, I have a car.");
	}
}

public class Son extends Father{
	public Son() {
		super();
		System.out.println("I'm son, my father will send him car to me.");
	}
}


public class JereTest {
	public static void main(String[] args) {
		System.out.println("print son!");
		Son son = new Son();
	}
}

输出结果:
print son!
I'm father, I have a car.
I'm son, my father will send him car to me.

2. 弄明白 super.onDestroy() 做了什么

当我们知道 super.onDestroy() 做了什么的时候,就不用疑惑自己的方法是放在 super.onDestroy() 方法前,还是 super.onDestroy() 方法后了。

首先,根据官方文档的介绍,onDestroy() 是在活动被销毁之前执行最后的清理。这可能是因为活动正在完成(有人在其上调用了 finish() 方法),也可能是因为系统为了节省空间而临时销毁了活动的这个实例。您可以使用 isFinishing() 方法来区分这两个场景。
注意:不要指望调用此方法来保存数据! 例如,如果一个活动正在内容提供者中编辑数据,那么这些编辑应该在 onPause() 或 onSaveInstanceState(Bundle) 中提交,而不是在这里提交。此方法通常用于释放与某个活动关联的线程等资源,以便被销毁的活动在其应用程序的其余部分仍在运行时不会留下这些资源。在某些情况下,系统只会在不调用此方法(或任何其他方法)的情况下终止活动的宿主进程,因此不应该使用它来做一些在进程结束后仍然存在的事情。
派生类必须通过超类来调用此方法的实现。如果没有,则抛出异常。

接着,我们到 Activity.java 中,查看 onDestroy() 方法究竟做了啥,如下:

/**
     * Perform any final cleanup before an activity is destroyed.  This can
     * happen either because the activity is finishing (someone called
     * {@link #finish} on it), or because the system is temporarily destroying
     * this instance of the activity to save space.  You can distinguish
     * between these two scenarios with the {@link #isFinishing} method.
     *
     * <p><em>Note: do not count on this method being called as a place for
     * saving data! For example, if an activity is editing data in a content
     * provider, those edits should be committed in either {@link #onPause} or
     * {@link #onSaveInstanceState}, not here.</em> This method is usually implemented to
     * free resources like threads that are associated with an activity, so
     * that a destroyed activity does not leave such things around while the
     * rest of its application is still running.  There are situations where
     * the system will simply kill the activity's hosting process without
     * calling this method (or any others) in it, so it should not be used to
     * do things that are intended to remain around after the process goes
     * away.
     *
     * <p><em>Derived classes must call through to the super class's
     * implementation of this method.  If they do not, an exception will be
     * thrown.</em></p>
     *
     * @see #onPause
     * @see #onStop
     * @see #finish
     * @see #isFinishing
     */
    @CallSuper
    protected void onDestroy() {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
        mCalled = true;

        // dismiss any dialogs we are managing.
        // dismiss 我们管理着的所有对话框
        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.
        // 关闭我们正在管理的 Cursor
        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();
        }

        if (mActionBar != null) {
            mActionBar.onDestroy();
        }
        
		//调用Application中的onActivityDestroyed方法,将该Activity从栈中删除。
        dispatchActivityDestroyed();

        notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_STOP);
    }

从上方的代码可以看出,super.onDestroy() 干了三件事:

  1. dismiss 所有我们管理着的 Dialog。
  2. 关闭我们正管理着的 Cursor。
  3. 关闭任何打开着的搜索对话框
  4. 将该Activity从栈中删除

现在知道了 onDestroy() 方法做了什么事情了吧,所以为了防止空异常的出现,我们需要将 ‘我们自己的方法’ 放在 super.onDestroy() 方法上面,比如:

@Override
protected void onDestroy() {
    // 我们自己的方法。
    super.onDestroy();

总结

在重写 onDestroy() 方法时,为了防止出现空异常,我们需要将我们的方法放在 super.onDestroy() 方法上面(但目前我还没遇到到重写 onDestroy() 方法出现空异常)。

顺带记录一下重写 Activity 生命周期的正确姿势:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        //我们自己的方法
    }

    @Override
    protected void onStart() {
        super.onStart();
        //我们自己的方法
    }

    @Override
    protected void onResume() {
        super.onResume();
        //我们自己的方法
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        //我们自己的方法
    }

    /**
     *  在onPause() onStop() onDestroy() 
     *  这三种方法中需要将我们自己的方法放在 super 方法之上。
     **/

    @Override
    protected void onPause() {
        //我们自己的方法
        super.onPause();
    }

    @Override
    protected void onStop() {
        //我们自己的方法
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        //我们自己的方法
        super.onDestroy();
    }
}

个人观点,如有错误,欢迎指正,感谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值