การทำงานกับ Enums ใน Android


120

ฉันเกือบจะเสร็จสิ้นกับกิจกรรมการคำนวณที่ฉันกำลังทำงานใน Android สำหรับแอปของฉัน ฉันพยายามสร้าง Gender Enum แต่ด้วยเหตุผลบางประการที่ทำให้เกิดข้อผิดพลาดทางไวยากรณ์ให้ใส่ "EnumBody" เพื่อกรอก EnumDeclaration

public static enum Gender
{
    static
    {
        Female = new Gender("Female", 1);
        Gender[] arrayOfGender = new Gender[2];
        arrayOfGender[0] = Male;
        arrayOfGender[1] = Female;
        ENUM$VALUES = arrayOfGender;
    }
}

ฉันได้ลองใช้โดยไม่คงที่ {} แต่ฉันได้รับข้อผิดพลาดทางไวยากรณ์เดียวกัน


ไม่แนะนำให้ใช้ Enums สำหรับปัญหาด้านประสิทธิภาพให้ใช้ค่าคงที่ดั้งเดิมแทน youtube.com/watch?v=Hzs6OBcvNQE
Myke Dev

UPDATE 2019: Enums จะมีการปรับการใช้งานใน Android ตั้งแต่ ART แทนที่ Dalvik เป็นสภาพแวดล้อมรันไทม์stackoverflow.com/a/56296746/4213436 ดังนั้นฉันคิดว่าคำตอบส่วนใหญ่ในหัวข้อนี้ไม่เกี่ยวข้อง
JDenais

@JDenais แน่นอนว่าคุณหมายถึงกระทู้ 'คุณ' ที่เพิ่งอ้างอิง
YoussefDir

คำตอบ:


343

คุณพบไวยากรณ์นี้ที่ไหนในโลก Java Enums นั้นง่ายมากคุณเพียงแค่ระบุค่า

public enum Gender {
   MALE,
   FEMALE
}

หากคุณต้องการให้มีความซับซ้อนมากขึ้นคุณสามารถเพิ่มค่าให้กับค่าเหล่านี้ได้เช่นนี้

public enum Gender {
    MALE("Male", 0),
    FEMALE("Female", 1);

    private String stringValue;
    private int intValue;
    private Gender(String toString, int value) {
        stringValue = toString;
        intValue = value;
    }

    @Override
    public String toString() {
        return stringValue;
    }
}

จากนั้นในการใช้ enum คุณจะต้องทำสิ่งนี้:

Gender me = Gender.MALE

12
ฉันจะให้ลองฉันบอกว่าฉันเป็นมือใหม่แน่นอน
JMSDEV

87
ขอโทษนะฉันไม่ได้หมายความในแง่ลบ เป็นเพียงไวยากรณ์ที่แปลกประหลาดที่สุดที่ฉันเคยเห็นสำหรับ Enum
Spidy

4
นอกจากนี้ยังมีประโยชน์ในการกล่าวถึง enums เป็นลำดับดังนั้นคุณสามารถใช้ .ordinal () บน enum เพื่อรับค่า int
Kalel Wade

1
ไวยากรณ์ในคำถามเป็นแบบที่อาจเกิดขึ้นจากการใช้ตัวถอดรหัส
Dan Getz

9
ฉันขำมากว่า "คุณเจอไวยากรณ์นี้ที่ไหนในโลก" พูดเหมือนครูกับนักเรียน
Zar E Ahmer

50

มีการถกเถียงกันเกี่ยวกับประเด็นแห่งความขัดแย้งนี้ แต่แม้กระทั่งในเอกสารล่าสุดของแอนดรอยด์ก็แนะนำว่าไม่ควรใช้ enums ในแอปพลิเคชัน Android สาเหตุเป็นเพราะพวกเขาใช้หน่วยความจำมากกว่าตัวแปรคงที่ นี่คือเอกสารจากหน้าปี 2014 ที่ให้คำแนะนำเกี่ยวกับการใช้ enums ในแอปพลิเคชัน Android http://developer.android.com/training/articles/memory.html#Overhead

ฉันอ้าง:

ระวังหน่วยความจำเหนือศีรษะ

มีความรู้เกี่ยวกับต้นทุนและค่าใช้จ่ายของภาษาและไลบรารีที่คุณใช้และคำนึงถึงข้อมูลนี้เมื่อคุณออกแบบแอปตั้งแต่ต้นจนจบ บ่อยครั้งสิ่งที่อยู่บนพื้นผิวที่ดูไม่มีพิษภัยอาจมีค่าใช้จ่ายจำนวนมาก ตัวอย่าง ได้แก่ :

  • Enums มักต้องการหน่วยความจำมากกว่าสองเท่าของค่าคงที่ คุณควรหลีกเลี่ยงการใช้ enums บน Android อย่างเคร่งครัด

  • ทุกคลาสใน Java (รวมถึงคลาสภายในที่ไม่ระบุชื่อ) ใช้โค้ดประมาณ 500 ไบต์

  • อินสแตนซ์คลาสทุกตัวมีค่าใช้จ่าย RAM 12-16 ไบต์

  • การใส่รายการเดียวลงใน HashMap จำเป็นต้องมีการจัดสรรอ็อบเจ็กต์รายการเพิ่มเติมที่ใช้เวลา 32 ไบต์ (ดูส่วนก่อนหน้าเกี่ยวกับคอนเทนเนอร์ข้อมูลที่ปรับให้เหมาะสม)

