踩坑之路:finish方法执行后居然还有这种操作?
https://www.jianshu.com/u/dd07890ebff0
protected void onStop() {
super.onStop();
if (mIsLoading) {
mAudioTool.pausePlayAudio();
}
}
* 开始抖动
*/
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)
}
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.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
* 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);
}
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);
}
}
}
* @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<ActivityRecord> 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.v(TAG_PAUSE, "Finish needs to pause: " + r);
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"finish() => pause with userLeaving=false");
//当前页面还没有进入pause状态,所以会调用此方法
startPausingLocked(false, false, null, pauseImmediately);
}
if (endTask) {
mService.getLockTaskController().clearLockedTask(task);
}
} else if (!r.isState(PAUSING)) {
// If the activity is PAUSING, we will complete the finish once
// it is done pausing; else we can just directly finish it here.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
if (r.visible) {
prepareActivityHideTransitionAnimation(r, transit);
}
final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE
: FINISH_AFTER_PAUSE;
final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj,
"finishActivityLocked") == null;
// The following code is an optimization. When the last non-task overlay activity
// is removed from the task, we remove the entire task from the stack. However,
// since that is done after the scheduled destroy callback from the activity, that
// call to change the visibility of the task overlay activities would be out of
// sync with the activitiy visibility being set for this finishing activity above.
// In this case, we can set the visibility of all the task overlay activities when
// we detect the last one is finishing to keep them in sync.
if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
for (ActivityRecord taskOverlay : task.mActivities) {
if (!taskOverlay.mTaskOverlay) {
continue;
}
prepareActivityHideTransitionAnimation(taskOverlay, transit);
}
}
return removedActivity;
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
}
return false;
} finally {
mWindowManager.continueSurfaceLayout();
}
}
设置当前ActivityRecord为finishing状态
停止按键的事件分发
检查ActivityResult状态,存在的话就加入到列表中
执行startPausingLocked方法。
ActivityRecord resuming, boolean pauseImmediately) {
...代码省略...
if (prev.attachedToProcess()) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving);
mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
...代码省略...
}
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
final IBinder token = transaction.getActivityToken();
final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
+ lifecycleItem + " for activity: "
+ getShortActivityName(token, mTransactionHandler));
}
if (r == null) {
// Ignore requests for non-existent client records for now.
return;
}
// Cycle to the state right before the final requested state.
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
// Execute the final transition with proper parameters.
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
PauseActivityItem#poseExecute()
ActivityTaskManagerService#activityPaused()
ActivityStack#activityPausedLocked()
ActivityStack#finishCurrentActivityLocked()
RootActivityContainer#resumeFocusedStacksTopActivities()
ActivityStack#resumeTopActivityUncheckedLocked()
ActivityStack#resumeTopActivityInnerLocked()
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...代码省略...
if (next.attachedToProcess()) {
...代码省略...
try {
final ClientTransaction transaction =
ClientTransaction.obtain(next.app.getThread(), next.appToken);
// Deliver all pending results.
ArrayList<ResultInfo> a = next.results;
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Delivering results to " + next + ": " + a);
transaction.addCallback(ActivityResultItem.obtain(a));
}
}
if (next.newIntents != null) {
transaction.addCallback(
NewIntentItem.obtain(next.newIntents, true /* resume */));
}
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
next.notifyAppResumed(next.stopped);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.mUserId,
System.identityHashCode(next), next.getTaskRecord().taskId,
next.shortComponentName);
next.sleeping = false;
mService.getAppWarningsLocked().onResumeActivity(next);
next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
next.clearOptionsLocked();
transaction.setLifecycleStateRequest(
ResumeActivityItem.obtain(next.app.getReportedProcState(),
getDisplay().mDisplayContent.isNextTransitionForward()));
mService.getLifecycleManager().scheduleTransaction(transaction);
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
+ next);
} catch (Exception e) {
...代码省略...
return true;
}
// From this point on, if something goes wrong there is no way
// to recover the activity.
try {
next.completeResumeLocked();
} catch (Exception e) {
// If any exception gets thrown, toss away this
// activity and try the next one.
Slog.w(TAG, "Exception thrown during resume of " + next, e);
requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
"resume-exception", true);
return true;
}
} else {
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
return true;
}
// to recover the activity.
try {
next.completeResumeLocked();
} catch (Exception e) {
// If any exception gets thrown, toss away this
// activity and try the next one.
Slog.w(TAG, "Exception thrown during resume of " + next, e);
requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
"resume-exception", true);
return true;
}
...代码省略...
// Schedule an idle timeout in case the app doesn't do it for us.
mStackSupervisor.scheduleIdleTimeoutLocked(this);
...代码省略...
}
void scheduleIdleTimeoutLocked(ActivityRecord next) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE,
"scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
}
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
...代码省略...
//这段代码最终会执行Activity的onResume方法
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
...代码省略...
if (r.window == null && !a.mFinished && willBeVisible) {
//这个判断条件代表当前页面是第一次进入,条件里面的处理就是初始化ViewRootImpl,将View添加在Window上面,执行View的第一次绘制操作
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
...代码省略...
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
mIdleHandlers.add(handler);
}
}
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// 获取当前时间
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
//target为空的情况下,才会进入此条件
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
//遍历messageQueue里面的所有消息,如果存在message是异步的,那么返回给调用者调用。如果不存在异步消息,那么等遍历完退出循环
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
//when主要是postDelay设置的,通过postDelay可以延迟执行,如果当前时间小于when,那么该消息不会被执行。
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
获取当前时间
判断当前message的target对象是否为空,如果是空的会进入if条件中(什么情况下message的target为空呢,答案是调用了postSyncBarrier方法,什么作用呢?主要是ViewRootImpl做同步屏障用的,为了可以让UI事件优先被处理,会设置一个同步屏障,然后发送异步消息处理UI。最大可能保证UI的流畅性)
获取异步消息(如果存在)
判断当前消息的when参数是否大于now(now为当前时间,如果执行postDelay的操作,when是有可能会大于now的,那么这个时候消息将不会执行)
如果当前消息需要立刻执行,将消息从链表中取出,然后设置标志位,交给Looper执行dispatch方法
以上就是消息的主要处理流程。
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
if (mBoundApplication != null && mProfiler.profileFd != null
&& mProfiler.autoStopProfiler) {
stopProfiling = true;
}
if (a != null) {
mNewActivities = null;
IActivityTaskManager am = ActivityTaskManager.getService();
ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
}
if (stopProfiling) {
mProfiler.stopProfiling();
}
applyPendingProcessState();
return false;
}
}
ActivityTaskManagerService#activityIdle()
ActivityStackSupervisor#activityIdleInternalLocked()
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
boolean processPausingActivities, Configuration config) {
if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);
ArrayList<ActivityRecord> finishes = null;
ArrayList<UserState> startingUsers = null;
int NS = 0;
int NF = 0;
boolean booting = false;
boolean activityRemoved = false;
ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers="
+ Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
...代码省略...
}
...代码省略...
// Atomically retrieve all of the other things to do.
final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r,
true /* remove */, processPausingActivities);
NS = stops != null ? stops.size() : 0;
...代码省略...
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.getActivityStack();
if (stack != null) {
if (r.finishing) {
//之前调用finish的时候会将此变量置为true
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false,
"activityIdleInternalLocked");
} else {
stack.stopActivityLocked(r);
}
}
}
...代码省略...
return r;
}
String reason) {
...代码省略...
if (mode == FINISH_IMMEDIATELY
|| (prevState == PAUSED
&& (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
|| finishingInNonFocusedStackOrNoRunning
|| prevState == STOPPING
|| prevState == STOPPED
|| prevState == ActivityState.INITIALIZING) {
r.makeFinishingLocked();
boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);
if (finishingInNonFocusedStackOrNoRunning) {
// Finishing activity that was in paused state and it was in not currently focused
// stack, need to make something visible in its place. Also if the display does not
// have running activity, the configuration may need to be updated for restoring
// original orientation of the display.
mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId,
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
if (activityRemoved) {
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
"destroyActivityLocked: finishCurrentActivityLocked r=" + r +
" destroy returned removed=" + activityRemoved);
return activityRemoved ? null : r;
}
// Need to go through the full pause cycle to get this
// activity into the stopped state and then finish it.
if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r);
mStackSupervisor.mFinishingActivities.add(r);
r.resumeKeyDispatchingLocked();
mRootActivityContainer.resumeFocusedStacksTopActivities();
// If activity was not paused at this point - explicitly pause it to start finishing
// process. Finishing will be completed once it reports pause back.
if (r.isState(RESUMED) && mPausingActivity != null) {
startPausingLocked(false /* userLeaving */, false /* uiSleeping */, next /* resuming */,
false /* dontWait */);
}
return r;
}
Message next() {
...代码省略...
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
...代码省略...
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
...代码省略...
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
...代码省略...
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
...代码省略...
}
}
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
setAnimation(animation);
invalidateParentCaches();
invalidate(true);
}
View#invalidate()
View#invalidateInternal()
ViewGroup#invalidateChild()
ViewGroup#invalidateChildInParent()
ViewRootImpl#invalidateChildInParent()
ViewRootImpl#invalidateRectOnScreen()
ViewRootImpl#scheduleTraversals()
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
if (mTraversalScheduled) {
//此处做了屏障,目的是使得一次Vsync信号只能绘制一次,
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
//执行performTraversals方法
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
...代码省略...
if (a != null) {
more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
concatMatrix = a.willChangeTransformationMatrix();
if (concatMatrix) {
mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
}
transformToApply = parent.getChildTransformation();
} else {
if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
// No longer animating: clear out old animation matrix
mRenderNode.setAnimationMatrix(null);
mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
}
if (!drawingWithRenderNode
&& (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
final Transformation t = parent.getChildTransformation();
final boolean hasTransform = parent.getChildStaticTransformation(this, t);
if (hasTransform) {
final int transformType = t.getTransformationType();
transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
}
}
}
...代码省略...
return more;
}
Animation a, boolean scalingRequired) {
...代码省略...
boolean more = a.getTransformation(drawingTime, t, 1f);
...代码省略...
if (more) {
if (!a.willChangeBounds()) {
...代码省略...
} else {
if (parent.mInvalidateRegion == null) {
parent.mInvalidateRegion = new RectF();
}
final RectF region = parent.mInvalidateRegion;
a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
invalidationTransform);
// The child need to draw an animation, potentially offscreen, so
// make sure we do not cancel invalidate requests
parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
final int left = mLeft + (int) region.left;
final int top = mTop + (int) region.top;
parent.invalidate(left, top, left + (int) (region.width() + .5f),
top + (int) (region.height() + .5f));
}
}
return more;
}
...代码省略...
final long startOffset = getStartOffset();
final long duration = mDuration;
float normalizedTime;
if (duration != 0) {
normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /
(float) duration;
} else {
// time is a step-change with a zero duration
normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
}
final boolean expired = normalizedTime >= 1.0f || isCanceled();
mMore = !expired;
...代码省略...
if (expired) {
if (mRepeatCount == mRepeated || isCanceled()) {
if (!mEnded) {
mEnded = true;
guard.close();
fireAnimationEnd();
}
} else {
if (mRepeatCount > 0) {
mRepeated++;
}
if (mRepeatMode == REVERSE) {
mCycleFlip = !mCycleFlip;
}
mStartTime = -1;
mMore = true;
fireAnimationRepeat();
}
}
return mMore;
}
动画还在一个duration之内,那么normalizedTime >= 1.0f为false,这个时候expired为false,那么mMore就为true。我们暂且不管mMore的作用,后面会说明
动画已经超过了一个duration(即一次动画执行完毕),那么normalizedTime >= 1.0f为true,这个时候expired为true,而mMore为false。
这个时候下面这段逻辑就会进去:
if (mRepeatCount == mRepeated || isCanceled()) {
if (!mEnded) {
mEnded = true;
guard.close();
fireAnimationEnd();
}
} else {
if (mRepeatCount > 0) {
mRepeated++;
}
if (mRepeatMode == REVERSE) {
mCycleFlip = !mCycleFlip;
}
mStartTime = -1;
mMore = true;
fireAnimationRepeat();
}
}
if (!a.willChangeBounds()) {
if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
} else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
// The child need to draw an animation, potentially offscreen, so
// make sure we do not cancel invalidate requests
parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
parent.invalidate(mLeft, mTop, mRight, mBottom);
}
} else {
if (parent.mInvalidateRegion == null) {
parent.mInvalidateRegion = new RectF();
}
final RectF region = parent.mInvalidateRegion;
a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
invalidationTransform);
// The child need to draw an animation, potentially offscreen, so
// make sure we do not cancel invalidate requests
parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
final int left = mLeft + (int) region.left;
final int top = mTop + (int) region.top;
parent.invalidate(left, top, left + (int) (region.width() + .5f),
top + (int) (region.height() + .5f));
}
}
上一个页面执行了Animation动画,由于动画是无限循环的,所以Animation会无限循环的往MessageQueue发送绘制UI的消息
当前页面执行finish操作,Activity进入onPause状态
然后寻找下一个即将resume的Activity,进入resume状态
发送一个延迟10s的消息进入messagequeue中,这个消息用来执行Activity的onStop和onDestroy操作
发送一个Idler对象,旨在MessageQueue空闲的时候执行Activity的onStop和onDestroy操作,并且移除掉第4步发送的延迟消息
由于MessageQueue一直有消息在执行,所以Idler对象没有执行的时机,10s之后,延迟的消息会执行onStop操作
在页面进入onPause的时候可以暂停Animation,然后在onResume的时候发送一个延迟的消息执行Animation,这样Idler就会有空隙执行Activity的onStop生命周期。不过由于这种方案不可靠,因为手机性能的原因,所以有可能存在发送的延迟消息已经开始执行了,Idler对象仍然还没有被post到messagequeue当中。
Animation替换成ValueAnimation,属性动画不会导致Activity的生命周期延迟执行(具体原因本文不做详细分析, 后期有时间可以详细研究),不过这种方案也只是解决了本文中的场景,没办法处理所有导致Activity生命周期延迟10s执行的操作。
我们经常会在onStop和onDestroy方法中做资源释放的操作,但是由于这个原因的存在可能会出现资源释放不及时导致的bug,那我们可以在onPause的时候判断当前finishing状态,如果是true,证明Activity即将关闭,那么可以直接释放资源。这种做法也比较合理,可以适用于各种场景。