android finish 判断当前_踩坑之路:Activity执行finish以后onStop方法10s以后才调用

背景

某天,测试提了一个bug,说当前页面关闭了以后回到了上一个页面,但是对应的音乐并没有立刻停止,而是过了一段时间才停止。于是翻阅了一下代码:

@Override

protected void onStop() {

super.onStop();

if (mIsLoading) {

mAudioTool.pausePlayAudio();

}

}

mAudioTool.pausePlayAudio方法是停止播放音频的代码,似乎并没有什么问题。而且这段代码已经运行了好久,之前测试也是通过的,为何这个版本会出现这个问题?

所以首先我debug一下当前页面的onStop方法,结果发现页面关闭的时候onStop方法并没有被执行,然后过了差不多10s左右再被执行,感觉又是踩到了某个坑里面去了,仔细回想了最近改了的代码,问题可能出在了上一个页面的下面这段代码:

/**

* 开始抖动

*/

private fun startShake() {

if(mRotateAnim == null){

mRotateAnim = RotateAnimation(-2f, 2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)

}

if (mRotateAnim!!.hasStarted() && !mRotateAnim!!.hasEnded()) {

//当前动画已经开始并且没有结束

return

}

//从左向右

mRotateAnim!!.duration = 50

mRotateAnim!!.repeatMode = Animation.REVERSE

mRotateAnim!!.repeatCount = Animation.INFINITE

val smallAnimationSet = AnimationSet(false)

smallAnimationSet.addAnimation(mRotateAnim)

cl_wrong_book.startAnimation(smallAnimationSet)

}

由于设置的repeatCount是INFINITE,所以动画是一直在执行中的。

不过还是有点纳闷,动画跟Activity生命周期有啥关系?为了印证下到底是不是Animation影响的当前页面生命周期调用异常,于是将这段代码进行了删除操作。结果Activity的onStop生命周期还真的就正常执行了。然后自己又做了一个demo,来查看下onStop的执行时间。

(这段是没有动画的)

2020-12-14 12:40:17.334 24575-24575/com.example.demo I/MainActivity: onCreate

2020-12-14 12:40:17.663 24575-24575/com.example.demo I/MainActivity: onStart

2020-12-14 12:40:17.670 24575-24575/com.example.demo I/MainActivity: onResume

2020-12-14 12:40:20.818 24575-24575/com.example.demo I/MainActivity: onPause

2020-12-14 12:40:20.836 24575-24575/com.example.demo I/SecondActivity: onCreate

2020-12-14 12:40:20.857 24575-24575/com.example.demo I/SecondActivity: onStart

2020-12-14 12:40:20.858 24575-24575/com.example.demo I/SecondActivity: onResume

2020-12-14 12:40:21.406 24575-24575/com.example.demo I/MainActivity: onStop

2020-12-14 12:40:22.930 24575-24575/com.example.demo I/SecondActivity: onPause

2020-12-14 12:40:22.936 24575-24575/com.example.demo I/MainActivity: onStart

2020-12-14 12:40:22.937 24575-24575/com.example.demo I/MainActivity: onResume

2020-12-14 12:40:23.439 24575-24575/com.example.demo I/SecondActivity: onStop

2020-12-14 12:40:23.440 24575-24575/com.example.demo I/SecondActivity: onDestroy

(这段是加上动画的)

2020-12-14 12:38:06.392 24278-24278/com.example.demo I/MainActivity: onCreate

2020-12-14 12:38:06.563 24278-24278/com.example.demo I/MainActivity: onStart

2020-12-14 12:38:06.565 24278-24278/com.example.demo I/MainActivity: onResume

2020-12-14 12:38:23.940 24278-24278/com.example.demo I/MainActivity: onPause

2020-12-14 12:38:23.964 24278-24278/com.example.demo I/SecondActivity: onCreate

2020-12-14 12:38:23.980 24278-24278/com.example.demo I/SecondActivity: onStart

2020-12-14 12:38:23.980 24278-24278/com.example.demo I/SecondActivity: onResume

2020-12-14 12:38:24.544 24278-24278/com.example.demo I/MainActivity: onStop

