LinearLayout layout_weightパフォーマンスの最適化(PriorityLinearLayoutがLinearLayoutスキームを置き換えます)



Linearlayout Layout_weight Performance Optimization



A.layout_weight置換スキーム

LinearLayoutのlayout_weightは、プロジェクトでよく使用されます。使用するのは便利ですが、layout_weightを追加すると、LinearLayoutが2回測定されます。 LinearLayoutに子ビューが多数ある場合、パフォーマンスの問題があります。



この問題を最適化するには、LinearLayout + layout_weightの使用法をPriorityLinearLayout + measure_priorityに置き換えることができます。

一般的なLinearLayout + layout_weightの使用法:



allprojects { repositories { ... maven { url 'https://jitpack.io' } } }

PriorityLinearLayout置換+ measure_priority置換:

たった3ステップ

1. project /build.gradleにリポジトリを追加します



dependencies { ... implementation 'com.github.ouxiaoyong:PriorityLinearLayout:v1.0.1' }

2. app /build.gradleの依存関係を増やします

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mOrientation == VERTICAL) { measureVertical(widthMeasureSpec, heightMeasureSpec) } else { measureHorizontal(widthMeasureSpec, heightMeasureSpec) } }

3.レイアウトを置き換えます

void measureVertical(int widthMeasureSpec, int heightMeasureSpec);

3.1。元のレイアウトのルートレイアウトをcom.oxy.library.PriorityLinearLayoutに置き換えます

3.2。 layout_height(layout_width)=元々layout_weight属性を含んでいたラベルの「match_parent」

3.3。 layout_weight属性を含まないラベルに汎用app:measure_priority = '1'(正の整数)を追加します。

layout_weightを使用しないこのソリューションは、1回だけ測定され、パフォーマンスが向上します。

2.以下のシーンがプロジェクトに含まれます。

ページの中央には、ListView、またはScrollViewなどのスクロール可能なコントロールがあります。以下は、[追加]ボタンを含むLinearLayoutです。 [追加]ボタンをクリックするたびに、サブアイテムがリストビューに追加されます。 ListViewのコンテンツが少ない場合、ListViewはスクロールできません。また、ListViewのコンテンツが多い場合(つまり、ページ内のTextView + ListView + LinearLayoutがアクティビティの高さよりも大きい場合)、ListViewをスクロールでき、[追加]ボタンのレイアウトが次の場合は、[追加]ボタンの後に次のように表示されます。下部に移動しません。言い換えると、ListViewの最大の高さmaxHeight =アクティビティの高さ-TextViewの高さ-LinearLayoutの高さ

従来の実装

追加/削除するたびに、ListViewのコンテンツの高さを計算します。 maxHeight未満の場合は、ListViewの実際の高さに設定します。 maxHeightより大きい場合は、ここでmaxHeightに設定し、一連のコードを記述する必要があります。

エレガントな実装はありますか?もちろん! PriorityLinearLayout + measure_priority

void measureVertical(int widthMeasureSpec, int heightMeasureSpec) { ... for (int i = 0 i

元のレイアウトのルートレイアウトを次のように置き換えるだけです

com.oxy.library.PriorityLinearLayout、および[追加]ボタンを含むLinearLayoutに属を追加します

App:measure_priority = '1'(正の整数)

PriorityLinearLayoutは、参照子ビューのmeasure_priorityプロパティに基づいて元の順序で介入するLinearLayoutを継承します。 measure_priority値には大きな優先度メジャーがあり、measure_priority(デフォルトは0)値を持たない子ビューも元の順序メジャー(つまり、addViewの順序)にあります。

PriorityLinearLayoutソースコード: https://github.com/ouxiaoyong/PriorityLinearLayout

主成分分析

実際、PriorityLinearLayoutの原則は非常に単純であり、measure_priority属性値のサイズに応じてメジャーの順序を変更するだけです。

LinearLayoutのレイアウト、レイアウト、および描画順序はすべて、Addサブビューの順序です。上記のレイアウトファイルのcom.oxy.library.PriorityLinearLayoutがLinearLayoutに変更された場合はどうなりますか?

1. ListViewサブアイテムが小さい場合、それは正常です。

2. ListViewサブアイテムがさらにある場合、下部のLinearLayoutは「消えます」。

LinerLayoutのメジャーソース分析を見てみましょう。

最初にonMeasureメソッドを見つけます

getVirtualChildAt()

私たちのmOrientation = VERTICAL、そして見てください

@Nullable View getVirtualChildAt(int index) { return getChildAt(index) } public View getChildAt(int index) { if (index = mChildrenCount) { return null } return mChildren[index] }

ここで、状況2の根本原因を分析できます(下部のLinearLayoutが消えます)。 usedHeightは、前の子ビューで使用された高さです。現在の子ビューが取得できる最大の高さは、usedHeightから差し引く必要があります。 ListViewの最初のメジャーは残りの高さを使い果たしたため、下部のLinearLayoutには割り当て可能な高さがないため、その高さは0です。

子ビューをトラバースするメジャーの順序は次のとおりです。

package com.example.ouxia.myapplication import android.annotation.SuppressLint import android.content.Context import android.content.res.TypedArray import android.support.annotation.Nullable import android.util.AttributeSet import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import java.util.ArrayList import java.util.Collections import java.util.Comparator import java.util.List public class PriorityLinearLayout extends LinearLayout { private List indexs = new ArrayList() private boolean isMeasureing = false public PriorityLinearLayout(Context context, @Nullable AttributeSet attrs) { this(context, attrs,0) } public PriorityLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr) } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new PriorityLinearLayout.LayoutParams(getContext(), attrs) } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { refreshIndexs() isMeasureing = true super.onMeasure(widthMeasureSpec, heightMeasureSpec) isMeasureing = false } private void refreshIndexs() { indexs.clear() for (int i = 0 i

getVirtualChildAtのロジックをオーバーライドするようにメジャーの順序を変更するには、getVirtualChildAtメソッドのアクセス許可がデフォルトであり、書き換えることはできません。

getChildAtメソッドのみをオーバーライドできます。

|_+_|

コアロジックが分析され、残りはコードの実装です。

すべてのコードは約100行です。

|_+_|