تأثیر Enum بر عملکرد اپلیکیشن اندروید — راهنمای کاربردی

۱۰۴ بازدید
آخرین به‌روزرسانی: ۰۵ مهر ۱۴۰۲
زمان مطالعه: ۴ دقیقه
تأثیر Enum بر عملکرد اپلیکیشن اندروید — راهنمای کاربردی

در زمان کار روی اپلیکیشن‌های اندرویدی در موارد مختلف از انواع Enums استفاده می‌کنیم، چون کارآمد هستند، اما ممکن است تأثیر کامل آن‌ها را روی اپلیکیشن اندرویدی ندانید. Enum-ها یک روش آسان محسوب می‌شوند، اما متأسفانه زمانی که به مصرف حافظه آن‌ها و سرعتشان نگاه می‌کنیم نتایج خوشایندی نمی‌بینیم. در این مقاله به بررسی تأثیر Enums بر عملکرد اپلیکیشن اندروید می‌پردازیم.

Enum چیست؟

Enum در جاوا یک نوع داده است که شامل مجموعه مشخصی از ثابت‌ها است. این یک نوع داده خاص است که به ما امکان می‌دهد یک متغیر را روی یکی از مقادیر ثابت از پیش تعیین‌شده تنظیم کنیم. متغیر آن باید برابر با یکی از مقادیری باشد که از قبل برایش تعریف شده است.

چرا باید از Enum استفاده کنیم؟

ما از Enum در مواردی استفاده می‌کنیم که یک متغیر بتواند تنها یک مقدار را از میان یک مجموعه از مقادیر ممکن بگیرد. به مثال زیر توجه کنید:

1public enum Fruits{ Apple, Bannana, Grape, Mango }

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

هزینه Enum-ها

مقادیر Enum در مقایسه با یک ثابت int حافظه بیشتری مصرف می‌کنند. افزودن یک Enum منفرد موجب افزایش اندازه فایل DEX نهایی به میزان 13 برابر در قیاس با استفاده از ثابت صحیح می‌شود. دلیل این امر آن است که هر مقدار در یک کلاس Enum به عنوان یک شیء تلقی می‌شود و هر مقدار بخشی از حافظه هیپ را برای ارجاع به شیء اشغال می‌کند. این وضعیت موجب مصرف شدن حافظه زیادی می‌شود.

شاید حتی اطلاع نداشته باشید که استفاده از Enum موجب تأثیر روی عملکرد اپلیکیشن می‌شود. شاید نوشتن یک یا دو enum روی عملکرد کلی اپلیکیشن تأثیر قابل توجهی نداشته باشد، اما اگر از برخی کلاس‌های Enum در اپلیکیشن خود استفاده می‌کنید و برخی کتابخانه‌ها وجود دارند که از کلاس‌های Enum دیگری استفاده می‌کنند، در مجموع تأثیر عمده‌ای روی اپلیکیشن داشته باشند و اندازه فایل را افزایش داده و روی عملکرد اپلیکیشن نیز تأثیر سوئی بگذارند.

نکته: به طور کلی استفاده از Enum-ها در هیچ بخشی از کد اپلیکیشن توصیه نمی‌شود.

راه‌حل

اندروید از طیف متنوعی از حاشیه‌نویسی‌ها از طریق کتابخانه Annotations Support پشتیبانی می‌کند. از طریق پکیج android.support.annotation می‌توانید به این کتابخانه دسترسی داشته باشید. این کتابخانه حاشیه‌نویسی از نوع TypeDef دارد. این حاشیه‌نویسی وجود یک پارامتر خاصی، مقدار بازگشتی، یا فیلدی که به مجموعه خاصی از ثابت‌ها ارجاع می‌دهد را تضمین می‌کند. همچنین موجب می‌شود تکمیل کد به صورت خودکار، ثابت‌های مجاز را پیشنهاد کند.

IntDef@ و StringDef@ دو مورد از حاشیه‌نویسی‌های ثابت هستند که می‌توانند به جای enums برای ثابت‌های int و رشته‌ای استفاده شوند و موجب ایمنی زمان build می‌شوند. این حاشیه‌نویسی‌ها به ما کمک می‌کنند که آرگومان‌های متغیر را به روشی مانند enum-ها در زمان کامپایل بررسی کنیم.

