【移动应用开发技术】Android 中Activity的启动过程有哪些_第1页
【移动应用开发技术】Android 中Activity的启动过程有哪些_第2页
【移动应用开发技术】Android 中Activity的启动过程有哪些_第3页
【移动应用开发技术】Android 中Activity的启动过程有哪些_第4页
【移动应用开发技术】Android 中Activity的启动过程有哪些_第5页
已阅读5页,还剩12页未读 继续免费阅读

付费下载

下载本文档

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

文档简介

【移动应用开发技术】Android中Activity的启动过程有哪些

本篇文章给大家分享的是有关Android中Activity的启动过程有哪些,在下觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着在下一起来看看吧。前言Activity是Android中一个很重要的概念,堪称四大组件之首,关于Activity有很多内容,比如生命周期和启动Flags,这二者想要说清楚,恐怕又要写两篇长文,更何况分析它们的源码呢。不过本文的侧重点不是它们,我要介绍的是一个Activity典型的启动过程,本文会从源码的角度对其进行分析。我们知道,当startActivity被调用的时候,可以启动一个Activity,但是你知道这个Activity是如何被启动的吗?每个Activity也是一个对象,你知道这个对象是啥时候被创建的吗(也就是说它的构造方法是什么时候被调用的)?为什么onCreate是Activity的执行入口?所有的这一切都被系统封装好了,对我们来说是透明的,我们使用的时候仅仅是传递一个intent然后startActivity就可以达到目的了,不过,阅读了本文以后,你将会了解它的背后到底做了哪些事情。在分析之前,我先介绍几个类:Activity:这个大家都熟悉,startActivity方法的真正实现在Activity中Instrumentation:用来辅助Activity完成启动Activity的过程ActivityThread(包含ApplicationThread+ApplicationThreadNative+IApplicationThread):真正启动Activity的实现都在这里源码分析code:Activity#startActivity@Override

public

void

startActivity(Intent

intent)

{

startActivity(intent,

null);

}

@Override

public

void

startActivity(Intent

intent,

Bundle

options)

{

if

(options

!=

null)

{

startActivityForResult(intent,

-1,

options);

}

else

{

//

Note

we

want

to

go

through

this

call

for

compatibility

with

//

applications

that

may

have

overridden

the

method.

startActivityForResult(intent,

-1);

}

}

public

void

startActivityForResult(Intent

intent,

int

requestCode)

{

startActivityForResult(intent,

requestCode,

null);

}说明:显然,从上往下,最终都是由startActivityForResult来实现的接着看code:Activity#startActivityForResultpublic

void

startActivityForResult(Intent

intent,

int

requestCode,

Bundle

options)

{

//一般的Activity其mParent为null,mParent常用在ActivityGroup中,ActivityGroup已废弃

if

(mParent

==

null)

{

//这里会启动新的Activity,核心功能都在mMainThread.getApplicationThread()中完成

Instrumentation.ActivityResult

ar

=

mInstrumentation.execStartActivity(

this,

mMainThread.getApplicationThread(),

mToken,

this,

intent,

requestCode,

options);

if

(ar

!=

null)

{

//发送结果,即onActivityResult会被调用

mMainThread.sendActivityResult(

mToken,

mEmbeddedID,

requestCode,

ar.getResultCode(),

ar.getResultData());

}

if

(requestCode

>=

0)

{

//

If

this

start

is

requesting

a

result,

we

can

avoid

making

//

the

activity

visible

until

the

result

is

received.

Setting

//

this

code

during

onCreate(Bundle

savedInstanceState)

or

onResume()

will

keep

the

//

activity

hidden

during

this

time,

to

avoid

flickering.

//

This

can

only

be

done

when

a

result

is

requested

because

//

that

guarantees

we

will

get

information

back

when

the

//

activity

is

finished,

no

matter

what

happens

to

it.

mStartedActivity

=

true;

}

final

View

decor

=

mWindow

!=

null

?

mWindow.peekDecorView()

:

null;

if

(decor

!=

null)

{

decor.cancelPendingInputEvents();

}

//

TODO

Consider

clearing/flushing

other

event

sources

and

events

for

child

windows.

}

else

{

//在ActivityGroup内部的Activity调用startActivity的时候会走到这里,内部处理逻辑和上面是类似的

if

(options

!=

null)

{

mParent.startActivityFromChild(this,

intent,

requestCode,

options);

}

else

{

//

Note

we

want

to

go

through

this

method

for

compatibility

with

//

existing

applications

that

may

have

overridden

it.

mParent.startActivityFromChild(this,

intent,

requestCode);

}

}

}说明:上述代码关键点都有注释了,可以发现,真正打开activity的实现在Instrumentation的execStartActivity方法中,去看看code:Instrumentation#execStartActivitypublic