ไม่กี่ไบต์ที่นี่และเพิ่มขึ้นอย่างรวดเร็ว - การออกแบบแอปที่มีคลาสหรืออ็อบเจ็กต์มากจะได้รับผลกระทบจากค่าใช้จ่ายนี้ สิ่งนี้อาจทำให้คุณอยู่ในตำแหน่งที่ยากลำบากในการดูการวิเคราะห์ฮีปและการตระหนักถึงปัญหาของคุณคือวัตถุขนาดเล็กจำนวนมากที่ใช้ RAM ของคุณจนหมด

มีบางสถานที่ที่พวกเขากล่าวว่าเคล็ดลับเหล่านี้ล้าสมัยและไม่มีคุณค่าอีกต่อไป แต่เหตุผลที่พวกเขายังคงทำซ้ำนั้นต้องมีความจริงอยู่บ้าง การเขียนแอปพลิเคชัน Android เป็นสิ่งที่คุณควรทำให้มีน้ำหนักเบาที่สุดเพื่อประสบการณ์การใช้งานที่ราบรื่น และทุก ๆ นิ้วของประสิทธิภาพมีค่า!


มีสถานที่บางแห่ง - คุณสามารถเพิ่มได้หรือไม่ถ้าคุณรู้จัก เพราะหาไม่เจอ
Krzysztof Skrzynecki

9
ที่นี่มีคนสังเกตว่าข้อมูลเกี่ยวกับการใช้ ints แทน enums ถูกลบออกจากคำแนะนำด้านประสิทธิภาพในเอกสารอย่างเป็นทางการ นอกจากนี้ฉันได้ทำการวิจัยและโพสต์สรุปเกี่ยวกับ reddit
Krzysztof Skrzynecki

1
รูปแบบประสิทธิภาพของ Android: ราคาของ ENUMs (100 วันของ Google Dev)
Afriza N. Arief

พวกคำถามของฉันคือถ้า Enum ปฏิบัติ "ไม่ดี" เหตุใด Google จึงยังสนับสนุนคุณลักษณะนี้ของ Java กับ Android :(
Jesús Castro

5
@ JesúsCastroเนื่องจาก Google ต้องการให้แน่ใจว่า บริษัท ที่มีตรรกะทางธุรกิจ Java ที่มีอยู่จำนวนมาก (ซึ่งอาจใช้ enums) สามารถทิ้งไลบรารีของตนลงในโครงการ Android และไปได้
David Brown

22

ตามความคิดเห็นของ Chris enums ต้องการหน่วยความจำมากขึ้นบน Android ซึ่งจะเพิ่มขึ้นเมื่อใช้งานได้ทุกที่ คุณควรลองใช้IntDefหรือStringDefแทนซึ่งใช้คำอธิบายประกอบเพื่อให้คอมไพเลอร์ตรวจสอบค่าที่ส่งผ่าน

public abstract class ActionBar {
...
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
@Retention(RetentionPolicy.SOURCE)
public @interface NavigationMode {}

public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;

@NavigationMode
public abstract int getNavigationMode();

public abstract void setNavigationMode(@NavigationMode int mode);

นอกจากนี้ยังสามารถใช้เป็นแฟล็กเพื่อให้สามารถจัดองค์ประกอบไบนารี (การดำเนินการ OR / AND)

แก้ไข : ดูเหมือนว่าเปลี่ยน enums เข้า ints เป็นหนึ่งในการเพิ่มประสิทธิภาพในการเริ่มต้น Proguard


3
ฉันต้องการวางค่าคงที่ int ไว้ในคลาสคำอธิบายประกอบโดยตรง จึงดูเหมือน enum ปกติ ฉันอธิบายไว้ที่นี่: blog.shamanland.com/2016/02/int-string-enum.html
Oleksii K.


9

ตามวิดีโอนี้หากคุณใช้ ProGuard คุณไม่จำเป็นต้องคิดเกี่ยวกับปัญหาประสิทธิภาพของ Enums !!

Proguard สามารถเพิ่มประสิทธิภาพ Enums เป็นค่า INT แทนคุณได้ในหลาย ๆ สถานการณ์ดังนั้นคุณจึงไม่จำเป็นต้องคิดถึงมันหรือทำงานใด ๆ


4

แนวทางที่ต้องการของ Android คือค่าคงที่บังคับกับ @IntDef:

public static final int GENDER_MALE = 1;
public static final int GENDER_FEMALE = 2;

@Retention(RetentionPolicy.SOURCE)
@IntDef ({GENDER_MALE, GENDER_FEMALE})
public @interface Gender{}

// Example usage...
void exampleFunc(@Gender int gender) {
  switch(gender) {
  case GENDER_MALE:

     break;
  case GENDER_FEMALE:
     // TODO
     break;
  }
}

เอกสาร: https://developer.android.com/studio/write/annotations.html#enum-annotations

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.