چگونه از Annotations استفاده کنیم؟

این موضوع را با طرح یک مثال بررسی می‌کنیم. فرض کنید کلاس Fruit را با مجموعه‌ای از ثابت‌های int داریم. بنابراین در زمان ایجاد شیء باید مقدار نوع int را از مجموعه موجود ارسال کنیم. اما در متد main یک مقدار ارسال می‌کنیم که در مجموعه ثابت‌ها وجود ندارد و منجر به موقعیت مشکل سازی می‌شود. در قطعه کد زیر هیچ نوع «امنیت نوع» (type safety) وجود ندارد:

1public class Fruit {  
2     public static final int APPLE = 0;   
3     public static final int BANNANA = 1;    
4     public static final int GRAPE = 2;   
5     public static final int MANGO = 3;
6public Fruit(int fruit) {   
7       System.out.println("Fruit Selected:" + fruit);   
8     }
9public static void main(String[] args) {     
10       //Passing Invalid value       
11       Fruit fruit = new Fruit(4);    
12     }
13}

در ادامه پیاده‌سازی کد مشابهی وجود دارد که از enums به صورت زیر استفاده می‌کند:

1public class EnumFruit {
2   public EnumFruit(Fruit fruit) {             .                 
3   System.out.println("Fruit selected is:" + fruit);
4 }
5public enum Fruit {  
6    APPLE, BANNANA, GRAPE, MANGO   
7 }
8public static void main(String[] args) {        
9   EnumFruit enumFruitInstance = new EnumFruit(Fruit.APPLE);  
10 }
11}

وابستگی حاشیه‌نویسی پشتیبانی را در build.gradle سطح اپلیکیشن اضافه می‌کنیم:

1dependencies {
2    implementation 'com.android.support:support-annotations:28.0.0'
3}

ثابت‌ها و IntDef@ را برای این ثابت‌ها اعلان می‌کنیم:

1public class AnnotationFruit {     
2   public static final int APPLE = 0;    
3   public static final int BANNANA = 1;  
4   public static final int GRAPE = 2;    
5   public static final int MANGO = 3;   
6 
7   public AnnotationFruit(@Fruit int fruit) {         
8     System.out.println("Fruit Selected is :" + fruit);   
9   }
10@IntDef({APPLE, BANNANA, GRAPE, MANGO})        
11   @Retention(RetentionPolicy.SOURCE) 
12   public @interface Fruit {}
13public static void main(String[] args) {       
14   AnnotationFruit  annotationSeason = new AnnotationFruit(GRAPE);   
15   }
16}

در مثال فوق حاشیه‌نویسی Typedef از موارد زیر استفاده می‌کند:

  • از interface@ برای اعلان نوع حاشیه‌نویسی شمارشی جدید استفاده می‌کند.
  • از حاشیه‌نویسی‌های IntDef@ و StringDef@ همراه با Retentio@ استفاده می‌کند که برای تعریف نوع شمارشی ضروری هستند.

حاشیه‌نویسی Retention(RetentionPolicy.SOURCE)@ به کامپایلر اعلام می‌کند که داده‌های حاشیه‌نویسی شمارشی را در فایل ‎.class ذخیره نکند.

Setter-ها و getter-ها را می‌توان به صورت زیر تعریف کرد:

1// Decorate the target methods with the annotation     
2   @Fruit    
3   public abstract int getFruitName();
4// Attach the annotation    
5   public abstract void setFruitName(@Fruit int fuitValue);

اگر Proguard به درستی پیکربندی شده باشد، می‌تواند enum-ها را به نیابت از ما در پاره‌ای یا بسیاری از موقعیت‌ها به صورت مقادیر int بهینه‌سازی کند. بنابراین جای نگرانی وجود ندارد.

سخن پایانی

Enum-ها در مقایسه با ثابت‌های ساده دست کم دو برابر به بایت‌های اندازه کلی APK اضافه می‌کنند و در مقایسه با ثابت‌های معادل حدود 5 تا 10 برابر RAM بیشتری اشغال می‌کنند. از این رو اگر می‌خواهید اپلیکیشن شما از نظر مصرف حافظه و عملکرد بهینه باشد، باید از استفاده از enum-ها در کد خود اجتناب کنید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
better-programming
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *