【移动应用开发技术】怎么浅析Activity的渲染过程_第1页
【移动应用开发技术】怎么浅析Activity的渲染过程_第2页
【移动应用开发技术】怎么浅析Activity的渲染过程_第3页
【移动应用开发技术】怎么浅析Activity的渲染过程_第4页
【移动应用开发技术】怎么浅析Activity的渲染过程_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

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

文档简介

【移动应用开发技术】怎么浅析Activity的渲染过程

今天就跟大家聊聊有关怎么浅析Activity的渲染过程,可能很多人都不太了解,为了让大家更加了解,在下给大家总结了以下内容,希望大家根据这篇文章可以有所收获。####以下代码基于API251.Activity是如何展现在我们眼前的?我大概知道UI方面是和Window相关的,而activity的attach方法会传入一个window对象,所以就从activity的attach方法入手:

attach方法里会创建一个PhoneWindow

activity在执行onCreate方法的时候都会执行一个方法performCreateCommon

点击setEnterActivityOptions方法:

注意window.getDecorView()这个方法/**

*Retrievethetop-levelwindowdecorview(containingthestandard

*windowframe/decorationsandtheclient'scontentinsideofthat),which

*canbeaddedasawindowtothewindowmanager.

*

*<p><em>Notethatcallingthisfunctionforthefirsttime"locksin"

*variouswindowcharacteristicsasdescribedin

*{@link#setContentView(View,android.view.ViewGroup.LayoutParams)}.</em></p>

*

*@returnReturnsthetop-levelwindowdecorview.

*/publicabstractViewgetDecorView();

官方的解释是说这个方法是获取了顶层window的decorview。

这里的window很明显是PhoneWindow,看它对getDecorView的实现。

mDecor其实在PhoneWindow的构造方法里就已经生成了preservedWindow向上追溯其来源:从onCreate里其实根本就找不到activity显示相关的源码,于是只能看看其他人怎么分析的。/jiaocheng/6995.html

(道中重点)/snow-flower/p/6111599.html/monkey646812329/article/details/52885835if

(r.window

==

null

&&

!a.mFinished

&&

willBeVisible)

{

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

&&

!a.mWindowAdded)

