android 4.2 rtlSupport對UI效能的坑
最近在android 4.2上發現APP特別卡頓的問題,通過抓trace發現很多耗時在ViewGroup.resolveRtlPropertiesIfNeeded, View.resolveRtlPropertiesIfNeeded方法
檢視相關程式碼,google4.2開始支援rtl,也就是右向坐right to left佈局(一些很稀有的小語種國家)
發現每次重新mearsure都要對佈局進行resolveRtlPropertiesIfNeeded
通過檢視程式碼,發現4.2上這個功能做得不完善,4.2的程式碼:
/**
* @hide
*/
@Override
public void resolveRtlPropertiesIfNeeded() {
super.resolveRtlPropertiesIfNeeded();
int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.isLayoutDirectionInherited()) {
child.resolveRtlPropertiesIfNeeded();
}
}
}
遞迴呼叫時並沒有判斷是否需要對子view進行遞迴resolveRtlPropertiesIfNeeded。 並且View的預設rtlSupport是inherit,導致每次measure導遊重新遞迴resolveRtlPropertiesIfNeeded
再看看4.3的程式碼:
/**
* @hide
*/
@Override
public boolean resolveRtlPropertiesIfNeeded() {
final boolean result = super.resolveRtlPropertiesIfNeeded();
// We dont need to resolve the children RTL properties if nothing has changed for the parent
if (result) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.isLayoutDirectionInherited()) {
child.resolveRtlPropertiesIfNeeded();
}
}
}
return result;
}
由於沒找到4,3的手機實際測試,沒法確定4.3上android是否徹底解決這個問題,但是在5.0以上手機確實沒發現一次measure過程resolveRtlPropertiesIfNeeded遞迴次數特別多。
針對這種情況,如果APP不需要支援右向左的小語種,可以在AndroidMenifest.xml宣告關閉rtlSupport,並在style中宣告layoutDirection為ltr
<applicationandroid:supportsRtl="false"
<style name="xxxx" parent="@android:style/Theme.Light.NoTitleBar"> <item name="android:layoutDirection" tools:targetApi="jelly_bean_mr1">ltr</item>