ActivityResult

execStartActivity(

Context

who,

IBinder

contextThread,

IBinder

token,

Activity

target,

Intent

intent,

int

requestCode,

Bundle

options)

{

//核心功能在这个whoThread中完成,其内部scheduleLaunchActivity方法用于完成activity的打开

IApplicationThread

whoThread

=

(IApplicationThread)

contextThread;

if

(mActivityMonitors

!=

null)

{

synchronized

(mSync)

{

//先查找一遍看是否存在这个activity

final

int

N

=

mActivityMonitors.size();

for

(int

i=0;

i<N;

i++)

{

final

ActivityMonitor

am

=

mActivityMonitors.get(i);

if

(am.match(who,

null,

intent))

{

//如果找到了就跳出循环

am.mHits++;

//如果目标activity无法打开,直接return

if

(am.isBlocking())

{

return

requestCode

>=

0

?

am.getResult()

:

null;

}

break;

}

}

}

}

try

{

intent.migrateExtraStreamToClipData();

intent.prepareToLeaveProcess();

//这里才是真正打开activity的地方,核心功能在whoThread中完成。

int

result

=

ActivityManagerNative.getDefault()

.startActivity(whoThread,

who.getBasePackageName(),

intent,

intent.resolveTypeIfNeeded(who.getContentResolver()),

token,

target

!=

null

?

target.mEmbeddedID

:

null,

requestCode,

0,

null,

null,

options);

//这个方法是专门抛异常的,它会对结果进行检查,如果无法打开activity,

//则抛出诸如ActivityNotFoundException类似的各种异常

checkStartActivityResult(result,

intent);

}

catch

(RemoteException

e)

{

}

return

null;

}说明:我想再说一下这个方法checkStartActivityResult,它也专业抛异常的,看代码,相信大家对下面的异常信息不陌生吧,就是它干的,其中最熟悉的非Unabletofindexplicitactivityclass莫属了,如果你在xml中没有注册目标activity,此异常将会抛出。/*package*/

static

void

checkStartActivityResult(int

res,

Object

intent)