{

a.mWindowAdded

=

true;

wm.addView(decor,

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;

}看上面的源码得到PhoneWindow对象

r.window

=

r.activity.getWindow();

View

decor

=

r.window.getDecorView();

从PhoneWindow获取DecorView并赋值给activity

a.mDecor

=

decor;通过WindowManager添加decorwm.addView(decor,

l);这样activity就展示在我们眼前了。关于WindowManager更加底层的源码后探讨。2.Activity的setContentView方法/**

*

Set

the

activity

content

from

a

layout

resource.

The

resource

will

be

*

inflated,

adding

all

top-level

views

to

the

activity.

*

*

@param

layoutResID

Resource

ID

to

be

inflated.

*

*

@see

#setContentView(android.view.View)

*

@see

#setContentView(android.view.View,

android.view.ViewGroup.LayoutParams)

*/

public

void

setContentView(@LayoutRes

int

layoutResID)

{

getWindow().setContentView(layoutResID);

initWindowDecorActionBar();

}

/**

*

Set

the

activity

content

to

an

explicit

view.

This

view

is

placed

*

directly

into

the

activity's

view

hierarchy.

It

can

itself

be

a

complex

*

view

hierarchy.

When

calling

this

method,

the

layout

parameters

of

the

*

specified

view

are

ignored.

Both

the

width

and

the

height

of

the

view

are

*

set

by

default

to

{@link

ViewGroup.LayoutParams#MATCH_PARENT}.

To

use

*

your

own

layout

parameters,

invoke

*

{@link

#setContentView(android.view.View,

android.view.ViewGroup.LayoutParams)}

*

instead.

*

*

@param

view

The

desired

content

to

display.

*

*

@see

#setContentView(int)

*

@see

#setContentView(android.view.View,

android.view.ViewGroup.LayoutParams)

*/

public

void

setContentView(View

view)

{

getWindow().setContentView(view);

initWindowDecorActionBar();

}

/**

*

Set

the

activity

content

to

an

explicit

view.

This

view

is

placed

*

directly

into

the

activity's

view

hierarchy.

It

can

itself

be

a

complex

*

view

hierarchy.

*

*

@param

view

The

desired

content

to

display.

*

@param

params

Layout

parameters

for

the

view.

*

*

@see

#setContentView(android.view.View)

*

@see

#setContentView(int)

*/

public

void

setContentView(View

view,

ViewGroup.LayoutParams

params)

{

getWindow().setContentView(view,

params);

initWindowDecorActionBar();

}

/**

*

Add

an

additional

content

view

to

the

activity.

Added

after

any

existing

*

ones

in

the

activity

--

existing

views

are

NOT

removed.

*

*

@param

view

The

desired

content

to

display.

*

@param

params

Layout

parameters

for

the

view.

*/

public

void

addContentView(View

view,

ViewGroup.LayoutParams

params)

{

getWindow().addContentView(view,

params);

initWindowDecorActionBar();

}

关于填充view,activity有4种方法。下面先讨论最常用的方法public

void

setContentView(@LayoutRes

int

layoutResID)

{

getWindow().setContentView(layoutResID);

initWindowDecorActionBar();

}第一步调用PhoneWindow的对应的方法(注意观察源码会发现,activity的绝大多数的方法都是在操作PhoneWindow)第二步初始化ActionBar先看看PhoneWindow的源码@Override

public

void

setContentView(int

layoutResID)

{

//

Note:

FEATURE_CONTENT_TRANSITIONS

may

be

set

in

the

process

of

installing

the

window

//

decor,

when

theme

attributes

and

the

like

are

crystalized.

Do

not

check

the

feature

//

before

this

happens.

if

(mContentParent

==

null)

{

installDecor();

}

else

if

(!hasFeature(FEATURE_CONTENT_TRANSITIONS))

{

mContentParent.removeAllViews();

}

if

(hasFeature(FEATURE_CONTENT_TRANSITIONS))

{

final

Scene

newScene

=

Scene.getSceneForLayout(mContentParent,

layoutResID,

getContext());

transitionTo(newScene);

}

else

{

mLayoutInflater.inflate(layoutResID,

mContentParent);

}

mContentParent.requestApplyInsets();

final

Callback

cb

=

getCallback();

if

(cb

!=

null

&&

!isDestroyed())

{

cb.onContentChanged();

}

mContentParentExplicitlySet

=

true;

}最开始程序应该是走了installDecor方法这个方法比较长,它负责的业务主要有以下几项。如果decor为null,创建PhoneWindow的decor,已经存在decor则与PhoneWindow绑定。如果mContentParent为null,通过decor创建mContentParent。转场动画的处理private

void

installDecor()

{

mForceDecorInstall

=

false;

if

(mDecor

==

null)

{

mDecor

=

generateDecor(-1);

mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

mDecor.setIsRootNamespace(true);

if

(!mInvalidatePanelMenuPosted

&&

mInvalidatePanelMenuFeatures

!=

0)

{

mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);

}

}

else

{

mDecor.setWindow(this);

}

if

(mContentParent

==

null)

{

mContentParent

=

generateLayout(mDecor);

//

Set

up

decor

part

of

UI

to

ignore

fitsSystemWindows

if

appropriate.

mDecor.makeOptionalFitsSystemWindows();

final

DecorContentParent

decorContentParent

=

(DecorContentParent)

mDecor.findViewById(

R.id.decor_content_parent);

if

(decorContentParent

!=

null)

{

mDecorContentParent

=

decorContentParent;

mDecorContentParent.setWindowCallback(getCallback());

if

(mDecorContentParent.getTitle()

==

null)

{

mDecorContentParent.setWindowTitle(mTitle);

}

final

int

localFeatures

=

getLocalFeatures();

for

(int

i

=

0;

i

<

FEATURE_MAX;

i++)

{

if

((localFeatures

&

(1

<<

i))

!=

0)

{

mDecorContentParent.initFeature(i);

}

}

mDecorContentParent.setUiOptions(mUiOptions);

if

((mResourcesSetFlags

&

FLAG_RESOURCE_SET_ICON)

!=

0

||

(mIconRes

!=

0

&&

!mDecorContentParent.hasIcon()))

{

mDecorContentParent.setIcon(mIconRes);

}

else

if

((mResourcesSetFlags

&

FLAG_RESOURCE_SET_ICON)

==

0

&&

mIconRes

==

0

&&

!mDecorContentParent.hasIcon())

{

mDecorContentParent.setIcon(

getContext().getPackageManager().getDefaultActivityIcon());

mResourcesSetFlags

|=

FLAG_RESOURCE_SET_ICON_FALLBACK;

}

if

((mResourcesSetFlags

&

FLAG_RESOURCE_SET_LOGO)

!=

0

||

(mLogoRes

!=

0

&&

!mDecorContentParent.hasLogo()))

{

mDecorContentParent.setLogo(mLogoRes);

}

//

Invalidate

if

the

panel

menu

hasn't

been

created

before

this.

//

Panel

menu

invalidation

is

deferred

avoiding

application

onCreateOptionsMenu

//

being

called

in

the

middle

of

onCreate

or

similar.

//

A

pending

invalidation

will

typically

be

resolved

before

the

posted

message

//

would

run

normally

in

order

to

satisfy

instance

state

restoration.

PanelFeatureState

st

=

getPanelState(FEATURE_OPTIONS_PANEL,

false);

if

(!isDestroyed()

&&

(st

==

null

||

st.menu

==

null)

&&

!mIsStartingWindow)

{

invalidatePanelMenu(FEATURE_ACTION_BAR);

}

}

else

{

mTitleView

=

(TextView)

findViewById(R.id.title);

if

(mTitleView

!=

null)

{

if

((getLocalFeatures()

&

(1

<<

FEATURE_NO_TITLE))

!=

0)

{

final

View

titleContainer

=

findViewById(R.id.title_container);

if

(titleContainer

!=

null)

{

titleContainer.setVisibility(View.GONE);

}

else

{

mTitleView.setVisibility(View.GONE);

}

mContentParent.setForeground(null);

}

else

{

mTitleView.setText(mTitle);

}

}

}

if

(mDecor.getBackground()

==

null

&&

mBackgroundFallbackResource

!=

0)

{

mDecor.setBackgroundFallback(mBackgroundFallbackResource);

}

//

Only

inflate

or

create

a

new

TransitionManager

if

the

caller

hasn't

//

already

set

a

custom

one.

if

(hasFeature(FEATURE_ACTIVITY_TRANSITIONS))

{

if

(mTransitionManager

==

null)

{

final

int

transitionRes

=

getWindowStyle().getResourceId(

R.styleable.Window_windowContentTransitionManager,

0);

if

(transitionRes

!=

0)

{

final

TransitionInflater

inflater

=

TransitionInflater.from(getContext());

mTransitionManager

=

inflater.inflateTransitionManager(transitionRes,

mContentParent);

}

else

{

mTransitionManager

=

new

TransitionManager();

}

}

mEnterTransition

=

getTransition(mEnterTransition,

null,

R.styleable.Window_windowEnterTransition);

mReturnTransition

=

getTransition(mReturnTransition,

USE_DEFAULT_TRANSITION,

R.styleable.Window_windowReturnTransition);

mExitTransition

=

getTransition(mExitTransition,

null,

R.styleable.Window_windowExitTransition);

mReenterTransition

=

getTransition(mReenterTransition,

USE_DEFAULT_TRANSITION,

R.styleable.Window_windowReenterTransition);

mSharedElementEnterTransition

=

getTransition(mSharedElementEnterTransition,

null,

R.styleable.Window_windowSharedElementEnterTransition);

mSharedElementReturnTransition

=

getTransition(mSharedElementReturnTransition,

USE_DEFAULT_TRANSITION,

R.styleable.Window_windowSharedElementReturnTransition);

mSharedElementExitTransition

=

getTransition(mSharedElementExitTransition,

null,

R.styleable.Window_windowSharedElementExitTransition);

mSharedElementReenterTransition

=

getTransition(mSharedElementReenterTransition,

USE_DEFAULT_TRANSITION,

R.styleable.Window_windowSharedElementReenterTransition);

if

(mAllowEnterTransitionOverlap

==

null)

{

mAllowEnterTransitionOverlap

=

getWindowStyle().getBoolean(

R.styleable.Window_windowAllowEnterTransitionOverlap,

true);

}

if

(mAllowReturnTransitionOverlap

==

null)

{

mAllowReturnTransitionOverlap

=

getWindowStyle().getBoolean(

R.styleable.Window_windowAllowReturnTransitionOverlap,

true);

}

if

(mBackgroundFadeDurationMillis

<

0)

{

mBackgroundFadeDurationMillis

=

getWindowStyle().getInteger(

R.styleable.Window_windowTransitionBackgroundFadeDuration,

DEFAULT_BACKGROUND_FADE_DURATION_MS);

}

if

(mSharedElementsUseOverlay

==

null)

{

mSharedElementsUseOverlay

=

getWindowStyle().getBoolean(

R.styleable.Window_windowSharedElementsUseOverlay,

true);

}

}

}

}对上面的方法主要节点剖析

