ผ่าน Enum หรือวัตถุผ่านเจตนา (ทางออกที่ดีที่สุด)


221

ฉันมีกิจกรรมที่เมื่อเริ่มต้นต้องการเข้าถึง ArrayLists ที่แตกต่างกันสองรายการ ทั้งสองรายการเป็นวัตถุต่าง ๆ ที่ฉันสร้างขึ้นเอง

โดยพื้นฐานแล้วฉันต้องการวิธีส่งวัตถุเหล่านี้ไปยังกิจกรรมจากเจตนา ฉันสามารถใช้ addExtras () ได้ แต่สิ่งนี้ต้องการคลาสที่เข้ากันได้กับ Parceable ฉันสามารถทำให้คลาสของฉันผ่านการทำให้เป็นอนุกรมได้ แต่เนื่องจากฉันเข้าใจว่านี่ทำให้โปรแกรมช้าลง

ตัวเลือกของฉันคืออะไร?

ฉันจะส่ง Enum ได้ไหม

ในฐานะที่เป็นกัน: มีวิธีการส่งพารามิเตอร์ไปยังตัวสร้างกิจกรรมจากเจตนาหรือไม่?


บางทีฉันหายไปบางอย่าง แต่ enum เกี่ยวข้องกับ ArrayList อย่างไร
Martin Konecny

คำตอบ:


558

นี่เป็นคำถามเก่า แต่ทุกคนล้มเหลวที่จะพูดถึงว่า Enums เป็นจริงSerializableและดังนั้นจึงสามารถเพิ่มเข้ากับเจตนาเป็นพิเศษได้อย่างสมบูรณ์แบบ แบบนี้:

public enum AwesomeEnum {
  SOMETHING, OTHER;
}

intent.putExtra("AwesomeEnum", AwesomeEnum.SOMETHING);

AwesomeEnum result = (AwesomeEnum) intent.getSerializableExtra("AwesomeEnum");

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


ทางเลือก:

จุดที่ดีคือการสังเกตโดยtedzycเกี่ยวกับความจริงที่ว่าวิธีการแก้ปัญหาโดยOderikให้ข้อผิดพลาด อย่างไรก็ตามทางเลือกที่นำเสนอนั้นค่อนข้างยุ่งยากในการใช้ (แม้จะใช้ยาชื่อสามัญ)

หากคุณกังวลเกี่ยวกับประสิทธิภาพของการเพิ่ม enum ในเจตจำนงฉันขอเสนอทางเลือกเหล่านี้แทน:

ตัวเลือกที่ 1:

public enum AwesomeEnum {
  SOMETHING, OTHER;
  private static final String name = AwesomeEnum.class.getName();
  public void attachTo(Intent intent) {
    intent.putExtra(name, ordinal());
  }
  public static AwesomeEnum detachFrom(Intent intent) {
    if(!intent.hasExtra(name)) throw new IllegalStateException();
    return values()[intent.getIntExtra(name, -1)];
  }
}

การใช้งาน:

// Sender usage
AwesomeEnum.SOMETHING.attachTo(intent);
// Receiver usage
AwesomeEnum result = AwesomeEnum.detachFrom(intent);

ตัวเลือกที่ 2: (ทั่วไปนำมาใช้ใหม่และแยกออกจาก enum)

public final class EnumUtil {
    public static class Serializer<T extends Enum<T>> extends Deserializer<T> {
        private T victim;
        @SuppressWarnings("unchecked") 
        public Serializer(T victim) {
            super((Class<T>) victim.getClass());
            this.victim = victim;
        }
        public void to(Intent intent) {
            intent.putExtra(name, victim.ordinal());
        }
    }
    public static class Deserializer<T extends Enum<T>> {
        protected Class<T> victimType;
        protected String name;
        public Deserializer(Class<T> victimType) {
            this.victimType = victimType;
            this.name = victimType.getName();
        }
        public T from(Intent intent) {
            if (!intent.hasExtra(name)) throw new IllegalStateException();
            return victimType.getEnumConstants()[intent.getIntExtra(name, -1)];
        }
    }
    public static <T extends Enum<T>> Deserializer<T> deserialize(Class<T> victim) {
        return new Deserializer<T>(victim);
    }
    public static <T extends Enum<T>> Serializer<T> serialize(T victim) {
        return new Serializer<T>(victim);
    }
}

