0

问题

我希望将以下属性添加到我在 Android 中构建的自定义视图中:

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

在我的代码内部,我想使用枚举来表示各种源类型:

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

但是在我的自定义视图中,我不确定如何将属性值转换为枚举:

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

我试过的

我考虑过执行以下操作:

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

然而,这感觉像是错误的解决方案:

  • 它需要使用.fromtInt .getValue实例化一个新的 SourceType
  • 如果我添加新值,它需要更新 switch 语句
  • 它为每个选项任意分配整数值

有更好的解决方案吗?

4

2 回答 2

1

要解决“如果我添加新值需要更新 switch 语句”的问题,您可以使用以下命令

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();
    }
}
于 2019-05-10T19:47:19.953 回答
1

枚举有一个方法,该方法values()返回该枚举类型的数组,每个枚举值都存在于数组中。您可以将该枚举类型的静态数组定义为枚举的成员。:

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

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

然后,您可以像这样实例化枚举对象:

SourceType s = SourceType.values[someInt];

您当然可以通过简单地对 SourceType.values() 返回的数组进行索引来做到这一点,但这效率较低,因为它会为每次调用创建一个数组。我相信这可以解决您的所有三个问题:您不必使用任何其他方法来实例化 SourceType;添加新值时不需要手动更新数组;并且您不会随意将整数值分配给枚举选项。

于 2019-05-10T19:26:00.043 回答