چطور Adapter تمیز با کارایی بهتر داشته باشیم؟

اگر برنامه نویس اندروید هستید حتما تاحالا از adapter ها استفاده کردید و می دونید که adapter ها وظیفه هندل کردن نمایش آیتم های لیست رو برعهده دارن تا بدون مصرف بیش از اندازه رم، لیست های بینهایت رو نمایش بدن. و حتما هروقت سراغ پیاده سازی یک adapter رفتید با کدهای اضافی که هربار مجبوریم پیاده سازی کنیم و کلاس ViewHolder که بعد از اومدن binding ها به کدهای اضافی تبدیل شدن، مواجه شدیم.اگر شماهم مثل من با کم کردن یک خط از کداتون احساس رضایت مندی می کنید، این پست رو تا انتها بخونید تا با هم یک adapter با کدهای خیلی کمتر، اما واقعا با کارایی بیشتر پیاده سازی کنیم ?پیش نیاز ها:آشنایی با View bindingآشنایی با کلاس های Genericآشنایی با Code foldingآشنایی با متدهای abstractنکته: در این پست، تمامی تصاویر متعلق به سه کلاس ViewHodler, BaseAdapter, ExampleAdapter می باشند.شروع:در پایین تصویر adapter بهینه نشده رو می بینید که قراره به تصویر دوم تبدیل بشه:اداپتر بهینه نشدهاداپتر بهینه شدهمواردی که قراره بهبود پیدا کنن:کدهای تکراری مانند context و items که در تمام adapter ها استفاده می شن، از اینجا حذف می شن.پارامترهای متد onBindViewHolder شخصی سازی می شن تا هربار نیاز نباشه با استفاده از position یک مدل بسازیم یا در این حالت، binding رو از holder بگیریم و بصورت مستقیم بهشون دسترسی داشته باشیم.متدها و کلاس هایی مانند getItemCount و ViewHolder هم که خوانایی کد رو کم می کنن نیازی نیست هربار اینجا صدا زده بشن یا پیاده سازی بشن.همچنین متدهایی هم که کار تکراری انجام می دن اما نمی تونیم به جای دیگه ای منتقلشون کنیم، می تونن با روش folding جلوی چشم نباشن تا خوانایی کد افزایش پیدا کنه.پیاده سازی:1. Generic ViewHolderViewHolderدر مرحله اول برای اینکه مجبور نباشیم برای هر adapter یک زیرکلاس ViewHolder بسازیم، می تونیم یک کلاس جنریک ViewHolder بسازیم و برای هر adapter از همین کلاس استفاده کنیم.این کلاس فقط نیاز داره تا جنس ViewBinding رو بصورت generic دریافت کنه.1. Generic BaseAdapterBaseAdapter در مرحه بعد نیاز داریم تا یک کلاس BaseAdapter بسازیم و موارد زیر رو بصورت generic براش مشخص کنیم:جنس ViewBinding با شناسه Bجنس لیست آیتم ها با شناسه Iجنس ViewHolder با شناسه V3. Override onBindViewHolderدر کلاس BaseAdapter متد onBindViewHolder رو override می کنیم اما ما نمی خوایم که از همین متد در adapter هامون استفاده کنیم، در نتیجه یک متد بصورت abstract به همین نام (می تونه هر نامی داشته باشه) با پارامترهای دلخواه ایجاد می کنیم و در adapter ها همین متد رو override می کنیم.BaseAdapter پارامترهایی که من برای این متد درنظر گرفتم، این موارده:پارامتر item : مدلی که هر بار نیاز بود تا توسط position از لیست دریافت کنمپارامتر binding : که هربار نیاز بود از holder دریافت کنمپارامتر position : که هربار باید با متد getAbsoluteAdapterPosition دوباره دریافتش می کردم4. Folding Constractorsخب می رسیم به مواردی که در adapter ها تکراری هستن و نیازی نیست دائما جلوی چشم باشن و خوانایی کد رو کم کنن.Adapterهمینطور که در کلاس BaseAdapter می بینید از خط 21 تا 30، کدهایی هستن که مقداردهی های اولیه رو انجام می دن و مسلما نیازی نیست تا دائما جلوی چشم ما باشن.در اینجا با استفاده از دو تگ (کامنت) زیر می تونیم این محدوده رو بعنوان code folding معین کنیم تا محیط توسعه این خطوط رو به ما نمایش نده.//region <name> ... //endregionSettingsالبته برای این که این محدوده بصورت پیشفرض Collapse باشه و نمایش داده نشه، باید در تنظیمات تیک گزینه Custom folding regions رو فعال کنید.تمام، adapter ما با حداقل کد و شخصی سازی های مدنظرمون آمادست ?باقی موارد مثلprotected بودن filed ها در BaseAdapter و Override کردن متد getItemCount در BaseAdapter برای جلوگیری از تکرار و ... فکر نمی کنم نیازی به توضیح داشته باشن و همین موارد گویای کار هست.اگر سوال یا ابهامی دارید در کامنتا مطرح کنید و اگر شما هم روشی دارید که می شه این آداپتر رو بهینه تر کنیم، خوشحال می شم به تکمیل این پست کمک کنید.