การใช้งาน:

// Sender usage
EnumUtil.serialize(AwesomeEnum.Something).to(intent);
// Receiver usage
AwesomeEnum result = 
EnumUtil.deserialize(AwesomeEnum.class).from(intent);

ตัวเลือก 3 (พร้อม Kotlin):

ไม่นานมานี้ แต่ตั้งแต่ตอนนี้เรามี Kotlin ฉันคิดว่าฉันจะเพิ่มตัวเลือกใหม่สำหรับกระบวนทัศน์ใหม่ ที่นี่เราสามารถใช้ประโยชน์จากฟังก์ชั่นส่วนขยายและประเภท reified (ซึ่งยังคงประเภทเมื่อรวบรวม)

inline fun <reified T : Enum<T>> Intent.putExtra(victim: T): Intent =
    putExtra(T::class.java.name, victim.ordinal)

inline fun <reified T: Enum<T>> Intent.getEnumExtra(): T? =
    getIntExtra(T::class.java.name, -1)
        .takeUnless { it == -1 }
        ?.let { T::class.java.enumConstants[it] }

มีประโยชน์เล็กน้อยในการทำเช่นนี้

  • เราไม่ต้องการ "ค่าใช้จ่าย" ของวัตถุตัวกลางในการทำซีเรียลinlineไลเซชั่นเพราะมันเสร็จเรียบร้อยแล้วขอบคุณที่จะแทนที่การโทรด้วยรหัสภายในฟังก์ชั่น
  • ฟังก์ชั่นนี้มีความคุ้นเคยมากกว่าเนื่องจากคล้ายกับ SDK
  • IDE จะเติมข้อความอัตโนมัติให้กับฟังก์ชั่นเหล่านี้ซึ่งหมายความว่าไม่จำเป็นต้องมีความรู้ก่อนหน้านี้เกี่ยวกับคลาสยูทิลิตี้

ข้อเสียอย่างหนึ่งคือถ้าเราเปลี่ยนลำดับของ Emums การอ้างอิงเก่า ๆ จะไม่ทำงาน นี่อาจเป็นปัญหากับสิ่งต่าง ๆ เช่น Intent ภายใน Intent ที่ค้างอยู่เนื่องจากอาจอยู่รอดจากการอัปเดต อย่างไรก็ตามสำหรับเวลาที่เหลือมันก็โอเค

สิ่งสำคัญคือต้องทราบว่าโซลูชันอื่น ๆ เช่นการใช้ชื่อแทนตำแหน่งจะล้มเหลวหากเราเปลี่ยนชื่อค่าใด ๆ แม้ว่าในกรณีเหล่านั้นเราจะได้รับข้อยกเว้นแทนค่า Enum ที่ไม่ถูกต้อง

การใช้งาน:

// Sender usage
intent.putExtra(AwesomeEnum.SOMETHING)
// Receiver usage
val result = intent.getEnumExtra<AwesomeEnum>()

14
+1 สำหรับการชี้ให้เห็นว่าเป็น "ความคิดที่ไม่ดีจริง ๆ " เพื่อทำให้แอปพลิเคชันกว้างขึ้น
bugfixr

3
จริง ๆ แล้วฉันทำงานในโครงการที่ฉันไม่ต้องการจัดการกับอนุกรมหรือวัตถุที่รวมเป็นกลุ่ม (วัตถุจำนวนมากที่มีตัวแปรจำนวนมากในพวกเขา) และการใช้ตัวแปรโกลบอลคงที่ดี ... จนกว่าเพื่อนร่วมทีมจะเข้าสู่ โครงการ. ค่าใช้จ่ายในการพยายามประสานการใช้กลมเหล่านั้นทำให้ฉันไป "ขันมันฉันกำลังเขียนตัวสร้างรหัสเพื่อทำให้พัสดุบางอย่าง" จำนวนข้อบกพร่องลดลงอย่างมีนัยสำคัญ
Joe Plante

