睿智的充值卡 · 重大变化!高速公路省界收费站年底前取消,这件 ...· 3 周前 · |
酒量小的眼镜 · 钢铁雄心4dlc推荐? - 知乎用户 ...· 1 年前 · |
玩篮球的甘蔗 · 钢铁魔女在哪里观看 - 头条搜索· 1 年前 · |
public
void
layout
(
int
l
,
int
t
,
int
r
,
int
b
)
{
if
(
DBG_SYSTRACE_LAYOUT
)
{
Trace
.
traceBegin
(
Trace
.
TRACE_TAG_VIEW
,
"layout : "
+
getClass
().
getSimpleName
());
}
// !=0 表示在measure 的时候设置这个标志,也就是measure的时候根据measure cache 测量,而不是直接调用onMeasure(),所以这里要重新onMeasure一次
if
((
mPrivateFlags3
&
PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
)
!=
0
)
{
/// M: Monitor onLayout time if longer than 3s print log.
if
(
DBG_LAYOUT
||
DBG_MEASURE_LAYOUT
)
{
Xlog
.
d
(
VIEW_LOG_TAG
,
"view onMeasure start (measure cache), this ="
+
this
+
", widthMeasureSpec = "
+
MeasureSpec
.
toString
(
mOldWidthMeasureSpec
)
+
", heightMeasureSpec = "
+
MeasureSpec
.
toString
(
mOldHeightMeasureSpec
));
}
long
logTime
=
System
.
currentTimeMillis
();
onMeasure
(
mOldWidthMeasureSpec
,
mOldHeightMeasureSpec
);
long
nowTime
=
System
.
currentTimeMillis
();
if
(
nowTime
-
logTime
>
DBG_TIMEOUT_VALUE
)
{
Xlog
.
d
(
VIEW_LOG_TAG
,
"[ANR Warning]onMeasure time too long, this ="
+
this
+
"time ="
+
(
nowTime
-
logTime
)
+
" ms"
);
}
if
(
DBG_LAYOUT
||
DBG_MEASURE_LAYOUT
)
{
Xlog
.
d
(
VIEW_LOG_TAG
,
"view onMeasure end (measure cache), this ="
+
this
+
", mMeasuredWidth = "
+
mMeasuredWidth
+
", mMeasuredHeight = "
+
mMeasuredHeight
+
", time ="
+
(
nowTime
-
logTime
)
+
" ms"
);
}
mPrivateFlags3
&=
~
PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
;
//将标志位恢复
}
int
oldL
=
mLeft
;
int
oldT
=
mTop
;
int
oldB
=
mBottom
;
int
oldR
=
mRight
;
//视觉/光学边界布局,一般是false
boolean
changed
=
isLayoutModeOptical
(
mParent
)
?
setOpticalFrame
(
l
,
t
,
r
,
b
)
:
setFrame
(
l
,
t
,
r
,
b
);
if
(
DBG_LAYOUT
||
DBG_MEASURE_LAYOUT
)
{
Xlog
.
d
(
VIEW_LOG_TAG
,
"view layout start, this = "
+
this
+
", mLeft = "
+
mLeft
+
", mTop = "
+
mTop
+
", mRight = "
+
mRight
+
", mBottom = "
+
mBottom
+
", changed = "
+
changed
);
}
//PFLAG_LAYOUT_REQUIRED这个标志也是在measure 的时候设置的.
if
(
changed
||
(
mPrivateFlags
&
PFLAG_LAYOUT_REQUIRED
)
==
PFLAG_LAYOUT_REQUIRED
)
{
/// M: Monitor onLayout time if longer than 3s print log.
long
logTime
=
System
.
currentTimeMillis
();
onLayout
(
changed
,
l
,
t
,
r
,
b
);
//这个方法view和ViewGroup都没有实现,具体是有子类去实现
long
nowTime
=
System
.
currentTimeMillis
();
if
(
nowTime
-
logTime
>
DBG_TIMEOUT_VALUE
)
{
Xlog
.
d
(
VIEW_LOG_TAG
,
"[ANR Warning]onLayout time too long, this ="
+
this
+
"time ="
+
(
nowTime
-
logTime
)
+
" ms"
);
}
if
(
DBG_LAYOUT
||
DBG_MEASURE_LAYOUT
)
{
Xlog
.
d
(
VIEW_LOG_TAG
,
"view layout end, this ="
+
this
+
", mLeft = "
+
mLeft
+
", mTop = "
+
mTop
+
", mRight = "
+
mRight
+
", mBottom = "
+
mBottom
+
", time ="
+
(
nowTime
-
logTime
)
+
" ms"
);
}
mPrivateFlags
&=
~
PFLAG_LAYOUT_REQUIRED
;
//将标志位恢复
ListenerInfo
li
=
mListenerInfo
;
if
(
li
!=
null
&&
li
.
mOnLayoutChangeListeners
!=
null
)
{
ArrayList
<
OnLayoutChangeListener
>
listenersCopy
=
(
ArrayList
<
OnLayoutChangeListener
>)
li
.
mOnLayoutChangeListeners
.
clone
();
int
numListeners
=
listenersCopy
.
size
();
for
(
int
i
=
0
;
i
<
numListeners
;
++
i
)
{
listenersCopy
.
get
(
i
).
onLayoutChange
(
this
,
l
,
t
,
r
,
b
,
oldL
,
oldT
,
oldR
,
oldB
);
//接口回调
}
}
}
else
{
if
(
DBG_LAYOUT
||
DBG_MEASURE_LAYOUT
)
{
Xlog
.
d
(
VIEW_LOG_TAG
,
"view layout end 2 (use previous layout), this = "
+
this
+
", mLeft = "
+
mLeft
+
", mTop = "
+
mTop
+
", mRight = "
+
mRight
+
", mBottom = "
+
mBottom
);
}
}
mPrivateFlags
&=
~
PFLAG_FORCE_LAYOUT
;
mPrivateFlags3
|=
PFLAG3_IS_LAID_OUT
;
if
(
DBG_SYSTRACE_LAYOUT
)
{
Trace
.
traceEnd
(
Trace
.
TRACE_TAG_VIEW
);
}
}
从上面的代码可以看到,layout 流程先会根据之前在measure流程中是否设置了
PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
变量来判断是否需要重新measure一遍,然后调用
setFrame
来确定自己的4个点的位置,4个点分别是left,top.right,bottom.有了这4个点,后续才能准确的绘制
.
接着根据在measure里面设置的
PFLAG_LAYOUT_REQUIRED
变量来执行
onLayout
流程,其实这个方法View和ViewGroup都没有去实现,真正的实现是在各个子类里面的,后面会分析.再这之后,如果这个视图设置过
OnLayoutChangeListener
接口,还会回调这些接口的
onLayoutChange()
-
protected
void
onMeasure
(
int
widthMeasureSpec
,
int
heightMeasureSpec
)
{
-
if
(
mOrientation
==
VERTICAL
)
{
-
measureVertical
(
widthMeasureSpec
,
heightMeasureSpec
);
-
}
else
{
-
measureHorizontal
(
widthMeasureSpec
,
heightMeasureSpec
);
-
}
-
}
这里我们只分析垂直布局
-
void
layoutVertical
(
int
left
,
int
top
,
int
right
,
int
bottom
)
{
-
final
int
paddingLeft
=
mPaddingLeft
;
-
-
int
childTop
;
-
int
childLeft
;
-
-
// Where right end of child should go
-
final
int
width
=
right
-
left
;
-
int
childRight
=
width
-
mPaddingRight
;
-
-
// Space available for child
-
int
childSpace
=
width
-
paddingLeft
-
mPaddingRight
;
-
-
final
int
count
=
getVirtualChildCount
();
-
-
final
int
majorGravity
=
mGravity
&
Gravity
.
VERTICAL_GRAVITY_MASK
;
-
final
int
minorGravity
=
mGravity
&
Gravity
.
RELATIVE_HORIZONTAL_GRAVITY_MASK
;
-
-
switch
(
majorGravity
)
{
-
case
Gravity
.
BOTTOM
:
-
// mTotalLength contains the padding already
-
childTop
=
mPaddingTop
+
bottom
-
top
-
mTotalLength
;
-
break
;
-
-
// mTotalLength contains the padding already
-
case
Gravity
.
CENTER_VERTICAL
:
-
childTop
=
mPaddingTop
+
(
bottom
-
top
-
mTotalLength
)
/
2
;
-
break
;
-
-
case
Gravity
.
TOP
:
-
default
:
-
childTop
=
mPaddingTop
;
-
break
;
-
}
-
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
-
final
View
child
=
getVirtualChildAt
(
i
);
-
if
(
child
==
null
)
{
-
childTop
+=
measureNullChild
(
i
);
-
}
else
if
(
child
.
getVisibility
()
!=
GONE
)
{
-
final
int
childWidth
=
child
.
getMeasuredWidth
();
-
final
int
childHeight
=
child
.
getMeasuredHeight
();
-
-
final
LinearLayout
.
LayoutParams
lp
=
-
(
LinearLayout
.
LayoutParams
)
child
.
getLayoutParams
();
-
-
int
gravity
=
lp
.
gravity
;
-
if
(
gravity
<
0
)
{
-
gravity
=
minorGravity
;
-
}
-
final
int
layoutDirection
=
getLayoutDirection
();
-
final
int
absoluteGravity
=
Gravity
.
getAbsoluteGravity
(
gravity
,
layoutDirection
);
-
switch
(
absoluteGravity
&
Gravity
.
HORIZONTAL_GRAVITY_MASK
)
{
-
case
Gravity
.
CENTER_HORIZONTAL
:
-
childLeft
=
paddingLeft
+
((
childSpace
-
childWidth
)
/
2
)
-
+
lp
.
leftMargin
-
lp
.
rightMargin
;
-
break
;
-
-
case
Gravity
.
RIGHT
:
-
childLeft
=
childRight
-
childWidth
-
lp
.
rightMargin
;
-
break
;
-
-
case
Gravity
.
LEFT
:
-
default
:
-
childLeft
=
paddingLeft
+
lp
.
leftMargin
;
-
break
;
-
}
-
-
if
(
hasDividerBeforeChildAt
(
i
))
{
-
childTop
+=
mDividerHeight
;
-
}
-
-
childTop
+=
lp
.
topMargin
;
-
setChildFrame
(
child
,
childLeft
,
childTop
+
getLocationOffset
(
child
),
-
childWidth
,
childHeight
);
-
childTop
+=
childHeight
+
lp
.
bottomMargin
+
getNextLocationOffset
(
child
);
-
-
i
+=
getChildrenSkipCount
(
child
,
i
);
-
}
-
}
-
}
View与ViewGroup layout 过程这儿过程相比measure要简单一点,我们先从View 的layout()看起,ViewGroup的layout主要还是判断一些条件之后调用View 的layout()View.javapublic void layout(int l, int t, int r, int b) { if (DBG_SYSTRACE_LAY
on
Layout
、
layout
方法简介
on
Layout
方法是
View
Group
中子
View
的布局方法,用于放置子
View
的位置。放置子
View
很简单,只需在重写on
Layout
方法,然后获取子
View
的实例,调用子
View
的
layout
方法实现布局。在实际开发中,一般要配合on
Measure
测量方法一起使用。
on
Layout
方法:
@Override
protected abst
为什么要进行性能优化?
随着项目版本的不断迭代,App的性能问题会逐渐的暴露出来,给用户带来一些卡顿、崩溃的体验。面对给和用户造成的不良效果,做出了性能优化,提升App整体性能,带用户带来良好的用户触感。
有哪些可以进行性能优化?
1.内存优化
内存泄漏是Androi...
Android stuido是Google官方唯一推荐的Android开发IDE,但是在使用
过程
中,必然会遇到一些一问题,Android Studio毕竟还在完善中,在这,分享一下我在使用Android Studio的时候遇到的问题以及解决方案,希望对广大博友有所帮助。
Error:A problem was found with the configuration of task ...
1. 优化布局层级
2. 在onDraw的时候避免做耗时操作,同时尽量不要在ondraw中创建局部对象,onDraw频繁调用会产生大量的临时对象占用过多内存导致多次gc,降低性能;
2.内存方向
1. 内存泄漏相关可以参看我的其他博客内容
2. 内存溢出
1.如果内存泄漏过多,很多对象未被回收,导致内存占用太大,内存溢出;
2.大...
最近参加了几轮面试,发现很多5-7年工作经验的候选人在性能优化这一块,基本上只能说出传统的分析方式,例如
ANR
分析,是通过查看/data/
anr
/ 下的log,分析主线程堆栈、cpu、锁信息等,
然而,这种方法有一定的局限性,并不是每次都奏效,很多时候是没有堆栈信息给你分析的,例如有些高版本设备需要root权限才能访问/data/
anr
/ 目录,或者是线上用户的反馈,只有一张
ANR
的截
10-27 09:08:37.031 648 1118 E ActivityManager: +0% 924/kworker/2:0: 0% user + 0% kernel
10-27 09:08:37.031 648 1118 E ActivityManager: +0% 1014/logcat: 0% user + 0% ...
at android.
view
.
View
.dispatchTouchEvent(
View
.java:14540) at android.
view
.
View
Group
.dispatchTransformedTouchEvent(
View
Group
.java:3120) at android.
view
.
View
Group
.dispatchTouchEvent(
View
Group
.java:2801) at android.
view
.
View
Group
.dispatchTransformedTouchEvent(
View
Group
.java:3120) at android.
view
.
View
Group
.dispatchTouchEvent(
View
Group
.java:2801) at android.
view
.
View
Group
.dispatchTransformedTouchEvent(
View
Group
.java:3120) at android.
view
.
View
Group
.dispatchTouchEvent(
View
Group
.java:2801) at android.
view
.
View
Group
.dispatchTransformedTouchEvent(
View
Group
.java:3120) at android.
view
.
View
Group
.dispatchTouchEvent(
View
Group
.java:2801) at android.
view
.
View
Group
.dispatchTransformedTouchEvent(
View
Group
.java:3120) at android.
view
.
View
Group
.dispatchTouchEvent(
View
Group
.java:2801) at android.
view
.
View
Group
.dispatchTransformedTouchEvent(
View
Group
.java:3120) at android.
view
.
View
Group
.dispatchTouchEvent(
View
Group
.java:2801) at android.
view
.
View
Group
.dispatchTransformedTouchEvent(
View
Group
.java:3120) at android.
view
.
View
Group
.dispatchTouchEvent(
View
Group
.java:2801)
玩篮球的甘蔗 · 钢铁魔女在哪里观看 - 头条搜索 1 年前 |