রিসাইক্লারভিউ সেটহ্যাসফিক্সডসাইজ বোঝা


136

আমি কিছু কষ্ট বোঝার হচ্ছে setHasFixedSize()। আমি জানি যে RecyclerViewডক্স থেকে যখন আকার পরিবর্তন হয় না তখন এটি অপ্টিমাইজেশনের জন্য ব্যবহৃত হয়।

যদিও এর অর্থ কী? বেশিরভাগ সাধারণ ক্ষেত্রে ListViewপ্রায় সর্বদা একটি নির্দিষ্ট আকার থাকে। কোন ক্ষেত্রে এটি একটি নির্দিষ্ট আকার হবে না? এর অর্থ কী এটি যে সত্যিকারের রিয়েল এস্টেট এটি পর্দায় দখল করে তা সামগ্রীর সাথে বেড়ে যায়?



আমি এই উত্তরটি দরকারী এবং সহজেই বুঝতে পেরেছি [স্ট্যাকওভারফ্লো - rv.setHasFixedSize (সত্য); ] ( স্ট্যাকওভারফ্লো.com / প্রশ্নগুলি / ২৮৮৮৫75৫97/২ )
মোস্তফা হাসান

উত্তর:


115

রিসাইক্লিউউয়ের একটি খুব সরলিকৃত সংস্করণটিতে রয়েছে:

void onItemsInsertedOrRemoved() {
   if (hasFixedSize) layoutChildren();
   else requestLayout();
}

এই লিঙ্কটি কেন কল requestLayoutকরা ব্যয়বহুল হতে পারে তা বর্ণনা করে । মূলত যখনই আইটেমগুলি সন্নিবেশ করা হয়, সরানো বা সরিয়ে ফেলা হয় তখন পুনর্ব্যবহারযোগ্য ভিউয়ের আকার (প্রস্থ এবং উচ্চতা) পরিবর্তন হতে পারে এবং পরিবর্তে হায়ারার্কির দিক থেকে অন্য কোনও দৃশ্যের আকার পরিবর্তন হতে পারে। আইটেমগুলি ঘন ঘন যুক্ত করা বা সরানো হয় তবে এটি বিশেষত সমস্যাযুক্ত।

সেটিং দ্বারা অপ্রয়োজনীয় বিন্যাস পাস চলুন setHasFixedSizeসত্যতে যখন এডাপটার বিষয়বস্তু পরিবর্তন এটা উচ্চতা বা বিস্তারে পরিবর্তন করে না।


আপডেট: পদ্ধতিটি আসলে কী করে তা আরও ভালভাবে বর্ণনা করার জন্য জাভাডক আপডেট করা হয়েছে।

রিসাইক্লার ভিউ অ্যাডাপ্টারের সামগ্রী দ্বারা প্রভাবিত হয় না তা আগে থেকে জানতে পারলে রিসাইক্লারভিউ বেশ কয়েকটি অনুকূলকরণ সম্পাদন করতে পারে। রিসাইক্লার ভিউ এখনও অন্য উপাদানগুলির উপর নির্ভর করে এর আকার পরিবর্তন করতে পারে (যেমন এর পিতামাতার আকার) তবে এই আকারের গণনাটি তার বাচ্চার আকার বা এর অ্যাডাপ্টারের সামগ্রীর উপর নির্ভর করতে পারে না (অ্যাডাপ্টারের আইটেমের সংখ্যা ব্যতীত)।

যদি আপনার পুনর্ব্যবহারযোগ্য ভিউ এর ব্যবহারটি এই বিভাগে আসে তবে এটি {@ কোড সত্য to এ সেট করুন} এটি অ্যাডাপ্টারের সামগ্রী পরিবর্তিত হলে পুরো লেআউটটিকে অকার্যকর করতে এড়াতে রিসাইক্লার ভিউকে অনুমতি দেবে।

অ্যাডাপ্টারের পরিবর্তনগুলি পুনর্ব্যবহারযোগ্য ভিউয়ের আকারকে প্রভাবিত করতে না পারে তবে @ পরিমাপিকৃত ফিক্সডসাইজ সত্য


162
আপনি যখনই কিছু না কিছু যুক্ত করুন রিসাইক্লারভিউয়ের আকার পরিবর্তন হয়। সেটহ্যাসফিক্সডসাইজ যা করেন তা হ'ল এটি নিশ্চিত করে (ব্যবহারকারী ইনপুট দ্বারা) যে রিসাইক্লারভিউয়ের আকারের এই পরিবর্তনটি স্থির। আইটেমের উচ্চতা (বা প্রস্থ) পরিবর্তন হবে না। যুক্ত বা সরানো প্রতিটি আইটেম একই হবে। আপনি যদি এটি সেট না করেন তবে এটি পরীক্ষা করবে আইটেমটির আকার পরিবর্তন হয়েছে এবং ব্যয়বহুল। কেবল স্পষ্ট করা কারণ এই উত্তরটি বিভ্রান্তিকর।
আর্নল্ড বলিউ

9
@ আর্নল্ডবি চমৎকার ব্যাখ্যা। এমনকি আমি এটি একটি স্বতন্ত্র উত্তর হিসাবে তর্ক করব।
তরুণ_সৌভালকি

4
@ আর্নল্ডবি - আমি এখনও বিভ্রান্ত আপনি কি পরামর্শ দিচ্ছেন যে যদি সমস্ত শিশুর প্রশস্ততা / উচ্চতা স্থির থাকে তবে আমাদের ফিক্সড সাইজটি সত্য হিসাবে সেট করা উচিত? যদি হ্যাঁ, তবে যদি এমন কোনও সম্ভাবনা থাকে যে রানটাইমের সময় কিছু বাচ্চাদের সরানো যায় (বৈশিষ্ট্যটি খারিজ করার জন্য আমার কাছে একটি সোয়াইপ রয়েছে) - এটি কি সত্য সেট করা ঠিক আছে?
জাগুয়ার

1
হ্যাঁ. কারণ আইটেমের প্রস্থ এবং উচ্চতা পরিবর্তন হচ্ছে না। এটি কেবল যুক্ত বা সরানো হচ্ছে। আইটেম যুক্ত বা অপসারণ তাদের আকার পরিবর্তন করে না।
আর্নল্ড বলিউ

3
@ আর্নল্ডবি আমি মনে করি না যে আইটেমের আকার (প্রস্থ / উচ্চতা) এখানে একটি সমস্যা। এটি আইটেমটির আকারও পরীক্ষা করবে না। এটি কেবল রিসাইক্লার requestLayoutভিউকে ডেটাসেট আপডেট হওয়ার পরে কল করতে বা না করতে বলে ।
কিমি চিউ

22

setHasFixedSizeরিসাইক্লিউউ নিজেই সম্পর্কিত যাচাই করতে পারেন , এবং প্রতিটি আইটেম এর সাথে অভিযোজিত আকার নয়।

আপনি এখন android:layout_height="wrap_content"একটি পুনর্ব্যবহারযোগ্য ভিউতে ব্যবহার করতে পারেন , যা অন্যান্য জিনিসের মধ্যে একটি কলাপসিং টুলবারলয়আউটকে জানার অনুমতি দেয় যে যখন রিসাইক্লারভিউ খালি থাকে তখন এটি ধসে পড়বে না। এটি কেবল তখনই কাজ করে যখন আপনি setHasFixedSize(false)রিক্সিলারভিউতে ব্যবহার করেন।

আপনি যদি setHasFixedSize(true)রিসাইক্লারভিউতে ব্যবহার করেন তবে কলসিংটুলবারলয়আউটটিকে সঙ্কুচিত হওয়া থেকে রক্ষা করতে এই আচরণটি কার্যকর হয় না, যদিও রিসাইক্লারভিউ সত্যই ফাঁকা রয়েছে।

যদি setHasFixedSizeআইটেমের আকারের সাথে সম্পর্কিত ছিল, যখন পুনর্ব্যবহারযোগ্য ভিউতে কোনও আইটেম না থাকে তখন তার কোনও প্রভাব ফেলতে হবে না।