2
@Ceffect ใช่มันเป็นคำแนะนำที่เข้าใจได้ แต่ในกรณีส่วนใหญ่สิ่งนี้อาจมีคุณสมบัติเป็นการเพิ่มประสิทธิภาพก่อนวัยอันควรเว้นแต่คุณจะแจงนับพัน enums (ซึ่งโดยธรรมชาติแล้วพวกเขาควรจะมีเพียงไม่กี่คนที่พวกเขาจะจัดการสถานะ) บน Nexus 4 คุณได้รับการปรับปรุง 1ms ( developerphil.com/parcelable-vs-serializable ) ไม่แน่ใจว่ามันคุ้มค่ากับการทำงานของขาพิเศษ แต่แล้วอีกครั้งคุณมีทางเลือกอื่น ๆ ที่ฉันแนะนำ;)
pablisco

1
@rgv ภายใต้ฝากระโปรง Kotlin compiles ข้ามenum classประเภทกับ enumJava ฉันเดาวิธีแก้ปัญหาที่ง่ายกว่าคือการทำให้การenum classใช้งานSerializable: enum class AwesomeEnum : Serializable { A, B, C }ไม่เหมาะ แต่ควรทำงาน
pablisco

1
@ เปียโนเช่นเดียวกับคำตอบที่ดีใด ๆ มี "มันขึ้นอยู่กับ" ไม่จำเป็นต้องขยาย Serialisable คำตอบเบื้องต้นนั้นถูกต้อง ตัวเลือกพิเศษเหล่านั้นคือในกรณีที่คุณมีกรณีที่อาจมีคอขวดเหมือนว่าคุณมีบันทึกนับล้านระเบียน (หวังว่าจะไม่) ใช้สิ่งที่คุณเห็นว่าเหมาะสม ...
pablisco

114

คุณสามารถทำให้ enum ใช้ Parcelable ได้ซึ่งค่อนข้างง่ายสำหรับ enums:

public enum MyEnum implements Parcelable {
    VALUE;


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(final Parcel dest, final int flags) {
        dest.writeInt(ordinal());
    }

    public static final Creator<MyEnum> CREATOR = new Creator<MyEnum>() {
        @Override
        public MyEnum createFromParcel(final Parcel source) {
            return MyEnum.values()[source.readInt()];
        }

        @Override
        public MyEnum[] newArray(final int size) {
            return new MyEnum[size];
        }
    };
}

จากนั้นคุณสามารถใช้ Intent.putExtra (String, Parcelable)

อัปเดต: โปรดทราบความคิดเห็นของ wreckgar ที่enum.values()จัดสรรอาร์เรย์ใหม่ในแต่ละการโทร

อัปเดต: Android Studio มีเทมเพลตสดParcelableEnumที่ใช้โซลูชันนี้ (สำหรับ Windows ให้ใช้Ctrl+ J)


3
นอกจากนี้ยังเป็นไปได้วิธีการ toString () และ valueOf () enum ของแทนการจัดอันดับ
Natix

2
การใช้ลำดับ () อาจแตกเมื่อนักพัฒนาแทรกสมาชิก enum ใหม่ แน่นอนว่าการเปลี่ยนชื่อสมาชิก enum จะทำให้แตกชื่อ () ด้วย แต่ผู้พัฒนามีแนวโน้มที่จะแทรกสมาชิกใหม่แทนที่จะเปลี่ยนชื่อเนื่องจากการเปลี่ยนชื่อกำหนดให้เขาต้องคำนึงถึงปัจจัยทั้งหมดของโครงการ
Cheok Yan Cheng

2
ฉันไม่ยอมรับว่าค่า enum เพิ่มเติม (หรือเรียงลำดับใหม่) มีแนวโน้มมากกว่าการเปลี่ยนชื่อ การใช้ IDE ที่มีความซับซ้อนเช่นการปรับโครงสร้าง IntelliJ IDEA ไม่ใช่เรื่องใหญ่ แต่ประเด็นของคุณยังดี: คุณต้องตรวจสอบให้แน่ใจว่าการทำให้เป็นอนุกรมนั้นสอดคล้องกันตลอดการใช้งานร่วมกัน นั่นเป็นความจริงสำหรับการจัดลำดับใด ๆ ฉันคิดว่าในกรณีส่วนใหญ่พัสดุจะถูกส่งไปรอบ ๆ แอปพลิเคชั่นเดียวที่มีการใช้งานเพียงหนึ่งครั้งเท่านั้นดังนั้นจึงไม่ควรเป็นปัญหา
Oderik

2
ค่า () สร้างอาร์เรย์ใหม่ในทุกการโทรดังนั้นควรเก็บไว้ในแคชเช่น อาร์เรย์คงที่แบบส่วนตัว
wreckgar23

2
ความจริงที่ว่าในกรณีทั่วไป (เช่นการจัดเก็บฐานข้อมูล) ลำดับ () ไม่ปลอดภัยไม่เกี่ยวข้องกับพัสดุ Android พัสดุภัณฑ์ไม่ได้มีไว้สำหรับการจัดเก็บข้อมูลระยะยาว (ถาวร) พวกเขาตายด้วยแอป ดังนั้นเมื่อคุณเพิ่ม / เปลี่ยนชื่อ enum คุณจะได้รับพัสดุใหม่
noamtm

24

คุณสามารถส่ง enum ผ่านเป็นสตริงได้

public enum CountType {
    ONE,
    TWO,
    THREE
}

private CountType count;
count = ONE;

String countString = count.name();

CountType countToo = CountType.valueOf(countString);

สนับสนุนสตริงที่กำหนดคุณควรจะสามารถส่งผ่านค่าของ enum รอบ ๆ โดยไม่มีปัญหา


3
การใช้งานที่ง่ายที่สุดของพวกเขาทั้งหมด
Avi Cohen

22

สำหรับการผ่าน enum โดยเจตนาคุณสามารถแปลง enum เป็นจำนวนเต็ม

Ex:

public enum Num{A ,B}

กำลังส่ง (enum ถึงจำนวนเต็ม):

Num send = Num.A;
intent.putExtra("TEST", send.ordinal());

กำลังรับ (จำนวนเต็มถึง enum):

Num rev;
int temp = intent.getIntExtra("TEST", -1);
if(temp >= 0 && temp < Num.values().length)
    rev = Num.values()[temp];

ขอแสดงความนับถืออย่างสูง. :)


8
หรือคุณสามารถส่งเป็นสตริง (ดังนั้นจึงสามารถอ่านได้) ด้วย Num.A.name () จากนั้นรับมันกลับมาโดยใช้ Num.ValueOf (intent.getStringExtra ("TEST"))
Benoit Jadinon

1
ฉันคิดว่าวิธีของเบอนัวต์นั้นมีความปลอดภัยมากกว่าเนื่องจาก temp.ordinal () ไม่ได้เป็นที่ต้องการในทางปฏิบัติเนื่องจากค่าลำดับ () อาจเปลี่ยนแปลงได้ ดูโพสต์นี้: stackoverflow.com/questions/2836256/…
Shnkc

15

หากคุณต้องการจริงๆคุณสามารถทำให้อนุกรม enum เป็นสตริงโดยใช้name()และvalueOf(String)ดังนี้:

 class Example implements Parcelable { 
   public enum Foo { BAR, BAZ }

   public Foo fooValue;

   public void writeToParcel(Parcel dest, int flags) {
      parcel.writeString(fooValue == null ? null : fooValue.name());
   }

   public static final Creator<Example> CREATOR = new Creator<Example>() {
     public Example createFromParcel(Parcel source) {        
       Example e = new Example();
       String s = source.readString(); 
       if (s != null) e.fooValue = Foo.valueOf(s);
       return e;
     }
   }
 }

เห็นได้ชัดว่าใช้งานไม่ได้หาก enums ของคุณมีสถานะที่ไม่แน่นอน (ซึ่งไม่ควรจริง ๆ )


4

อาจเป็นไปได้ที่จะทำให้ Enum ของคุณใช้ Serializable จากนั้นคุณสามารถส่งผ่านทาง Intent ได้เนื่องจากมีวิธีการส่งผ่านเป็น Serializable คำแนะนำในการใช้ int แทน enum คือการหลอกลวง Enums ใช้เพื่อทำให้รหัสของคุณง่ายต่อการอ่านและบำรุงรักษาง่ายขึ้น มันเป็นการก้าวถอยหลังครั้งใหญ่สู่ยุคมืดเพื่อที่จะไม่สามารถใช้ Enums ได้


2
ชนิด Enum ใด ๆ ขยาย Enum superclass โดยค่าเริ่มต้นซึ่งใช้ Serializable แล้ว
Arcao

2

เกี่ยวกับโพสต์ของ Oderik:

คุณสามารถทำให้ enum ใช้ Parcelable ได้ซึ่งค่อนข้างง่ายสำหรับ enums:

Public enum MyEnum ใช้ Parcelable {... } คุณสามารถใช้ Intent.putExtra (String, Parcelable) ได้

หากคุณกำหนดตัวแปร MyEnum myEnum ให้ทำ intent.putExtra ("Parcelable1", myEnum) คุณจะได้รับข้อความแสดงข้อผิดพลาด "The เมธอด putExtra (String, Parcelable) ไม่ชัดเจนสำหรับประเภท Intent" เพราะยังมีวิธี Intent.putExtra (String, Parcelable) และตัวพิมพ์ 'Enum' ดั้งเดิมใช้อินเตอร์เฟส Serializable ดังนั้นคอมไพเลอร์จึงไม่ทราบว่าเลือกวิธีใด (intent.putExtra (String, Parcelable / หรือ Serializable)

แนะนำให้ลบส่วนต่อประสาน Parcelable ออกจาก MyEnum และย้ายรหัสหลักไปยังการใช้งาน Parcelable ในคลาสของคลาส wrap เช่นนี้ (Father2 เป็นแบบ Parcelable และมีฟิลด์ enum):

public class Father2 implements Parcelable {

AnotherEnum mAnotherEnum;
int mField;

public Father2(AnotherEnum myEnum, int field) {
    mAnotherEnum = myEnum;
    mField = field;
}

private Father2(Parcel in) {
    mField = in.readInt();
    mAnotherEnum = AnotherEnum.values()[in.readInt()];
}

public static final Parcelable.Creator<Father2> CREATOR = new Parcelable.Creator<Father2>() {

    public Father2 createFromParcel(Parcel in) {
        return new Father2(in);
    }

    @Override
    public Father2[] newArray(int size) {
        return new Father2[size];
    }

};

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(mField);
    dest.writeInt(mAnotherEnum.ordinal());
}

}

จากนั้นเราสามารถทำได้:

AnotherEnum anotherEnum = AnotherEnum.Z;
intent.putExtra("Serializable2", AnotherEnum.X);   
intent.putExtra("Parcelable2", new Father2(AnotherEnum.X, 7));

5
คุณสามารถเลือกลายเซ็นที่ถูกต้องได้อย่างชัดเจนโดยการ "โต้แย้ง" อาร์กิวเมนต์เช่นintent.putExtra("myEnum", (Parcelable) enumValue);
Oderik

การใช้ลำดับที่สมบูรณ์แบบ!
slott

bundle.putExtra("key", AnotherEnum.X.ordinal())นี้เป็นวิธีที่ซับซ้อนมากที่บอก
TWiStErRob

2

คุณสามารถใช้ตัวสร้าง enum เพื่อให้ enum มีชนิดข้อมูลดั้งเดิมได้

public enum DaysOfWeek {
    MONDAY(1),
    TUESDAY(2),
    WEDNESDAY(3),
    THURSDAY(4),
    FRIDAY(5),
    SATURDAY(6),
    SUNDAY(7);

