ادغام آداپتورها به صورت متوالی با MergeAdapte

ترجمه و تالیف : پوریا شریفی
تاریخ انتشار : 22 خرداد 99
خواندن در 2 دقیقه
دسته بندی ها : اندروید

 MergeAdapter یک کلاس جدید در کتابخانه‌ی recyclerview:1.2.0-alpha02 است، که شما را قادر می‌سازد چند آداپتور را به صورت متوالی ترکیب کرده تا در یک RecyclerView نمایش داده شود. این قابلیت در کپسوله کردن بهتر آداپتورها به ما کمک می‌کند جای اینکه داده‌های زیادی را در یک آداپتور ترکیب کنیم، که آداپتورها را متمرکز و قابل استفاده‌ی مجدد می‌کند.

یک مورد استفاده برای آن، نمایش وضعیت بارگزاری لیست در Header یا Footer است، وقتی لیست درحال دریافت اطلاعات از شبکه است، می‌خواهیم یک pregress spinner را نمایش دهیم؛ در صورت بروز خطا، می‌خواهیم خطا و یک دکمه‌ی امتحان مجدد را نمایش دهیم.

ادغام آداپتورها به صورت متوالی با MergeAdapte

معرفی MergeAdapter

MergeAdapter به ما اجازه می‌دهد که محتوای چند آداپتور را به صورت متوالی نمایش ‌دهیم، برای مثال، باید بگوییم که سه آداپتور زیر را داریم:

val firstAdapter: FirstAdapter = …
val secondAdapter: SecondAdapter = …
val thirdAdapter: ThirdAdapter = …
val mergeAdapter = MergeAdapter(firstAdapter, secondAdapter, 
     thirdAdapter)
recyclerView.adapter = mergeAdapter

RecyclerView آیتم‌های هر آداپتور را به صورت متوالی نمایش می‌دهد.

داشتن آداپتورهای مختلف به شما اجازه می‌دهد وابستگی‌های هر قسمت متوالی لیست را بهتر از هم جدا کنید. برای مثال اگر می‌خواهید یک Header را نمایش دهید، نیاز ندارید منطق مربوط به Header را در همان آداپتور که نمایش لیست را کنترل می‌کند قرار دهید، به جای آن می‌توانید آن را در آداپتور مخصوص خود کپسوله کنید.

ادغام آداپتورها به صورت متوالی با MergeAdapte

نمایش وضعیت بارگزاری در Header و Footer

Header یا Footer نشانگر پیشرفت را نشان می‌دهد و یا خطایی را گزارش می‌کند. وقتی لیست با موفقیت بارگذاری را به پایان می‌رساند، Header یا Footer نباید چیزی را نمایش دهند. بنابراین می‌توان آن‌ها را به‌عنوان لیست با 0 یا 1 آیتم با آداپتور مخصوص خود نشان داد.

val mergeAdapter = MergeAdapter(headerAdapter, listAdapter, 
    footerAdapter)
recyclerView.adapter = mergeAdapter

اگر هم Header و هم Footer از یک Layout مشابه، ViewHolder و Ui استفاده می‌کنن (مثلا وقتی که نوار پیشرفت نمایش داده می‌شود)، می‌توانید فقط یک کلاس آداپتور را پیاده‌سازی کنید و دو نمونه از آن‌را ایجاد کنید، یکی برای Header و یکی برای Footer.

برای پیاده‌سازی کامل، این pull request را برسی کنید که شامل:

  • وضعیت بارگزاری که در معرض دید ViewModel قرار دارد
  • Layout برای وضعیت براگزاری Header و Footer
  • شیء ViewHolder برای Header و Footer
  • یک ListAdapter که آیتم 0 یا 1 را براساس وضعیت بارگزاری نمایش می‌دهد. هر بار که وضعیت بارگزاری تغییر کند، متوجه خواهیم شد که آیتم نیاز به تغییر دارد، آن‌ را اضافه و یا حذف کنید.( برای مشاهده کدها به این لینک بروید ).

اطلاعات بیشتر در مورد MergeAdapter

ViewHolders

به صورت پیش‌فرض، هر آداپتور ViewHolder خود را بدون استفاده‌ی مجدد بین آداپتورها حفظ می‌کند. اگر چند آداپتور یک ViewHolder را نمایش دهند، ممکن است که بخواهیم از همان نمونه بین آن‌ها استفاده کنیم. برای دستیابی به این موضوع ما می‌توانیم شیء MergeAdapter را با MergeAdapter.Config بسازیم، که isolatedViewType = false می‌شود. با این عمل تمام آداپتورهای ادغام شده از یک View استفاده می‌کنند. در مثال وضعیت بارگذاری Header و Footer، هر دو ViewHolder درواقع همان محتوا را نمایش می‌دهند بنابراین می‌توانیم از آن‌ها دوباره استفاده کنیم.

