getIntent().getExtras()在Activity中有时会崩溃

5

我使用一些额外的参数启动一个Intent,然后在Activity的onCreate方法中读取传递过来的参数。

class MyActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val extras: Bundle? = intent.extras // <-- crash
        val someInt = extras?.getInt(EXTRA_SOME_INT, -1) ?: -1

        // ...
    }

    companion object {

        const val EXTRA_SOME_INT = "someInt"

        fun createIntent(context: Context, someInt: Int) =
            Intent(context, MyActivity::class.java).apply {
                putExtra(EXTRA_SOME_INT, someInt)
            }
    }
}

// Activity started like this:
fun startMyActivity(context: Context) {
    context.startActivity(MyActivity.createIntent(context, 1234))
}

这个代码在测试中运行良好,但是在生产环境中,当调用getExtras()时,标记行有时会导致应用程序崩溃。根据文档,它可以为null,但不应该抛出异常。

崩溃日志并不总是相同的,但是要么发生在BaseBundle中:

java.lang.NullPointerException
Attempt to invoke virtual method 'int android.os.Parcel.dataSize()' on a null object reference

BaseBundle.java line 164 in android.os.BaseBundle.<init>()
Bundle.java line 106 in android.os.Bundle.<init>()
Intent.java line 6580 in android.content.Intent.getExtras()

……否则会发生这种情况:

java.lang.IllegalArgumentException
Duplicate key in ArrayMap:

BaseBundle.java line 126 in android.os.BaseBundle.<init>()
Bundle.java line 102 in android.os.Bundle.<init>()
Intent.java line 5756 in android.content.Intent.getExtras()

崩溃仅发生在Android 5、6或7上。我没有找到在自己的设备上复现它的方法。

我做错了什么吗?或者有什么最好的方法可以避免这种崩溃?如果没有额外的bundle,我就无法显示我的Activity。


@blackapps getIntent() 不会导致崩溃,在 Activity 的 onCreate 中它永远不会为 null。getExtras() 的内部调用才会导致 NullPointerException。 - Day
好的。但是无论如何,您都可以捕获这些异常,以便您的应用程序不会崩溃。显示一个toast来通知用户。也许重新启动? - blackapps
你的活动启动意图做得如何了?好吗? - blackapps
"someInt"。这是一个字符串字面量,不是整数。 - blackapps
1
@Day 这是可能修复此问题的提交:https://cs.android.com/android/_/android/platform/frameworks/base/+/694753465b577509cecba33a90fb7cb6d50f5533 - Saurabh Thorat
显示剩余8条评论
2个回答

3

这是一个AOSP中的bug,在Android 7之后被修复。以下是提交信息中的原因:

修复 writeToParcel 和 unparcel 中的竞争问题

不要在另一个线程可能回收已封装数据时访问它。

还要创建 mMap 的本地引用,以防其被另一个线程修改。


谢谢您指出这一点。因此,如果发生错误,我将简单地用try/catch包装我的代码并完成活动。 如果我在最新的发布中获得更多关于这个崩溃更频繁的见解,我会发布它。 - Day

-1
    Bundle receiveData = getIntent().getExtras();

    if (receiveData != null){
        .....
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接