    private int value;
    private DaysOfWeek(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    private static final SparseArray<DaysOfWeek> map = new SparseArray<DaysOfWeek>();

    static
    {
         for (DaysOfWeek daysOfWeek : DaysOfWeek.values())
              map.put(daysOfWeek.value, daysOfWeek);
    }

    public static DaysOfWeek from(int value) {
        return map.get(value);
    }
}

คุณสามารถใช้เพื่อส่ง int เป็นค่าพิเศษจากนั้นดึงค่าจาก enum โดยใช้ค่าของมัน


2

คำตอบส่วนใหญ่ที่ใช้แนวคิด Parcelable ที่นี่อยู่ในโค้ด Java มันง่ายกว่าที่จะทำใน Kotlin

เพียงแค่ใส่คำอธิบายประกอบคลาส enum ของคุณด้วย @Parcelizeและใช้อินเตอร์เฟส Parcelable

@Parcelize
enum class ViewTypes : Parcelable {
TITLE, PRICES, COLORS, SIZES
}

1

ฉันชอบเรียบง่าย

  • กิจกรรมเฟร็ดมีสองโหมด - และHAPPYSAD
  • สร้างสแตติกIntentFactoryที่สร้างขึ้นIntentเพื่อคุณ ผ่านมันไปตามที่Modeคุณต้องการ
  • การIntentFactoryใช้ชื่อของModeคลาสเป็นชื่อของพิเศษ
  • การIntentFactoryแปลงModeเป็นการStringใช้name()
  • เมื่อเข้าสู่การใช้ข้อมูลนี้เพื่อแปลงกลับไปเป็นonCreateMode
  • คุณสามารถใช้ordinal()และMode.values()เช่นกัน ฉันชอบสตริงเพราะฉันเห็นพวกเขาในตัวดีบั๊ก

    public class Fred extends Activity {
    
        public static enum Mode {
            HAPPY,
            SAD,
            ;
        }
    
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.betting);
            Intent intent = getIntent();
            Mode mode = Mode.valueOf(getIntent().getStringExtra(Mode.class.getName()));
            Toast.makeText(this, "mode="+mode.toString(), Toast.LENGTH_LONG).show();
        }
    
        public static Intent IntentFactory(Context context, Mode mode){
            Intent intent = new Intent();
            intent.setClass(context,Fred.class);
            intent.putExtra(Mode.class.getName(),mode.name());
    
            return intent;
        }
    }

อยากรู้อยากเห็น .. ใครโทร IntentFactory คุณสามารถอธิบายได้อย่างชัดเจนว่ากิจกรรมที่แตกต่างจะเรียก Fred อย่างไรและ Fred สามารถประกันได้อย่างไรว่าโหมดนั้นผ่านไปแล้ว
erik

0

ฉันคิดว่าทางออกที่ดีที่สุดของคุณคือการแปลงรายการเหล่านั้นเป็นสิ่งที่พัสดุเช่นสตริง (หรือแผนที่?) เพื่อไปที่กิจกรรม จากนั้นกิจกรรมจะต้องแปลงกลับเป็นอาร์เรย์

การนำพัสดุที่กำหนดเองไปใช้นั้นเป็นความเจ็บปวดที่คอ IMHO ดังนั้นฉันจะหลีกเลี่ยงได้ถ้าเป็นไปได้


0

พิจารณาติดตาม enum ::

public static  enum MyEnum {
    ValueA,
    ValueB
}

สำหรับการผ่าน ::

 Intent mainIntent = new Intent(this,MyActivity.class);
 mainIntent.putExtra("ENUM_CONST", MyEnum.ValueA);
 this.startActivity(mainIntent);

เมื่อต้องการเรียกคืนจากเจตนา / ชุดรวม / อาร์กิวเมนต์ ::

 MyEnum myEnum = (MyEnum) intent.getSerializableExtra("ENUM_CONST");

0

หากคุณเพียงแค่ต้องการส่ง Enum คุณสามารถทำสิ่งที่ชอบ:

ก่อนประกาศ enum ที่มีค่าบางอย่าง (ซึ่งสามารถส่งผ่านเจตนา):

 public enum MyEnum {
    ENUM_ZERO(0),
    ENUM_ONE(1),
    ENUM_TWO(2),
    ENUM_THREE(3);
    private int intValue;

    MyEnum(int intValue) {
        this.intValue = intValue;
    }

    public int getIntValue() {
        return intValue;
    }

    public static MyEnum getEnumByValue(int intValue) {
        switch (intValue) {
            case 0:
                return ENUM_ZERO;
            case 1:
                return ENUM_ONE;
            case 2:
                return ENUM_TWO;
            case 3:
                return ENUM_THREE;
            default:
                return null;
        }
    }
}

แล้ว:

  intent.putExtra("EnumValue", MyEnum.ENUM_THREE.getIntValue());

และเมื่อคุณต้องการที่จะได้รับมัน:

  NotificationController.MyEnum myEnum = NotificationController.MyEnum.getEnumByValue(intent.getIntExtra("EnumValue",-1);

เค้กชิ้น!


0

ใช้ฟังก์ชั่นเสริม Kotlin

inline fun <reified T : Enum<T>> Intent.putExtra(enumVal: T, key: String? = T::class.qualifiedName): Intent =
    putExtra(key, enumVal.ordinal)

inline fun <reified T: Enum<T>> Intent.getEnumExtra(key: String? = T::class.qualifiedName): T? =
    getIntExtra(key, -1)
        .takeUnless { it == -1 }
        ?.let { T::class.java.enumConstants[it] }

สิ่งนี้จะช่วยให้คุณมีความยืดหยุ่นในการส่งหลายชนิด enum เดียวกันหรือเป็นค่าเริ่มต้นในการใช้ชื่อคลาส

// Add to gradle
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

// Import the extension functions
import path.to.my.kotlin.script.putExtra
import path.to.my.kotlin.script.getEnumExtra

// To Send
intent.putExtra(MyEnumClass.VALUE)

// To Receive
val result = intent.getEnumExtra<MyEnumClass>()

-2

อย่าใช้ enums เหตุผลที่ # 78 ไม่ใช้ enums :) ใช้จำนวนเต็มซึ่งสามารถ remoting ผ่าน Bundle และ Parcelable ได้อย่างง่ายดาย


8
@hackbod - อีก 77 เหตุผลคืออะไร? ;) อย่างจริงจังแม้ว่า - ดูเหมือนจะมีประโยชน์มากมายในการแจงนับและพวกเขาก็ไม่ยากที่จะ 'ห่างไกล' อย่างแน่นอน - โอกาสใดที่คุณสามารถขยายเหตุผลของคุณกับพวกเขา?
ostergaard

3
@hackbod กรุณาทำอย่างละเอียด หากไม่ควรใช้ enums ให้ลบออกจาก API
dcow

2
Enums เป็นส่วนหนึ่งของสเปคภาษา Java ดังนั้นพวกเขากำลังยากเล็ก ๆ น้อย ๆ ที่จะลบและยังคงมีการดำเนินงานที่สอดคล้องกับ Java :)
ตาด

1
แล้วmEnum.ordinal()ไงล่ะ มันกลับมาตำแหน่งขององค์ประกอบ
Saif Hamed

3
ค่าของEnum.ordinal()ได้รับการแก้ไขในเวลารวบรวม เพียงครั้งเดียวที่ความคิดเห็นนั้นจะมีการส่งผ่านข้อมูลระหว่างแอพที่มี enum เวอร์ชันต่าง ๆ หรือระหว่างการอัปเดตแอปที่เปลี่ยนลำดับขององค์ประกอบภายใน enum สิ่งนั้นเป็นสิ่งที่อันตรายเมื่อใดก็ตามที่คุณใช้สิ่งใดก็ตามที่ไม่ใช่สิ่งดั้งเดิม สำหรับการส่งผ่านความตั้งใจระหว่างกิจกรรมภายในแอปเดียวEnum.ordinal()ควรปลอดภัยอย่างสิ้นเชิง
Ian McLaird
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.