【问题标题】:Kotlin parcelable class throwing ClassNotFoundExceptionKotlin 可打包类抛出 ClassNotFoundException
【发布时间】:2017-10-13 11:27:21
【问题描述】:

我有一个类用作 RecyclerView 的数据模型,以便通过 Intent 将此类的对象从一个活动传递到另一个活动,我必须将其设为 Parcelable

现在的问题是我能够将对象从一个活动发送到另一个活动并检索它,这样应用就不会崩溃,但会在 logcat 屏幕中不断抛出 ClassNotFoundException .

我做错了什么?

----> Person.kt

@Parcelize
class Person(var name: String, var username: String, var address: String, val avatar: Int) : Parcelable

---->在 MainActivity.kt

val intent = Intent(this, ProfilePage::class.java)
        intent.putExtra("clicked_person",person)
        startActivity(intent)

---->。 onCreate() 在 ProfilePAge.kt 中

var person  = intent.getParcelableExtra<Person>("clicked_person") as Person

还有Exception

E/Parcel: Class not found when unmarshalling: com.example.testkot.kotlinapp.Person
                                         java.lang.ClassNotFoundException: com.example.testkot.kotlinapp.Person

请记住,应用程序不会崩溃,它会继续工作,但会在 logcat 中显示异常

【问题讨论】:

  • 哪里抛出了异常?请显示整个堆栈跟踪?你是把这个Intent 和“附加”放在Notification 中还是发送到AlarmManager
  • 您是否尝试过将 person 对象放入 bundle 中,然后将这个 bundle 放入 Intent extra 中?
  • @KuLdipPaTel 如果您检查我的 Person.kt 代码,它与您在评论中提到的接受的答案相匹配
  • @MalwinderSingh 使用Bundle 或像我在MainActivity.kt 上那样传递参数有什么重大区别吗??

标签: android-intent kotlin parcelable


【解决方案1】:

在评论中测试解决方案后,以下工作不会引发任何异常

通过Bundle发送Parcelable

val intent = Intent(this, ProfilePage::class.java)
var bundle = Bundle()
bundle.putParcelable("selected_person",person)
intent.putExtra("myBundle",bundle)
startActivity(intent)

正在恢复Parcelable

val bundle = intent.getBundleExtra("myBundle")
var person  = bundle.getParcelable<Person>("selected_person") as Person

但是,我不知道我的旧代码在问题中的区别以及为什么旧代码会抛出异常以及为什么这个新代码不会抛出

【讨论】:

  • 不知道它为什么起作用,但您的解决方案使它起作用。谢谢。
  • 我认为……这行得通。由于某种原因,当您使用 Intent.putExtra(CustomParcellableClass) 时,它不会存储类加载器信息。无论如何,谢谢你的解决方案:D
  • 我不知道如何从 savedInstanceState 中恢复 Parcelable,但是添加行 as MyClass 就可以了。奇怪的是尖括号中的类型参数会生成一个警告,指出它是不必要的并且可以推断出来。如果我删除它,我会收到一个编译错误,说明推理失败。下定决心,科特林!
【解决方案2】:

为了方便您在没有任何警告的情况下使用 Kotlin Parcelables,我准备了以下扩展功能。

fun Intent.putParcel(key: String = "parcel_key", parcel: Parcelable) {
    val bundle = Bundle()
    bundle.putParcelable(key, parcel)
    this.putExtra("parcel_bundle", bundle)
}

fun <T : Parcelable> Intent.getParcel(key: String = "parcel_key"): T? {
    return this.getBundleExtra("parcel_bundle")?.getParcelable(key)
}

用法:

//Put parcel
intent.putParcel(parcel = Person()) //any Parcalable

//Get parcel
val person: Person?  = intent.getParcel() //auto converts using Generics

【讨论】:

    【解决方案3】:

    我想目前这是 Kotlin 和 Java 之间的兼容性问题。 我找到了一个简单的解决方案,它只允许使用 Kotlin 而无需样板。

    val intent = Intent(this, ProfilePage::class.java).apply {
        extras?.putParcellable("clicked_person",person)
    }
    
    startActivity(intent)
    

    然后检索您应该使用的值:

    var person = intent?.extras?.getParcellable<Person>("clicked_person")
    

    注意:您不需要转换为 Person

    【讨论】:

      【解决方案4】:
      var bundle = intent.extras
      var person = bundle.getParcelable<Person>("selected_person")
      

      上面的代码对我有用。您可以按如下方式缩短代码。

      var person = intent.extras.getParcelable<Person>("selected_person")
      

      【讨论】:

        【解决方案5】:

        在第一个 Activity 中:

         val intent = Intent(this@MainActivity, DetailsActivity::class.java)
                intent.putExtra(Const.SELECTED_NOTE, noteList[position])
                startActivity(intent)
        

        在第二个活动中:

        val note = intent.getParcelableExtra<Note>(Const.SELECTED_NOTE)
        

        解释:首先你应该在下一个活动中输入Parcelable 数据并调用getParcelableExtra! 在getParcelableExtra 你应该调用Data class(这里是Note)和Key Of Bundle(这里是Const.SELECTED_NOTE)!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-07-15
          • 1970-01-01
          • 1970-01-01
          • 2019-09-05
          • 1970-01-01
          • 2013-05-27
          • 2017-05-30
          相关资源
          最近更新 更多