如何在Android中使用Kotlin枚举修复'java.lang.InstantiationError'

时间:2019-06-24 17:51:00

标签: java android kotlin

我正在尝试从Android中的旧版Java活动开始一个新的kotlin活动,并且需要传递一个枚举(在kotlin中定义)作为额外的意图。从第一个(java)活动中,我可以看到额外的意图,但是从第二个(kotlin)活动中,应用程序崩溃,因为额外的意图已经消失了。有没有办法直接传递枚举,还是我必须还原为传递枚举的名称或序数?

请注意,如果枚举类不包含其自身的任何抽象函数(在这种情况下为getTitle()),则没有错误。但是,我需要保留这些功能。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                IntentExtension.putParcelableExtra(intent, "test", TestEnum.TWO);
                startActivityForResult(intent, 42);
            }
        });
    }
}

SecondActivity.kt

@Parcelize
enum class TestEnum : Parcelable {
    ONE {
        override fun getTitle(): String = "Title One!"
    },

    TWO {
        override fun getTitle(): String = "Title Two!"
    };

    abstract fun getTitle(): String
}

class SecondActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        val extra = intent.getParcelableExtra<TestEnum>("test") // crash here
        welcomeText.text = getString(R.string.message, extra.name)
    }
}

IntentExtension.kt

@file:JvmName("IntentExtension")

fun Intent.putParcelableExtra(key: String, value: Parcelable) {
    this.putExtra(key, value)
}

错误日志

    java.lang.InstantiationError: com.example.myapplication.TestEnum
        at com.example.myapplication.TestEnum$Creator.createFromParcel(Unknown Source:5)
        at android.os.Parcel.readParcelable(Parcel.java:2782)
        at android.os.Parcel.readValue(Parcel.java:2676)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:3043)
        at android.os.BaseBundle.unparcel(BaseBundle.java:257)
        at android.os.Bundle.getParcelable(Bundle.java:888)
        at android.content.Intent.getParcelableExtra(Intent.java:7075)
        at com.example.myapplication.SecondActivity.onCreate(SecondActivity.kt:27)
        at android.app.Activity.performCreate(Activity.java:6975)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

1 个答案:

答案 0 :(得分:2)

看来Kotlin注释处理器无法为枚举包裹生成正确的代码。这样编写自己的代码:

enum class TestEnum : Parcelable {
    ONE {
        override fun getTitle(): String = "Title One!"
    },

    TWO {
        override fun getTitle(): String = "Title Two!"
    };

    abstract fun getTitle(): String

    override fun describeContents(): Int {
        return 0
    }

    override fun writeToParcel(dest: Parcel?, flags: Int) {
        dest!!.writeInt(ordinal)
    }

    companion object CREATOR : Parcelable.Creator<TestEnum> {
        override fun createFromParcel(parcel: Parcel): TestEnum {
            return values()[parcel.readInt()]
        }

        override fun newArray(size: Int): Array<TestEnum?> {
            return newArray(size)
        }
    }
}