تحياتي عزيزي harazhiteli! دفعني هذا المنشور لكتابة مقال (أو بالأحرى ، الشعور بارتفاع حاد في درجة الحرارة المحلية في المنطقة ... هم ، أسفل الظهر ، والذي يحدث عادة عندما يكون شخص ما مخطئًا على الإنترنت).
لنبدأ من البداية. أوافق تمامًا على أن "هناك شيء مشترك بين دورة حياة النشاط وعمل RecyclerView" - هذا "شيء" - الحاجة إلى فهم ما نقوم به ولماذا. وقراءة الوثائق. والفشل في تلبية هاتين الضرورتين ، مثل حلم العقل ، يؤدي إلى وحوش. هنا فقط بالطريقة التي يقترحها المؤلف السابق أن هذه الوحوش تعرض القتال ، أختلف بشدة.
ضع في اعتبارك شرطين.
الشرط رقم مرات
إذا أغلقت مستمعًا في مكان ما ، فيجب عليك فصله في مكان آخر. عادة ما يفعلون ذلك في وظائف متماثلة - إرفاق onViewAttachedToWindow
، وإزالته إلى onViewDetachedFromWindow
. نعلق في onBindViewHolder
... نحن لا نعلق في onBindViewHolder
. هذه المكالمة غير متناظرة ، يمكن استدعاؤها عدة مرات حسب الظروف المختلفة. لا حاجة لتعقيد حياتك.
إذا كنت ، مثل مؤلف المقالة الأصلية ، قد فكرت: "ولكن هناك حالات عندما ... في المستمع من الضروري مراعاة موضع العنصر في القائمة ، والوصول إليه متاح في طريقة onBindViewHolder () وهو غائب في onViewAttachedToWindow ()" ، ثم قم بقيادة هذا فكر خارج. لا يمكنك فعل ذلك. حتى لو كنت تريد حقا. كما هو مذكور في الوثائق ، لن يتم استدعاء هذه الطريقة إذا تم تغيير موضع العنصر فقط ، ولكن ليس محتوياته ، لذلك فإننا نخاطر بالحصول على وضع خاطئ في مستمعنا. استخدم getAdapterPosition
.
الشرط الثاني
RecyclerView
هو شيء معقد للغاية. لا حاجة لتعقيد حياتك أكثر. إذا لم تكن مشتركًا في تحسين الأداء ، فلا يهمك ما إذا كان هذا العنصر في التجمع العام أم لا.
النتيجة
في ظل هاتين الحالتين ، من غير المحتمل أن تحتاج إلى إعادة اختراع العجلة على شكل علامة viewWasRecycled
.
ما الذي يجري؟
ماذا يمكن أن يحدث لعنصر في RecyclerView
بشكل عام؟ أولاً ، ضع في اعتبارك أن هناك "مستودعين" - ذاكرة التخزين المؤقت والتجمع. يدخل عنصر إلى ذاكرة التخزين المؤقت إذا تجاوز حدود الشاشة ، ولكن يمكن أن يعود مرة أخرى في أي وقت - حتى بدون إعادة ربط هذا العنصر (على سبيل المثال ، لن يتم استدعاء طريقة onBindViewHolder
). إذا كانت ذاكرة التخزين المؤقت ممتلئة ، أو لسبب آخر ، قررت RecyclerView
أننا لسنا بحاجة إلى هذا العنصر في المستقبل القريب ، فسوف ينتقل إلى التجمع (هنا سيتم استدعاء onViewRecycled
). سيتم إعادة ربط العنصر المسترد من التجمع (لأنه على الأرجح تغير موقعه) ، وسوف نتلقى مكالمة onBindViewHolder
. ولكن إذا غادر العنصر التجمع ، فعندئذٍ سيخضع العنصر الجديد للدورة بأكملها - onCreateViewHolder
، onBindViewHolder
، onViewAttachedToWindow
.
المجموع ، لدينا 3 خيارات لتطوير الأحداث:
- لم يكن هناك عنصر من قبل: نخلق ، نعلق ، نعلق ؛
- كان العنصر في التجمع: ربط ، وإرفاق ؛
- كان العنصر في ذاكرة التخزين المؤقت: إرفاق فقط.
أين وكيف؟
ما وفي أي مراحل من الأفضل القيام بعنصر؟
onCreateViewHolder
. إنشاء ، هم ، ViewHolder
. ليست هناك حاجة لربط المستمع ، وملئه بالمحتوى ، إلخ. ما عليك سوى تحديد النوع الذي نحتاجه وإنشائه.onBindViewHolder
. نقوم بتنفيذ ربط المحتوى الفعلي - النص والصور. لا يمكن استخدام معلمة position
إلا في الطريقة نفسها - فنحن لا نحفظها ، ولا نرسلها إلى عمليات الإغلاق ، وتذكر أنه سيتم استدعاء هذه الطريقة مرة أخرى إذا تغيرت البيانات (ولن يتم تنفيذها إذا تم تغيير الموضع فقط). لن أعلق المستمع هنا أيضًا - لأسباب تتعلق بالتماثل.onViewAttachedToWindow
. سيكون العنصر الآن مرئيًا على الشاشة ، وسيكون المستخدم قادرًا على التفاعل معه - وهي لحظة جيدة لإرفاق مستمع. تذكر أنه إذا كنا بحاجة إلى موضع عنصر بداخله ، فإننا نحصل عليه من خلال getAdapterPosition
.onViewDetachedFromWindow
. لن يتم عرض العنصر على الشاشة. لن يتمكن المستخدم من التفاعل معه. إزالة المستمع.onViewRecycled
. يتم إرسال العنصر إلى الجحيم تجمع هنا يمكنك تحرير الموارد الثقيلة (الصور المخبأة ، على سبيل المثال). إذا كان سيتم إعادة استخدام العنصر - ثم ، على الأرجح ، لموقف مختلف.
يبدو أن هذا كل شيء. آمل أنني لم أنسِ شيئًا أو مزجت أي شيء ، ولكن إذا كان هناك أي شيء ، كز أنفك ، فلا تخجل.