理解できませんsetHasFixedSize()
。私はそれがRecyclerView
ドキュメントから、サイズが変わらないときに最適化に使用されることを知っています。
それはどういう意味ですか?ほとんどの場合、ListView
ほとんどの場合、サイズは固定されています。固定サイズにならないのはどのような場合ですか?画面上で占有する実際の不動産がコンテンツとともに成長するということですか?
理解できませんsetHasFixedSize()
。私はそれがRecyclerView
ドキュメントから、サイズが変わらないときに最適化に使用されることを知っています。
それはどういう意味ですか?ほとんどの場合、ListView
ほとんどの場合、サイズは固定されています。固定サイズにならないのはどのような場合ですか?画面上で占有する実際の不動産がコンテンツとともに成長するということですか?
回答:
非常に RecyclerViewの簡素化バージョンがあります:
void onItemsInsertedOrRemoved() {
if (hasFixedSize) layoutChildren();
else requestLayout();
}
このリンクは、通話requestLayout
が高価になる理由を説明しています。基本的に、アイテムが挿入、移動、または削除されるたびに、RecyclerViewのサイズ(幅と高さ)が変化し、ビュー階層内の他のビューのサイズが変化する可能性があります。これは、アイテムが頻繁に追加または削除される場合に特に厄介です。
setHasFixedSize
アダプターのコンテンツを変更しても高さまたは幅が変更されない場合は、trueに設定して不要なレイアウトパスを回避します。
更新:メソッドが実際に何をするかをよりよく説明するために、JavaDocが更新されました。
RecyclerViewのサイズがアダプタの内容に影響されないことが事前にわかっている場合、RecyclerViewはいくつかの最適化を実行できます。RecyclerViewは、他の要素(親のサイズなど)に基づいてサイズを変更できますが、このサイズの計算は、子のサイズやアダプターのコンテンツ(アダプター内のアイテムの数を除く)に依存できません。
RecyclerViewの使用がこのカテゴリに該当する場合は、これを{@code true}に設定します。これにより、RecyclerViewは、アダプターの内容が変更されたときにレイアウト全体が無効になるのを回避できます。
@param hasFixedSizeアダプターの変更がRecyclerViewのサイズに影響を与えない場合はtrue。
requestLayout
dataSetが更新された後にRecyclerViewに呼び出すかどうかを通知するだけです。
確認できるのsetHasFixedSize
はRecyclerView自体に関するものであり、それに適合した各アイテムのサイズではありません。
android:layout_height="wrap_content"
RecyclerViewで使用できるようになりました。これにより、特に、RecyclerViewが空の場合にCollapsingToolbarLayoutが折りたたまれないようにすることができます。これsetHasFixedSize(false)
は、RecylcerViewで使用する場合にのみ機能します。
setHasFixedSize(true)
RecyclerViewで使用する場合、RecyclerViewが実際に空であっても、CollapsingToolbarLayoutが折りたたまれないようにするこの動作は機能しません。
場合はsetHasFixedSize
アイテムの大きさに関係していたRecyclerViewは何のアイテムを持っていないとき、それはどんな効果を持つべきではありません。
setHasFixedSize(true)
新しいアイテムが追加されたときに展開するように削除する必要がありました。
hasFixedSize: set to true if adapter changes cannot affect the size of the RecyclerView.
アイテムのサイズが変わる場合でも、これをtrueに設定できます。
ListViewにも同様の名前付き関数があり、個々のリストアイテムの高さのサイズに関する情報を反映していると思います。RecyclerViewのドキュメントでは、アイテムのサイズではなく、RecyclerView自体のサイズを参照していると明確に述べられています。
setHasFixedSize()メソッドの上のRecyclerViewソースコメントから:
* RecyclerView can perform several optimizations if it can know in advance that changes in
* adapter content cannot change the size of the RecyclerView itself.
* If your use of RecyclerView falls into this category, set this to true.
設定setHasFixedSize(true)
するRecyclerView
と、リサイクラーのサイズは固定され、アダプターの内容の影響を受けません。この場合onLayout
、アダプターのデータを更新するときにリサイクラーで呼び出されません(ただし、例外があります)。
例に行きましょう:
RecyclerView
持っているRecyclerViewDataObserver
(このファイルにデフォルトimplemntationを見つけるいくつかの方法で)、メイン重要です:
void triggerUpdateProcessor() {
if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
} else {
mAdapterUpdateDuringMeasure = true;
requestLayout();
}
}
このメソッドはsetHasFixedSize(true)
、アダプタのデータを次の方法で設定および更新した場合に呼び出されますnotifyItemRangeChanged, notifyItemRangeInserted, notifyItemRangeRemoved or notifyItemRangeMoved
。この場合、リサイクラーのへの呼び出しはありませんonLayout
が、子requestLayout
を更新するための呼び出しがあります。
我々が設定されている場合でも、setHasFixedSize(true)
を介してアダプタのデータを更新しnotifyItemChanged
、その後の呼び出しがあるonChange
リサイクル業者のデフォルトのRecyclerViewDataObserver
およびへの呼び出しなしでtriggerUpdateProcessor
。この場合、またはonLayout
を設定するたびにリサイクラーが呼び出されます。setHasFixedSize
true
false
// no calls to triggerUpdateProcessor
@Override
public void onChanged() {
assertNotInLayoutOrScroll(null);
mState.mStructureChanged = true;
processDataSetCompletelyChanged(true);
if (!mAdapterHelper.hasPendingUpdates()) {
requestLayout();
}
}
// calls to triggerUpdateProcessor
@Override
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
assertNotInLayoutOrScroll(null);
if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
triggerUpdateProcessor();
}
}
自分で確認する方法:
カスタムRecyclerView
を作成してオーバーライド:
override fun requestLayout() {
Log.d("CustomRecycler", "requestLayout is called")
super.requestLayout()
}
override fun invalidate() {
Log.d("CustomRecycler", "invalidate is called")
super.invalidate()
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
Log.d("CustomRecycler", "onLayout is called")
super.onLayout(changed, l, t, r, b)
}
リサイクラーのサイズをmatch_parent
(xmlで)に設定します。使用して、アダプタのデータを更新しようreplaceData
とreplaceOne
SETINGとsetHasFixedSize(true)
、その後とfalse
。
// onLayout is called every time
fun replaceAll(data: List<String>) {
dataSet.clear()
dataSet.addAll(data)
this.notifyDataSetChanged()
}
// onLayout is called only for setHasFixedSize(false)
fun replaceOne(data: List<String>) {
dataSet.removeAt(0)
dataSet.addAll(0, data[0])
this.notifyItemChanged(0)
}
そして、ログを確認してください。
私のログ:
// for replaceAll
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onMeasure is called
D/CustomRecycler: onMeasure is called
D/CustomRecycler: onLayout
D/CustomRecycler: requestLayout is called
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called
// for replaceOne
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called
要約:
をsetHasFixedSize(true)
呼び出す以外の方法でオブザーバーに通知してアダプターのデータを設定および更新するnotifyDataSetChanged
と、recycler onLayout
メソッドの呼び出しがないため、パフォーマンスが向上します。
RecyclerView
with match_parent
as height / widthがある場合setHasFixedSize(true)
、RecyclerView
それ自体のサイズはアイテムの挿入または削除に影響しないため、追加する必要があります。
setHasFixedSizeは、我々がRecyclerViewを持っている場合はfalseでなければなりませんwrap_content
よう、高さ/幅アダプタが挿入された各要素はサイズ変更される可能性があるためRecycler
、挿入項目に応じて/ので、削除のサイズRecycler
、我々は/削除追加するたびに異なるだろうがアイテム。
より明確に言えば、
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
使用できます my_recycler_view.setHasFixedSize(true)
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
を使用する必要がありますmy_recycler_view.setHasFixedSize(false)
。これはwrap_content
、幅としても使用する場合に適用されます
false
挿入と削除のアニメーションが表示されない場合、recyclerviewのアニメーションに影響します。したがってtrue
、recyclerviewのアニメーションを追加した場合に備えてください。