برای پشتیبانی از ViewHolderهای مختلف، باید Adapter.getItemViewType را پیاده‌سازی کنید. وقتی که از ViewHolder استفاده‌ی مجدد می‌کنید، مطمئن شوید که ViewType به ViewHolder دیگری اشاره نمی‌کند. بهترین کار این است که Layout ID را به‌عنوان ViewType برگردانید.

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
   
class HeaderAdapter() : RecyclerView.Adapter<LoadingStateViewHolderHeaderViewHolder>() { 

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return LoadingStateViewHolder(parent)
}

    override fun getItemViewType(position: Int): Int {
-       return 0
+	   return R.layout.list_loading
    }
}

class FooterAdapter() : RecyclerView.Adapter<LoadingStateViewHolderFooterViewHolder>() { 

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return LoadingStateViewHolder(parent)
}

    override fun getItemViewType(position: Int): Int {
-      return 0
+	  return R.layout.list_loading
    }
}

استفاده از Idهای پایدار

به جای استفاده از شناسه‌های پایدار به همراه notiFyDataSetChanged، توصیه می‌شود از رویداد notify مخصوص آداپتور استفاده کنید، که اطلاعات بیشتری به RecyclerView در مورد تغییرات مجموعه داده می‌دهد. که این امکان را به RecyclerView می‌دهد موثرتر Ui و انیمیشن را بروز کند. اگر از ListAdapte استفاده می‌کنید رویدادهای notify برای شما با کمک DiffUtil CallBack اداره می‌شود. اما در صورت نیاز به استفاده از شناسه‌های پایدار، MergeAdapter.Config سه نوع تنظیم مختلف برای شناسه‌های پایدار ارائه می‌دهد: NO_STABLE_IDS, ISOLATED_STABLE_IDS و SHARED_STABLE_IDS. دومورد آخر به شما نیاز دارند تا شناسه‌های پایدار را در آداپتور کنترل کنند. برای طلاعات بیشتر از نحوه‌ی کار آن‌ها StableIdMode را بررسی کنید.

تغییر داده‌ها با notify

وقتی که یکی از آداپتورهای MergeAdapter، یکی از توابع Notify را فرا می‌خواند، MergeAdapter قبل از بروزرسانی RecyclerView موقعیت آیتم جدید را محاسبه می‌کند.

 از نظر RecyclerView، notifyItemRangeChanged به این معنی است که آیتم‌ها یکی هستند و فقط محتوای آن‌ها تغییر کرده است. notifyDataSetChanged یعنی که هیچ رابطه‌ای بین قبل و بعد وجود ندارد. از این رو نمی‌توانیم notifyDataSetChanged را به جای notifyItemRangeChanged کنیم.

اگر آداپتوری Adapter.notifyDataSetChanged را فراخوانی کند، MergeAdapter نیز Adapter.notifyDataSetChanged را به جای Adapter.notifyItemRangeChanged فراخوانی می‌کند. طبق معمول با استفاده از RecyclerView از Adapter.notifyDataSetChange پرهیز کنید، بروزرسانی‌های تکی را استفاده کنید و یا از پیاده‌سازی‌های آداپتور که این کار را خودکار انجام می‌دهند، مانند ListAdapter یا SortedList استفاده کنید.

یافتن موقعیت ViewHolder

ممکن است در گذشته از ViewHolder.getAdpaterPostion استفاده کرده باشید تا موقعیت یک ViewHolder را در آداپتور به دست آورید. اکنون چون چندین آداپتور را ادغام می‌کنیم، از ViewHolder.getBindingAdapterPostion() استفاده کنید. اگر می‌خواهید آخرین آداپتوری که به ViewHolder متصل شده است را بدست اورید، در موردی که ViewHolder را به اشتراک می‌گذارید، از Adapter,getBindingAdapter() استفاده کنید.

اگر می‌خواهید داده‌های مختلف را به صورت متوالی نمایش دهید بهتر است که آن‌ها را در آداپتور مخصوص خود کپسوله کنید و از MergeAdapter استفاده کنید.

منبع

گردآوری و تالیف پوریا شریفی
آفلاین
user-avatar

ابتدا که با برنامه‌نویسی آشنا شدم به سمت php و طراحی وب رفتم، بعد از اون به توسعه‌ی اندروید علاقه‌مند شدم و تقریبا ۲ سال است که مشغول به برنامه‌نویسی اندروید هستم، همچنین عاشق یادگیری چیزهای جدید هستم.

دیدگاه‌ها و پرسش‌ها

برای ارسال نظر لازم است ابتدا وارد سایت شوید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید