مسألة دورة حياة تطبيق Android أو جزء من تطبيق Android مهم للغاية لممارسة Android (مطور Android). لماذا؟ لأن ترتيب تنفيذ عمليات الاسترجاعات لجميع الطرق المتعلقة بحالة دورة الحياة ( onCreate () و onStart () ، وما إلى ذلك) يتم تشفيره بشكل ثابت وسوف يؤدي تطبيقه غير الصحيح إلى عدم قابلية التطبيق للتشغيل. ما علاقة دورة الحياة بها؟ - سيسأل habretchit اليقظة. بعد كل شيء ، يبدو أن العنوان ليس عنه؟ أجيب: هناك شيء مشترك بين دورة حياة النشاط وعمل RecyclerView - هناك أمر صعب لتنفيذ طرق رد الاتصال عند استخدام هذه الأداة ، وبالتالي ، الحاجة إلى تطبيقه بشكل صحيح .
إذا لم يتم ذلك ، يمكن أن تتصرف القوائم بطريقة غامضة للغاية.
محول الأدنى ل RecyclerView
على سبيل المثال. يوجد محول القائمة هذا مع الحد الأدنى القياسي للحشو:
الإدراج 1
public class RvCustomAdapter extends RecyclerView.Adapter<RvCustomAdapter.CustomViewHolder> { private final Frag1 frag; private final LayoutInflater lInflater; private ArrayList<JSONDataSet> dataSet; ... ... ... public RvCustomAdapter(final Frag1 fragment) { this.frag = fragment; this.lInflater = (LayoutInflater) fragment.getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.dataSet = new ArrayList<>(); } ... ... ... @Override public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
في كود طريقة onBindViewHolder () لمحول قائمتنا ، التي تحتوي عناصرها على مربع اختيار ( CheckBox ) ، هناك نداء إلى طريقة المعالج ( صاحب 'أ) ، حيث يتم قراءة البيانات من المجموعة المتصلة بالمحول وبناء على ذلك - مربع الاختيار - الحالة ، وكذلك العناصر الضرورية ( المستمع ) مرتبطة بالعناصر المختلفة للواجهة:
قائمة 2
void showData(final int position) { cur = dataSet.get(position); cb_Data.setChecked(cur.isChecked()); ... ... ... cb_Data.setOnCheckedChangeListener(cb_DataOnCheckedChangeListener); ll_Data.setOnClickListener(ll_DataOnClickListener); } private OnClickListener ll_DataOnClickListener = new OnClickListener() { @Override public void onClick(View view) { cur.setChecked(!cur.isChecked()); cb_Data.setChecked(cur.isChecked()); } }; private OnCheckedChangeListener cb_DataOnCheckedChangeListener = new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { cur.setChecked(checked); compoundButton.setChecked(checked); setItemsColor(checked); if (checked) { if (...) { (frag).addSelectedItemsCounter(cur); } else { cur.setChecked(!checked); compoundButton.setChecked(!checked); setItemsColor(!checked); if (...) { createPrimaryDialog(); } else { createSecondaryDialog(); } } } else { (frag).remSelectedItemsCounter(cur); } } };
عندما يتم تعيين العلم وتلبية شرط معين ، يقوم المستمعون بتغيير البيانات في المجموعة ، وعندما لا يتم تنفيذها ، يعرضون إما مربع حوار أو آخر.
اتضح شيء مثل هذا:



في الشكل 1 - القائمة التي تم إنشاؤها. في الشكل 2 - عنصر القائمة المحدد. في الشكل 3 - حوار لإبلاغه بانتهاك الشرط عند وضع علامة على العنصر التالي.
للحصول على النتيجة باستخدام مدير تخطيط قائمة الشكل 1 ( LayoutManager ) ، يتم تنفيذ الترتيب التالي لاستدعاء الوظائف الضرورية:
خوارزمية 1
- Rv_Adapter.getItemCount () - يتحقق من عدد العناصر في المجموعة ؛
- Rv_Adapter.onAttachedToRecyclerView () - المحول متصل بالقطعة ؛
- حتى يتم ملء مساحة القائمة بعناصر القائمة ، يتم تنفيذ الخطوات التالية من الخوارزمية 2 للقائمة:
الخوارزمية 2
- Rv_Adapter.onCreateViewHolder () - لكل عنصر من عناصر المجموعة ، يتم إنشاء معالج خاص به ؛
- CustomViewHolder () - يتم تنفيذ مُنشئ المعالج ؛
- Rv_Adapter.onBindViewHolder () - لكل مثيل ، يبدأ منشئ العرض ؛
- Rv_Adapter.onViewAttachedToWindow () - طريقة العرض التي تم إنشاؤها متصلة بالنافذة ؛
كل شيء رائع! إن لم يكن لـ "لكن". بدلا من ذلك ، ولكن!
المشكلة
عند التمرير عبر قائمة طويلة تحتوي على ما لا يقل عن اثني عشر عنصرًا ، سوف نتلقى رسالة من الشكل 3 بدون أي إجراءات أخرى.
استكشاف الأخطاء وإصلاحها
والسبب هو أنه عند كتابة رمز المحول ، فإننا لم نأخذ في الاعتبار ترتيب الأداء لوظائف الاتصال المدرجة هنا وهنا عند التمرير. وهو هكذا:
الخوارزمية 3
- عند الاختباء في الخارج رؤية كل عنصر من عناصر القائمة للمثيل المرتبط للمعالج ، يتم تنفيذ طريقة Rv_Adapter.onViewDetachedFromWindow () ، والتي تفصل طريقة الإختباء من النافذة ؛
- عندما يظهر كل عنصر جديد في القائمة ( itemView ) من خارج نطاق الرؤية ، يتم تنفيذ الخوارزمية 2 لمثيل المعالج المرتبط ؛
لكن هذا ليس كل شيء باستخدام الإعدادات "الافتراضية" لمدير العلامات ، لا يبقى كل عنصر قائمة غير متصل بالنافذة طويلًا في قائمة الانتظار للوصول السريع. بمجرد وجود 2 منهم هناك ، يتم نقلهم من قبل المدير إلى قائمة انتظار الحالات التي تم التخلص منها ، والتي يتم تمييزها باستدعاء طريقة Rv_Adapter.onViewRecycled () لكل عنصر قائمة مستخدم والعكس بالعكس.
لذلك ، تبدو الخوارزمية 3 كما يلي:
الخوارزمية 3 '
من الخوارزمية 3 أعلاه ، يُلاحظ أنه إذا قمت بالتمرير عبر القائمة بأكثر من الحد الأقصى ، فسيتم إنشاء عدد مواقع العرض فيها من جديد ، والتي سيتم استخدام طريقة Rv_Adapter.onBindViewHolder (حامل ، وضوحا ،) ، والتي ستكرر إجراءات المستخدم.
الخلاصة والتوصية
لتجنب تكرار العمليات في طريقة onBindViewHolder (الحامل ، visualPos) عند التمرير في القائمة حسب عدد المواضع التي تزيد عن الحد الأقصى ، من الضروري:
- استكمل عناصر المجموعة بحقل مع علامة على ازدحام العرض المرتبط في قائمة انتظار المعالجات المستخدمة ، على سبيل المثال ، المعاد تدويره ؛
- إدراج تعليمات حول كيفية تعيين هذه العلامة في طريقة onViewRecycled (حامل) ، على سبيل المثال .... setRecycled (true) ؛
- أدخل في طريقة onBindViewHolder (الحامل ، visualPos) فحصًا لهذه العلامة ، على سبيل المثال إذا (! Handler.cur.isRecycled ()) ... ؛
- قم بإدراج تعليمات طريقة onViewAttachedToWindow (حامل) لإزالة هذا العرض ، على سبيل المثال .... setRecycled (false) ؛
على سبيل المثال ، مثل هذا:
قائمة 3
@Override public void onViewRecycled(@NonNull CustomViewHolder holder) { super.onViewRecycled(holder); holder.cur.setRecycled(true); } @Override public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) { if (!holder.cur.isRecycled()){ ... ... ... } } @Override public void onViewAttachedToWindow(@NonNull CustomViewHolder holder) { super.onViewAttachedToWindow(holder); holder.cur.setRecycled(false); }