Androidでの列挙型の操作


120

私は自分のアプリのAndroidで使用している計算アクティビティをほぼ完了しました。性別列挙型を作成しようとしましたが、何らかの理由で構文エラーが発生したため、「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;
    }
}

静的{}なしでも試してみましたが、同じ構文エラーが発生します。


列挙型はパフォーマンスの問題にはお勧めできません。代わりにプリミティブ定数を使用してください。youtube.com/watch?v=Hzs6OBcvNQE
Myke Dev

UPDATE 2019:ARTがランタイム環境としてのDALVIKを置き換えたため、列挙型はAndroidで使用しても問題ありませんstackoverflow.com/a/56296746/4213436。したがって、このスレッドに関するほとんどの回答は無関係であると思います。
JDenais

@JDenaisはもちろん、「参照した」スレッドを意味します
YoussefDir

回答:


343

一体どこでこの構文を見つけましたか?Java Enumは非常に単純で、値を指定するだけです。

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;
    }
}

次に、列挙型を使用するには、次のようにします。

Gender me = Gender.MALE

11
私はそれを試してみます。私は絶対的な初心者だったと言っていました
JMSDEV

86
申し訳ありませんが、私はそれを否定的に言ったわけではありません。私が今まで列挙型で見た中で最も奇妙な構文
Spidy

3
enumが順次であることを言及することも役立つので、enumで.ordinal()を使用してint値を取得できます。
Kalel Wade、2014

1
問題の構文は、逆コンパイラを使用することで思いつくかもしれない種類です。
Dan Getz

9
「一体どこでこの構文を見つけたのか」と私はとても笑いました。生徒に教師のように言う
Zar E Ahmer

50

この競合のポイントについてはいくつかの議論がありましたが、最新のドキュメントでさえ、androidは、androidアプリケーションで列挙型を使用することはそれほど良い考えではないと示唆しています。静的定数変数より多くのメモリを消費するためです。これは、Androidアプリケーションでの列挙型の使用を推奨しない2014年のページのドキュメントです。http://developer.android.com/training/articles/memory.html#Overhead

私は引用します:

メモリのオーバーヘッドに注意してください

使用している言語とライブラリのコストとオーバーヘッドについて理解し、アプリを最初から最後まで設計するときにこの情報に留意してください。多くの場合、無害に見える表面上のものは、実際には大量のオーバーヘッドを持っている可能性があります。例は次のとおりです。

  • 多くの場合、列挙型は静的定数の2倍以上のメモリを必要とします。Androidでの列挙型の使用は厳密に避けてください。

  • Javaのすべてのクラス(匿名の内部クラスを含む)は、約500バイトのコードを使用します。

  • すべてのクラスインスタンスには、12〜16バイトのRAMオーバーヘッドがあります。

  • 単一のエントリをHashMapに配置するには、32バイトを使用する追加のエントリオブジェクトを割り当てる必要があります(最適化されたデータコンテナーについては、前のセクションを参照してください)。

あちこちに数バイトが加算されます。クラスやオブジェクトが多いアプリデザインは、このオーバーヘッドの影響を受けます。これにより、ヒープ分析を見て、RAMを使い果たしている多くの小さなオブジェクトが問題であることに気づくという難しい状況に陥る可能性があります。

これらのヒントは古く、価値がないと彼らが言うところがいくつかありましたが、彼らがそれを繰り返し続ける理由は、それにいくつかの真実があるにちがいないに違いありません。Androidアプリケーションの記述は、スムーズなユーザーエクスペリエンスを実現するために、可能な限り軽量に保つ必要があります。そして、パフォーマンスのすべての小さな部分が重要です!


いくつかの場所がありました -あなたがそれらを知っているなら、いくつか追加できますか?何も見つからないため
Krzysztof Skrzynecki

9
ここで誰かが、列挙型の代わりにintを使用することに関する情報が公式ドキュメントのパフォーマンスのヒントから削除されていることに気づきました。さらに、redditについて
Krzysztof Skrzynecki

1
Androidパフォーマンスパターン:ENUMの価格(Google Devの100日間)
Afriza N. Arief 2015年

皆さん、私の質問は、Enumが「悪い」習慣である場合、なぜGoogleがAndroidでJavaのこの機能をまだサポートしているのですか?:(
ヘスス・カストロ

5
@JesúsCastroGoogleは、多数の既存のJavaビジネスロジック(列挙型を使用している可能性がある)を備えた企業がライブラリをAndroidプロジェクトにドロップして実行できることを保証したいためです。
David Brown

22

Chrisがコメントしたように、列挙型は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演算)が可能です。

編集:enumをintに変換することは、Proguardのデフォルトの最適化の1つであるようです


3
int定数をアノテーションクラスに直接配置するのが好きです。したがって、通常の列挙型のように見えます。ここで説明しました:blog.shamanland.com/2016/02/int-string-enum.html
Oleksii K.


9

このビデオによると、ProGuardを使用している場合は、Enumsのパフォーマンスの問題について考える必要すらありません。

Proguardは多くの状況でEnumをINT値に最適化できるため、実際にそれについて考えたり、作業したりする必要はありません。


4

Androidの推奨されるアプローチは、@ IntDefで強制されるint定数です。

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.