4
আমার সবেমাত্র একটি অভিজ্ঞতা রয়েছে যা একই দিক নির্দেশ করে। গ্রিডলাউটম্যানেজার (প্রতি সারিতে 3 টি আইটেম) এবং লেআউট_হাইট = মোড়ানো_কন্টেন্টের সাথে একটি পুনর্ব্যবহারযোগ্য ভিউ ব্যবহার করা। আমি যখন তালিকায় 3 টি নতুন আইটেম যুক্ত করা একটি বোতাম ক্লিক করি তখন নতুন আইটেমগুলির সাথে ফিট করার জন্য পুনর্ব্যবহারযোগ্য দৃশ্যটি প্রসারিত হয় না। বরং এটি একই আকার বজায় রাখে এবং নতুন আইটেমগুলি দেখার একমাত্র উপায় এটি স্ক্রোল করছে। আইটেমগুলির একই আকার থাকা সত্ত্বেও, setHasFixedSize(true)নতুন আইটেম যুক্ত করার সময় এটির প্রসারণ করতে আমাকে মুছে ফেলতে হয়েছিল।
ম্যাটিউস গন্ডিম

আমি মনে করি তুমি ঠিক. দস্তাবেজ থেকে, hasFixedSize: set to true if adapter changes cannot affect the size of the RecyclerView.সুতরাং আইটেমটির আকার পরিবর্তন হলেও আপনি এখনও এটি সত্যতে সেট করতে পারেন।
কিমি চিউ

12

লিস্টভিউতে একটি একই নামযুক্ত ফাংশন ছিল যা আমি মনে করি স্বতন্ত্র তালিকা আইটেমের উচ্চতার আকার সম্পর্কে তথ্য প্রতিফলিত করে। রিসাইক্লিউউয়ের জন্য ডকুমেন্টেশনটি খুব পরিষ্কারভাবে জানিয়েছে যে এটি নিজেরাই আইটেমের আকার নয়, বরং পুনর্ব্যবহারযোগ্য এর আকারের কথা উল্লেখ করছে।

সেটহ্যাসফিক্সডসাইজ () পদ্ধতির উপরে রিসাইক্লারভিউ উত্স থেকে মন্তব্য:

 * 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.

16
তবে কীভাবে রিসাইক্লারভিউয়ের "আকার" সংজ্ঞায়িত হয়? এটি কি কেবলমাত্র স্ক্রিনে দৃশ্যমান আকার বা পুনর্ব্যবহারযোগ্য ভিউয়ের পুরো আকার, যা সমান (আইটেম উচ্চতা + প্যাডিং + ফাঁক যোগফল)?
ভিকি চিজওয়ানি

2
আসলে, এটি আরও তথ্যের প্রয়োজন। আপনি যদি আইটেমগুলি সরিয়ে ফেলেন এবং পুনর্ব্যবহারযোগ্যদর্শন সঙ্কুচিত হয়, তবে এটি কি আকার পরিবর্তিত হয়েছে বলে বিবেচিত হয়?
হেনরিক ডি সোসা

4
আমি এটির মতো ভাবব কীভাবে কোনও টেক্সটভিউ নিজেকে আলাদা করে রাখতে পারে। যদি আপনি মোড়ানো_ কনটেন্ট নির্দিষ্ট করে থাকেন, তবে আপনি যখন পাঠ্য সেট করেন তখন পাঠ্য ভিউ একটি লেআউট পাসের অনুরোধ করতে পারে এবং স্ক্রিনে এটি স্থানের পরিমাণ পরিবর্তন করতে পারে। যদি আপনি ম্যাচ_পিতা বা একটি নির্দিষ্ট মাত্রা নির্দিষ্ট করে থাকেন, তবে টেক্সটভিউ কোনও লেআউট পাসের জন্য অনুরোধ করবে না কারণ আকারটি স্থির এবং টেক্সট ইনডের পরিমাণ কখনই স্থান অধিকারের পরিমাণ পরিবর্তন করবে না। রিসাইক্লারভিউ একই রকম। সেটহ্যাসফিক্সডসাইজ () আরভিতে ইঙ্গিত দেয় এর জন্য অ্যাডাপ্টারের আইটেমগুলির পরিবর্তনের উপর ভিত্তি করে লেআউট পাসের অনুরোধ করা উচিত নয়।
ডাং ভার্মিত

1
@ ডাং ভার্মিটের সুন্দর ব্যাখ্যা!
হোয়ারক্নিয়া

6

