踩坑之路:finish方法执行后居然还有这种操作_第1页
踩坑之路:finish方法执行后居然还有这种操作_第2页
踩坑之路:finish方法执行后居然还有这种操作_第3页
踩坑之路:finish方法执行后居然还有这种操作_第4页
踩坑之路:finish方法执行后居然还有这种操作_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

踩坑之路:finish方法执行后居然还有这种操作?某天,测试提了一个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:

onDestroydemo的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

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

ent.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方法。

final

boolean

startPausingLocked(boolean

userLeaving,

boolean

uiSleeping,

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;

}

...代码省略...

}这里面有一大段代码都需要管,重点关注里面的mService.getLifecycleManager().scheduleTransaction这个方法。是通过TransactionExecutor进行调度的。这段代码最终会执行ActivityThread里面的下面这段处理:ActivityThread.javacase

EXECUTE_TRANSACTION:

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;TransactionExecutor.java

private

void

executeLifecycleState(ClientTransaction

transaction)

{

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);

}我们是执行了startPausingLocked方法,那么此处最后自然会执行到PauseActivityItem的execute方法里面去的。execute方法就是简单的做了pause的生命周期方法,重点关注下postExecute方法,这里简单梳理下postExecute的调用链。在公众号后端架构师后台回复“架构整洁”,获取一份惊喜礼包。PauseActivityItem#poseExecute()ActivityTaskManagerService#activityPaused()ActivityStack#activityPausedLocked()ActivityStack#finishCurrentActivityLocked()RootActivityContainer#resumeFocusedStacksTopActivities()ActivityStack#resumeTopActivityUncheckedLocked()ActivityStack#resumeTopActivityInnerLocked()@GuardedBy("mService")

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

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

{

pleteResumeLocked();

}

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;

}next.attachedToProcess()可以判断next页面是否已经被系统回收,如果是false就代表页面被回收了走else分支,调用StackSupervisor的startSpecificActivityLocked重启页面。如果是true,那么就会通过TransactionExecutor调度执行ResumeActivityItem的execute方法,执行前一个页面的onResume方法。逻辑处理完以后接下来有这么一段代码:

//

From

this

point

on,

if

something

goes

wrong

there

is

no

way

//

to

recover

the

activity.

try

{

pleteResumeLocked();

}

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;

}我们看下completeResumeLocked的逻辑:

void

completeResumeLocked()

{

...代码省略...

//

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);

}主要就是发送一个延时的message,message主要就是用了执行Activity的onStop和onDestroy生命周期,而IDLE_TIMEOUT正是10s。当前页面的Activity执行了finish操作,并且onStop已经调用,然后上一个页面的onResume方法也已经调用。至此finish相关的操作逻辑告一段落,但是似乎没有看到执行onStop和onDestroy地方(只有一个延迟10s执行的代码)。handleResumeActivity的处理

@Override

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

}handleResumeActivity的过程自然也不是本文的重点,重点关注最后一句话Looper.myQueue().addIdleHandler(newIdler()),这句话什么作用呢?这里就要重点看下addIdleHandler方法到底添加了什么东西。MessageQueue.java

public

void

addIdleHandler(@NonNull

IdleHandler

handler)

{

if

(handler

==

null)

{

throw

new

NullPointerException("Can't

add

a

null

IdleHandler");

}

synchronized

(this)

{

mIdleHandlers.add(handler);

}

}很简单的代码,只是将IdleHandler添加到mIdleHandlers的列表中,那么什么时候会使用这个对象呢。查看了mIdleHandlers的调用地方。发现除了添加和删除IdleHandler对象以外只有MessageQueue的next方法里面有调用的地方。

Message

next()

{

//

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

th

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论