stevendesu
stevendesu

Reputation: 16831

Utilizing enum for custom view attributes in Android

Issue

I wish to add the following attribute to a custom view I'm building in Android:

        <attr name="sourceType" format="enum">
            <enum name="generic" value="???" />
            <enum name="dash" value="???" />
            <enum name="smooth_streaming" value="???" />
            <enum name="hls" value="???" />
        </attr>

Internally in my code I would like to use an enum to represent the various source types:

public enum SourceType {
    Generic, DASH, SmoothStreaming, HLS;
}

However in my custom view I'm not sure how to convert the attribute value to an enum:

    public BFPlayer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.BFPlayer);

        // Clearly wrong:
        //    1. SourceType.Generic cannot be cast to int
        //    2. int cannot be cast to SourceType
        SourceType sourceType = attributes.getInt(R.styleable.BFPlayer_sourceType, SourceType.Generic);
    }

What I've tried

I've considered doing something like the following:

attrs.xml

        <attr name="sourceType" format="enum">
            <enum name="generic" value="1" />
            <enum name="dash" value="2" />
            <enum name="smooth_streaming" value="3" />
            <enum name="hls" value="4" />
        </attr>

SourceType.java

public enum SourceType {
    Generic (1), DASH (2), SmoothStreaming (3), HLS (4);

    private int value;

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

    public int getValue() {
        return value;
    }

    public static SourceType fromInt(int value) {
        switch (value) {
            case 1: return Generic;
            case 2: return DASH;
            case 3: return SmoothStremaing;
            case 4: return HLS;
            default: throw new Error("Invalid SourceType");
        }
    }
}

BFPlayer.java

    public BFPlayer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.BFPlayer);

        // Clearly wrong:
        //    1. SourceType.Generic cannot be cast to int
        //    2. int cannot be cast to SourceType
        SourceType sourceType = SourceType.fromInt(
            attributes.getInt(R.styleable.BFPlayer_sourceType, SourceType.Generic.getValue())
        );
    }

However this feels like the wrong solution:

Is there a better solution?

Upvotes: 0

Views: 570

Answers (2)

jseashell
jseashell

Reputation: 755

To fix your issue that "It requires updating the switch statement if I add new values", you can use the following

public enum SourceType {
    // ...

    private static final List<SourceType> SOURCE_TYPES_ = Arrays.asList(SourceType.values());

    public static Optional<SourceType> find(int value) {
        return SOURCE_TYPES_ 
                        .stream()
                        .filter(type -> value == type.getValue())
                        .findFirst();
    }
}

Upvotes: 1

Snail Cadet
Snail Cadet

Reputation: 311

Enums have a method values() that returns an array of that enum's type, with each enum value present in the array. You can define a static array of that enum type as a member of the enum.:

public enum SourceType {
    Generic, DASH, SmoothStreaming, HLS;

    static final SourceType values[] = SourceType.values();
}

You can then instantiate enum objects like this:

SourceType s = SourceType.values[someInt];

You could of course do this by simply indexing into the array returned by SourceType.values(), but that's less efficient because it creates an array for every call. I believe this solves all three of your problems: You don't have to use any additional methods to instantiate a SourceType; You don't need to manually update the array when adding new values; and you aren't arbitrarily assigning integer values to the enum options.

Upvotes: 1

Related Questions