{

if

(res

>=

ActivityManager.START_SUCCESS)

{

return;

}

switch

(res)

{

case

ActivityManager.START_INTENT_NOT_RESOLVED:

case

ActivityManager.START_CLASS_NOT_FOUND:

if

(intent

instanceof

Intent

&&

((Intent)intent).getComponent()

!=

null)

throw

new

ActivityNotFoundException(

"Unable

to

find

explicit

activity

class

"

+

((Intent)intent).getComponent().toShortString()

+

";

have

you

declared

this

activity

in

your

AndroidManifest.xml?");

throw

new

ActivityNotFoundException(

"No

Activity

found

to

handle

"

+

intent);

case

ActivityManager.START_PERMISSION_DENIED:

throw

new

SecurityException("Not

allowed

to

start

activity

"

+

intent);

case

ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:

throw

new

AndroidRuntimeException(

"FORWARD_RESULT_FLAG

used

while

also

requesting

a

result");

case

ActivityManager.START_NOT_ACTIVITY:

throw

new

IllegalArgumentException(

"PendingIntent

is

not

an

activity");

default:

throw

new

AndroidRuntimeException("Unknown

error

code

"

+

res

+

"

when

starting

"

+

intent);

}

}接下来我们要去看看IApplicationThread,因为核心功能由其内部的scheduleLaunchActivity方法来完成,由于IApplicationThread是个接口,所以,我们需要找到它的实现类,我已经帮大家找到了,它就是ActivityThread中的内部类ApplicationThread,看下它的继承关系:privateclassApplicationThreadextendsApplicationThreadNative;publicabstractclassApplicationThreadNativeextendsBinderimplementsIApplicationThread;可以发现,ApplicationThread还是间接实现了IApplicationThread接口,先看下这个类的结构看完ApplicationThread的大致结构,我们应该能够猜测到,Activity的生命周期中的resume、newIntent、pause、stop等事件都是由它触发的,事实上,的确是这样的。这里,我们为了说明问题,仅仅看scheduleLaunchActivity方法code:ApplicationThread#scheduleLaunchActivitypublic

final

void

scheduleLaunchActivity(Intent

intent,

IBinder

token,

int

ident,

ActivityInfo

info,

Configuration

curConfig,

CompatibilityInfo

compatInfo,

int

procState,

Bundle

state,

List<ResultInfo>

pendingResults,

List<Intent>

pendingNewIntents,

boolean

notResumed,

boolean

isForward,

String

profileName,

ParcelFileDescriptor

profileFd,

boolean

autoStopProfiler)

{

updateProcessState(procState,

false);

ActivityClientRecord

r

=

new

ActivityClientRecord();

r.token

=

token;

r.ident

=

ident;

ent

=

intent;

r.activityInfo

=

info;

patInfo

=

compatInfo;

r.state

=

state;

r.pendingResults

=

pendingResults;

r.pendingIntents

=

pendingNewIntents;

r.startsNotResumed

=

notResumed;

r.isForward

=

isForward;

fileFile

=

profileName;

fileFd

=

profileFd;

r.autoStopProfiler

=

autoStopProfiler;

updatePendingConfiguration(curConfig);

queueOrSendMessage(H.LAUNCH_ACTIVITY,

r);

}说明:上述代码很好理解,构造一个activity记录,然后发送一个消息,所以,我们要看看Handler是如何处理这个消息的,现在转到这个Handler,它有个很短的名字叫做Hcode:ActivityThread#H//这个类太长,我只帖出了我们用到的部分

private

class

H

extends

Handler

{

public

void

handleMessage(Message

msg)

{

if

(DEBUG_MESSAGES)

Slog.v(TAG,

">>>

handling:

"

+

codeToString(msg.what));

switch

(msg.what)

{

//这里处理LAUNCH_ACTIVITY消息类型

case

LAUNCH_ACTIVITY:

{

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,

"activityStart");

ActivityClientRecord

r

=

(ActivityClientRecord)msg.obj;

r.packageInfo

=

getPackageInfoNoCheck(

r.activityInfo.applicationInfo,

patInfo);

//这里处理startActivity消息

handleLaunchActivity(r,

null);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

}

break;

case

RELAUNCH_ACTIVITY:

{

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,

"activityRestart");

ActivityClientRecord

r

=

(ActivityClientRecord)msg.obj;

handleRelaunchActivity(r);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

}

break;

case

PAUSE_ACTIVITY:

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,

"activityPause");

handlePauseActivity((IBinder)msg.obj,

false,

msg.arg1

!=

0,

msg.arg2);

maybeSnapshot();

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

break;

...

}

}说明:看来还要看handleLaunchActivitycode:ActivityThread#handleLaunchActivityprivate

void

handleLaunchActivity(ActivityClientRecord

r,

Intent

customIntent)

{

//

If

we

are

getting

ready

to

gc

after

going

to

the

background,

well

//

we

are

back

active

so

skip

it.

unscheduleGcIdler();

if

(fileFd

!=

null)

{

mProfiler.setProfiler(fileFile,

fileFd);

mProfiler.startProfiling();

mProfiler.autoStopProfiler

=

r.autoStopProfiler;

}

//

Make

sure

we

are

running

with

the

most

recent

config.

handleConfigurationChanged(null,

null);

if

(localLOGV)

Slog.v(

TAG,

"Handling

launch

of

"

+

r);

//终于到底了,大家都有点不耐烦了吧,从方法名可以看出,

//performLaunchActivity真正完成了activity的调起,

//同时activity会被实例化,并且onCreate会被调用

Activity

a

=

performLaunchActivity(r,

customIntent);

if

(a

!=

null)

{

r.createdConfig

=

new

Configuration(mConfiguration);

Bundle

oldState

=

r.state;

//看到没,目标activity的onResume会被调用

handleResumeActivity(r.token,

false,

r.isForward,

!r.activity.mFinished

&&

!r.startsNotResumed);

if

(!r.activity.mFinished

&&

r.startsNotResumed)

{

//

The

activity

manager

actually

wants

this

one

to

start

out

//

paused,

because

it

needs

to

be

visible

but

isn't

in

the

//

foreground.

We

accomplish

this

by

going

through

the

//

normal

startup

(because

activities

expect

to

go

through

//

onResume()

the

first

time

they

run,

before

their

window

//

is

displayed),

and

then

pausing

it.

However,

in

this

case

//

we

do

-not-

need

to

do

the

full

pause

cycle

(of

freezing

//

and

such)

because

the

activity

manager

assumes

it

can

just

//

retain

the

current

state

it

has.

try

{

r.activity.mCalled

=

false;

//同时,由于新activity被调起了,原activity的onPause会被调用

mInstrumentation.callActivityOnPause(r.activity);

//

We

need

to

keep

around

the

original

state,

in

case

//

we

need

to

be

created

again.

But

we

only

do

this

//

for

pre-Honeycomb

apps,

which

always

save

their

state

//

when

pausing,

so

we

can

not

have

them

save

their

state

//

when

restarting

from

a

paused

state.

For

HC

and

later,

//

we

want

to

(and

can)

let

the

state

be

saved

as

the

normal

//

part

of

stopping

the

activity.

if

(r.isPreHoneycomb())

{

r.state

=

oldState;

}

if

(!r.activity.mCalled)

{

throw

new

SuperNotCalledException(

"Activity

"

+

ent.getComponent().toShortString()

+

"

did

not

call

through

to

super.onPause()");

}

}

catch

(SuperNotCalledException

e)

{

throw

e;

}

catch

(Exception

e)

{

if

(!mInstrumentation.onException(r.activity,

e))

{

throw

new

RuntimeException(

"Unable

to

pause

activity

"

+

ent.getComponent().toShortString()

+

":

"

+

e.toString(),

e);

}

}

r.paused

=

true;

}

}

else

{

//

If

there

was

an

error,

for

any

reason,

tell

the

activity

//

manager

to

stop

us.

try

{

ActivityManagerNative.getDefault()

.finishActivity(r.token,

Activity.RESULT_CANCELED,

null);

}

catch

(RemoteException

ex)

{

//

Ignore

}

}

}说明:关于原activity和新activity之间的状态同步,如果大家感兴趣可以自己研究下,因为逻辑太复杂,我没法把所有问题都说清楚,否则就太深入细节而淹没了整体逻辑,研究源码要的就是清楚整体逻辑。下面看最后一个方法,这个方法是activity的启动过程的真正实现。code:ActivityThread#performLaunchActivityprivate

Activity

performLaunchActivity(ActivityClientRecord

r,

Intent

customIntent)

{

//

System.out.println("#####

["

+

System.currentTimeMillis()

+

"]

ActivityThread.performLaunchActivity("

+

r

+

")");

ActivityInfo

aInfo

=

r.activityInfo;

if

(r.packageInfo

==

null)

{

r.packageInfo

=

getPackageInfo(aInfo.applicationInfo,

patInfo,

Context.CONTEXT_INCLUDE_CODE);

}

//首先从intent中解析出目标activity的启动参数

ComponentName

component

=

ent.getComponent();

if

(component

==

null)

{

component

=

ent.resolveActivity(

mInitialApplication.getPackageManager());

ent.setComponent(component);

}

if

(r.activityInfo.targetActivity

!=

null)

{

component

=

new

ComponentName(r.activityInfo.packageName,

r.activityInfo.targetActivity);

}

Activity

activity

=

null;

try

{

java.lang.ClassLoader

cl

=

r.packageInfo.getClassLoader();

//用ClassLoader(类加载器)将目标activity的类通过类名加载进来并调用newInstance来实例化一个对象

//其实就是通过Activity的无参构造方法来new一个对象,对象就是在这里new出来的。

activity

=

mInstrumentation.newActivity(

cl,

component.getClassName(),

ent);

StrictMode.incrementExpectedActivityCount(activity.getClass());

ent.setExtrasClassLoader(cl);

if

(r.state

!=

null)

{

r.state.setClassLoader(cl);

}

}

catch

(Exception

e)

{

if

(!mInstrumentation.onException(activity,

e))

{

throw

new

RuntimeException(

"Unable

to

instantiate

activity

"

+

component

+

":

"

+

e.toString(),

e);

}

}

try

{

Application

app

=

r.packageInfo.makeApplication(false,

mInstrumentation);

if

(localLOGV)

Slog.v(TAG,

"Performing

launch

of

"

+

r);

if

(localLOGV)

Slog.v(

TAG,

r

+

":

app="

+

app

+

",

appName="

+

app.getPackageName()

+

",

pkg="

+

r.packageInfo.getPackageName()

+

",

comp="

+

ent.getComponent().toShortString()

+

",

dir="

+

r.packageInfo.getAppDir());

if

(activity

!=

null)

{

Context

appContext

=

createBaseContextForActivity(r,

activity);

CharSequence

title

=

r.activityInfo.loadLabel(appContext.getPackageManager());

Configuration

config

=

new

Configuration(mCompatConfiguration);

if

(DEBUG_CONFIGURATION)

Slog.v(TAG,

"Launching

activity

"

+

r.activityI

+

"

with

config

"

+

config);

activity.attach(appContext,

this,

getInstrumentation(),

r.token,

r.ident,

app,

ent,

r.activityInfo,

title,

r.parent,

r.embeddedID,

r.lastNonConfigurationInstances,

config);

if

(customIntent

!=

null)

{

a

温馨提示

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

评论

0/150

提交评论