ওয়েন আমরা সেট setHasFixedSize(true)উপর RecyclerViewতার মানে এর recycler আকার সংশোধন করা হয়েছে এবং অ্যাডাপ্টারের বিষয়বস্তু দ্বারা প্রভাবিত হয় না। এবং এই ক্ষেত্রে onLayoutযখন আমরা অ্যাডাপ্ট্রারের ডেটা আপডেট করি তখন পুনর্ব্যবহারকারীকে ডাকা হবে না (তবে একটি ব্যতিক্রম রয়েছে)।

আসুন উদাহরণটিতে যাই:

RecyclerViewবেশ কয়েকটি পদ্ধতি সহ একটি RecyclerViewDataObserver( এই ফাইলে ডিফল্ট প্রয়োগটি সন্ধান করুন ) রয়েছে, প্রধান গুরুত্বপূর্ণটি হ'ল:

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আপডেট করার জন্য কল রয়েছে calls

তবে আমরা যদি 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তবে আপনার কিছুটা পারফরম্যান্স রয়েছে, কারণ রিসাইক্লার onLayoutপদ্ধতির কোনও কল নেই ।


আপনি কি র্যাপ_কন্টেন্ট বা ম্যাচ_প্যারেন্টটি ব্যবহার করে উচ্চতার রিসাইক্লার ভিউ দিয়ে পরীক্ষা করেছেন?
লুবস মুদ্রাক

6

আমরা যদি RecyclerViewসঙ্গে match_parentহিসাবে উচ্চতা / প্রস্থ , আমরা যোগ করা উচিত setHasFixedSize(true)আকার যেহেতু RecyclerViewনিজেই ঢোকাতে বা বের তা আইটেম মুছে ফেলার পরিবর্তন করে না।

সেটহ্যাসফিক্সডসাইজটি মিথ্যা হওয়া উচিত যদি আমাদের উচ্চতা / প্রস্থwrap_content হিসাবে একটি পুনর্ব্যবহারযোগ্য ভিউ থাকে যেহেতু অ্যাডাপ্টারের মাধ্যমে সন্নিবেশিত প্রতিটি উপাদান sertedোকানো / মুছে ফেলা আইটেমগুলির উপর নির্ভর করে আকারের আকার পরিবর্তন করতে পারে , তাই প্রতিবার আমরা যুক্ত / মুছলে প্রতি আকারের আকার আলাদা হবে আইটেম।RecyclerRecycler

আরও স্পষ্টভাবে, যদি আমরা ব্যবহার করি

<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প্রস্থ হিসাবেও ব্যবহার করি


3

সেটহ্যাসফিক্সডসাইজ (সত্য) অর্থ রিসাইক্লার ভিউতে বাচ্চারা (আইটেম) রয়েছে যা প্রস্থ এবং উচ্চতা নির্ধারণ করেছে। এটি আপনার অ্যাডাপ্টারের উপর ভিত্তি করে পুরো তালিকার সঠিক উচ্চতা এবং প্রস্থ নির্ধারণের মাধ্যমে পুনর্ব্যবহারযোগ্য ভিউটিকে আরও ভাল করতে সহায়তা করে।


5
@ ড্যাং ভার্মিটের পরামর্শ এটাই নয়।
অদ্ভুত সময়

5
বিভ্রান্তিকর, এটি আসলে পুনর্ব্যবহারযোগ্য দর্শনের আকার, সামগ্রীটির আকার নয়
বেনোইট

0

এটি যদি রিসাইক্লিউউরটির অ্যানিমেশনগুলিকে প্রভাবিত করে, যদি এটি হয় false.. animaোকানো এবং সরিয়ে অ্যানিমেশনগুলি প্রদর্শিত হবে না। সুতরাং trueআপনি পুনর্ব্যবহারের জন্য অ্যানিমেশন যুক্ত করেছেন তা নিশ্চিত হয়ে নিন ।


0

যদি রিসাইক্লারভিউয়ের আকার (পুনর্ব্যবহারযোগ্য ভিউ নিজেই)

... অ্যাডাপ্টার সামগ্রী উপর নির্ভর করে না:

mRecyclerView.setHasFixedSize(true);

... অ্যাডাপ্টারের সামগ্রীর উপর নির্ভর করে:

mRecyclerView.setHasFixedSize(false);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.