2020-12-14 12:38:28.111 24278-24278/com.example.demo I/SecondActivity: onPause

2020-12-14 12:38:28.117 24278-24278/com.example.demo I/MainActivity: onStart

2020-12-14 12:38:28.118 24278-24278/com.example.demo I/MainActivity: onResume

2020-12-14 12:38:38.153 24278-24278/com.example.demo I/SecondActivity: onStop

2020-12-14 12:38:38.155 24278-24278/com.example.demo I/SecondActivity: onDestroy

demo的log也显示了在加上动画以后,确实onStop和onDestroy就会被延迟执行,而且试了多次,发现每次延迟的时间都是10s左右。所以猜测一定存在某种定时执行onStop操作的场景,不然不可能每次都这么凑巧。

既然踩到坑,那么我就得想办法搞清楚为什么会出现这种情况。所以还是跟以前一样,查阅Android源码一探究竟。

finish()操作

/**

* Finishes the current activity and specifies whether to remove the task associated with this

* activity.

*/

@UnsupportedAppUsage

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 (ActivityTaskManager.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));

}

}

/**

* Call this when your activity is done and should be closed. The

* ActivityResult is propagated back to whoever launched you via

* onActivityResult().

*/

public void finish() {

finish(DONT_FINISH_TASK_WITH_ACTIVITY);

}

Activity的finish方法会调用自身带有参数的finish方法,然后通过Binder会执行ActivityTaskManagerService的finishActivity方法。

@Override

public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,

int finishTask) {

...代码省略...

synchronized (mGlobalLock) {

...代码省略...

try {

boolean res;

final boolean finishWithRootActivity =

finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;

if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY

|| (finishWithRootActivity && r == rootR)) {

...代码省略

} else {

res = tr.getStack().requestFinishActivityLocked(token, resultCode,

resultData, "app-request", true);

if (!res) {

Slog.i(TAG, "Failed to finish by app-request");

}

}

return res;

} finally {

Binder.restoreCallingIdentity(origId);

}

}

}

由于finishTask是DONT_FINISH_TASK_WITH_ACTIVITY类型,所以会走else分支,tr.getStack()得到的是ActivityStack对象,所以接下来执行的就是ActivityStack的requestFinishActivityLocked方法。

/**

* @return Returns true if this activity has been removed from the history

* list, or false if it is still in the list and will be removed later.

*/

final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,

String reason, boolean oomAdj, boolean pauseImmediately) {

if (r.finishing) {

//这个判断条件是为了防止多次进入,做了一道屏障

Slog.w(TAG, "Duplicate finish request for " + r);

return false;

}

mWindowManager.deferSurfaceLayout();

try {

//这个方法是为了将finishing设置为true

r.makeFinishingLocked();

final TaskRecord task = r.getTaskRecord();

EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,

r.mUserId, System.identityHashCode(r),

task.taskId, r.shortComponentName, reason);

final ArrayList activities = task.mActivities;

final int index = activities.indexOf(r);

if (index < (activities.size() - 1)) {

task.setFrontOfTask();

if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {

// If the caller asked that this activity (and all above it)

// be cleared when the task is reset, don't lose that information,

// but propagate it up to the next activity.

ActivityRecord next = activities.get(index+1);

next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

}

}

//停止按键的事件分发

r.pauseKeyDispatchingLocked();

adjustFocusedActivityStack(r, "finishActivity");

//检查是否有设置ActivityResult,如果存在则加入列表中

finishActivityResultsLocked(r, resultCode, resultData);

final boolean endTask = index <= 0 && !task.isClearingToReuseTask();

final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;

//当前页面处于Resume状态,所以会进入此分支

if (mResumedActivity == r) {

if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,

"Prepare close transition: finishing " + r);

if (endTask) {

mService.getTaskChangeNotificationController().notifyTaskRemovalStarted(

task.getTaskInfo());

}

getDisplay().mDisplayContent.prepareAppTransition(transit, false);

// Tell window manager to prepare for this one to be removed.

r.setVisibility(false);

if (mPausingActivity == null) {

if (DEBUG_PAUSE) Slog.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值