版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】怎么浅析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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 福建省龙岩市达标名校2024届中考语文考试模拟冲刺卷含解析
- (中考试题)2024年浙江省绍兴市中考数学真题试卷解析版
- 陕西省西安地区八校2024年高三第六次模拟考试数学试卷含解析
- 福建省泉州市永春县重点达标名校2022年初中化学毕业考试模拟冲刺卷含解析
- 2024年合成材料助剂项目融资计划书
- 金学导航2023-2024学年高三3月份第一次模拟考试数学试卷含解析
- 2024年放电线圈项目营销方案
- 2024年电动汽车项目经营分析报告
- 2024年油橄榄果提取物化妆品项目经营分析报告
- 辛集市弘百机械有限公司新建年产300万件(套)机械配件项目环境影响报告表
- 硫堇的电化学性质
- 高万忠老师《打造团队凝聚力》课程大纲
- 功能性蛤蜊肽粉标准征求意见稿
- 临床试验中的统计学要求
- 彻底修复激光头诀窍
- 工业危害分析记录表次氯酸钠
- 备件修复管理办法正式版
- 紧固件验收规范
- 东南大学基础工程试题库
- 单位请假条模板(共1页)
- 广州牛津版八年级上册英语新版单词表(默写版)
评论
0/150
提交评论