推荐结合这篇博客Andriod中Style/Theme原理以及Activity界面文件选取过程浅析来看这个方法的源码protected

ViewGroup

generateLayout(DecorView

decor)

{

//

Apply

data

from

current

theme.

TypedArray

a

=

getWindowStyle();

...//根据window

style设置window的属性

WindowManager.LayoutParams

params

=

getAttributes();

//

Non-floating

windows

on

high

end

devices

must

put

up

decor

beneath

the

system

bars

and

//

therefore

must

know

about

visibility

changes

of

those.

if

(!mIsFloating

&&

ActivityManager.isHighEndGfx())

{

if

(!targetPreL

&&

a.getBoolean(

R.styleable.Window_windowDrawsSystemBarBackgrounds,

false))

{

setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,

FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS

&

~getForcedWindowFlags());

}

if

(mDecor.mForceWindowDrawsStatusBarBackground)

{

params.privateFlags

|=

PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;

}

}

if

(a.getBoolean(R.styleable.Window_windowLightStatusBar,

false))

{

decor.setSystemUiVisibility(

decor.getSystemUiVisibility()

|

View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

}

if

(mAlwaysReadCloseOnTouchAttr

||

getContext().getApplicationInfo().targetSdkVersion

>=

android.os.Build.VERSION_CODES.HONEYCOMB)

{

if

(a.getBoolean(

R.styleable.Window_windowCloseOnTouchOutside,

false))

{

setCloseOnTouchOutsideIfNotSet(true);

}

}

if

(!hasSoftInputMode())

{

params.softInputMode

=

a.getInt(

R.styleable.Window_windowSoftInputMode,

params.softInputMode);

}

if

(a.getBoolean(R.styleable.Window_backgroundDimEnabled,

mIsFloating))

{

/*

All

dialogs

should

have

the

window

dimmed

*/

if

((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND)

==

0)

{

params.flags

|=

WindowManager.LayoutParams.FLAG_DIM_BEHIND;

}

if

(!haveDimAmount())

{

params.dimAmount

=

a.getFloat(

android.R.styleable.Window_backgroundDimAmount,

0.5f);

}

}

if

(params.windowAnimations

==

0)

{

params.windowAnimations

=

a.getResourceId(

R.styleable.Window_windowAnimationStyle,

0);

}

//

The

rest

are

only

done

if

this

window

is

not

embedded;

otherwise,

//

the

values

are

inherited

from

our

container.

if

(getContainer()

==

null)

{

if

(mBackgroundDrawable

==

null)

{

if

(mBackgroundResource

==

0)

{

mBackgroundResource

=

a.getResourceId(

R.styleable.Window_windowBackground,

0);

}

if

(mFrameResource

==

0)

{

mFrameResource

=

a.getResourceId(R.styleable.Window_windowFrame,

0);

}

mBackgroundFallbackResource

=

a.getResourceId(

R.styleable.Window_windowBackgroundFallback,

0);

if

(false)

{

System.out.println("Background:

"

+

Integer.toHexString(mBackgroundResource)

+

"

Frame:

"

+

Integer.toHexString(mFrameResource));

}

}

if

(mLoadElevation)

{

mElevation

=

a.getDimension(R.styleable.Window_windowElevation,

0);

}

mClipToOutline

=

a.getBoolean(R.styleable.Window_windowClipToOutline,

false);

mTextColor

=

a.getColor(R.styleable.Window_textColor,

Color.TRANSPARENT);

}

//

Inflate

the

window

decor.

int

layoutResource;

int

features

=

getLocalFeatures();

//

System.out.println("Features:

0x"

+

Integer.toHexString(features));

if

((features

&

(1

<<

FEATURE_SWIPE_TO_DISMISS))

!=

0)

{

layoutResource

=

R.layout.screen_swipe_dismiss;

}

else

if

((features

&

((1

<<

FEATURE_LEFT_ICON)

|

(1

<<

FEATURE_RIGHT_ICON)))

!=

0)

{

if

(mIsFloating)

{

TypedValue

res

=

new

TypedValue();

getContext().getTheme().resolveAttribute(

R.attr.dialogTitleIconsDecorLayout,

res,

true);

layoutResource

=

res.resourceId;

}

else

{

layoutResource

=

R.layout.screen_title_icons;

}

//

XXX

Remove

this

once

action

bar

supports

these

features.

removeFeature(FEATURE_ACTION_BAR);

//

System.out.println("Title

Icons!");

}

else

if

((features

&

((1

<<

FEATURE_PROGRESS)

|

(1

<<

FEATURE_INDETERMINATE_PROGRESS)))

!=

0

&&

(features

&

(1

<<

FEATURE_ACTION_BAR))

==

0)

{

//

Special

case

for

a

window

with

only

a

progress

bar

(and

title).

//

XXX

Need

to

have

a

no-title

version

of

embedded

windows.

layoutResource

=

R.layout.screen_progress;

//

System.out.println("Progress!");

}

else

if

((features

&

(1

<<

FEATURE_CUSTOM_TITLE))

!=

0)

{

//

Special

case

for

a

window

with

a

custom

title.

//

If

the

window

is

floating,

we

need

a

dialog

layout

if

(mIsFloating)

{

TypedValue

res

=

new

TypedValue();

getContext().getTheme().resolveAttribute(

R.attr.dialogCustomTitleDecorLayout,

res,

true);

layoutResource

=

res.resourceId;

}

else

{

layoutResource

=

R.layout.screen_custom_title;

}

//

XXX

Remove

this

once

action

bar

supports

these

features.

removeFeature(FEATURE_ACTION_BAR);

}

else

if

((features

&

(1

<<

FEATURE_NO_TITLE))

==

0)

{

//

If

no

other

features

and

not

embedded,

only

need

a

title.

//

If

the

window

is

floating,

we

need

a

dialog

layout

if

(mIsFloating)

{

TypedValue

res

=

new

TypedValue();

getContext().getTheme().resolveAttribute(

R.attr.dialogTitleDecorLayout,

res,

true);

layoutResource

=

res.resourceId;

}

else

if

((features

&

(1

<<

FEATURE_ACTION_BAR))

!=

0)

{

layoutResource

=

a.getResourceId(

R.styleable.Window_windowActionBarFullscreenDecorLayout,

R.layout.screen_action_bar);

}

else

{

layoutResource

=

R.layout.screen_title;

}

//

System.out.println("Title!");

}

else

if

((features

&

(1

<<

FEATURE_ACTION_MODE_OVERLAY))

!=

0)

{

layoutResource

=

R.layout.screen_simple_overlay_action_mode;

}

else

{

//

Embedded,

so

no

decoration

is

needed.

layoutResource

=

R.layout.screen_simple;

//

System.out.println("Simple!");

}

mDecor.startChanging();

mDecor.onResourcesLoaded(mLayout

温馨提示

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

评论

0/150

提交评论