Activity 的 isFinishing()、isDestroy()

结论:

isFinishing() 用于判断 Activity 是否正在 finish。
isDestroy() 用于判断 Activity 是否已经 destroy。
isFinishing() 返回 true 后 isDestroy() 才会返回 true。
一、isFinishing()

   /**
     * Check to see whether this activity is in the process of finishing,
     * either because you called {@link #finish} on it or someone else
     * has requested that it finished.  This is often used in
     * {@link #onPause} to determine whether the activity is simply pausing or
     * completely finishing.
     *
     * @return If the activity is finishing, returns true; else returns false.
     *
     * @see #finish
     */
    public boolean isFinishing() {
        return mFinished;
    }

如注释所说,isFinishing 可以用在 onPause 中判断,该 Activity 是单纯的 pause,还是正在 finish。

isFinishing 只是简单地返回 mFinished 的值,而 mfinished 在 finish() 方法中被赋值。

   /**
     * Finishes the current activity and specifies whether to remove the task associated with this
     * activity.
     */
    private void finish(int finishTask) {
        if (mParent == null) {
            int resultCode;
            Intent resultData;
            synchronized (this) {
                resultCode = mResultCode;
                resultData = mResultData;
            }
            if (false) Log.v(TAG, "Finishing self: token=" + mToken);
            try {
                if (resultData != null) {
                    resultData.prepareToLeaveProcess(this);
                }
                if (ActivityManager.getService()
                        .finishActivity(mToken, resultCode, resultData, finishTask)) {
                    mFinished = true;
                }
            } catch (RemoteException e) {
                // Empty
            }
        } else {
            mParent.finishFromChild(this);
        }

        // Activity was launched when user tapped a link in the Autofill Save UI - Save UI must
        // be restored now.
        if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
            getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_RESTORE,
                    mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
        }
    }


二、isDestroy()

isDestroy() 也只是返回 mDestroyed 的值。

   /**
     * Returns true if the final {@link #onDestroy()} call has been made
     * on the Activity, so this instance is now dead.
     */
    public boolean isDestroyed() {
        return mDestroyed;
    }

mDestroyed 在 performDestroy() 中被赋值,在 onDestroy 执行前赋值。

final void performDestroy() {
        mDestroyed = true;
        mWindow.destroy();
        mFragments.dispatchDestroy();
        onDestroy();
        writeEventLog(LOG_AM_ON_DESTROY_CALLED, "performDestroy");
        mFragments.doLoaderDestroy();
        if (mVoiceInteractor != null) {
            mVoiceInteractor.detachActivity();
        }
    }

三、分析

看一下 Activity finish 的流程:

finish//【Activity】
    ActivityManagerNative.getDefault().finishActivity//【AMS】
        tr.stack.requestFinishActivityLocked//【ActivityStack】
        finishActivityLocked
        finishCurrentActivityLocked
        destroyActivityLocked
            r.app.thread.scheduleDestroyActivity//【ApplicationThread】                        
                handleDestroyActivity//【ActivityThread】
                performDestroyActivity
                    mInstrumentation.callActivityOnDestroy//【Instrumentation】
performDestroy//【Activity】
onDestroy


从上面 finish() 的源码可以看出,当 ActivityManagerNative.getDefault().finishActivity 方法返回 true 后,mFinished 会被赋值。

在 finishActivity 内会调用 requestFinishActivityLocked,requestFinishActivityLocked 内会调 finishActivityLocked,finishActivityLocked 执行完后,requestFinishActivityLocked 就会返回 true。

finishActivityLocked 内会调用 r.app.thread.scheduleDestroyActivity,所以 r.app.thread.scheduleDestroyActivity 执行完后,mFinished 就被赋为 true。

在这里插入图片描述

而 mDestroyed 会在 r.app.thread.scheduleDestroyActivity 执行后,转移到主线程的 handler 里再进行一些操作后才被赋为 true。

所以,mFinished 为 true 比 isDestroyed 为 true 要早。即 isFinishing() 返回 true 后 isDestroy() 才会返回 true。

逻辑上讲也是这样,先进行 finishing,然后才能 destroyed。

当需要使用 Activity 时,判断 activity != null && !activity.isFinishing() 即可。
 


延伸:

Activity onDestroy() 调用研究

刚刚一个BUG让我发现,如果 activity 实现了一个回调接口,然后使用 this 设置给需要回调接口的方法,这种应用场景比较常见,最常见的就是实现 onClickListener 接口,然后 findViewById().setOnClickListenr(this)

如果,这个回调接口设置到了一个静态对象(单例模式),当 activity finish() 的时候(按返回键,回到桌面),则activity 不会被调用 onDestroy() ,原因可能是 activity 对象还在被引用!

此时你再点击图标回到应用,onCreate() 再次调用!

很明显,如果你把资源释放放在了 onDestroy() 里面,就会导致内存泄露!

那有没有解决办法呢?有的

你可以在 onPause() 方法里面判断 isFinishing() ,正常调用 finish() 后 activity 的回调过程是 onPause、onStop、onDestroy ,倘若出现上面的情况,只到 onPause!但是 isFinishing() 标志还是为 true !你可以释放资源了。 
 

 

 

 

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值