如何通过 kotlin 中的意图传递自定义对象

Posted

技术标签:

【中文标题】如何通过 kotlin 中的意图传递自定义对象【英文标题】:How to Pass custom object via intent in kotlin 【发布时间】:2018-05-15 13:09:13 【问题描述】:
fun launchNextScreen(context: Context, people: People): Intent 
    val intent = Intent(context, NextScreenActivity::class.java)
    intent.putExtra(EXTRA_PEOPLE, (Parcelable) people)
    //intent.putExtra(EXTRA_PEOPLE, people as Parcelable)
    //intent.putExtra(EXTRA_PEOPLE, people)
    // tried above all three ways
    return intent

我尝试使用上面的代码使用 kotlin 通过意图传递 People 类的实例,但出现错误。 我做错了什么?

【问题讨论】:

您遇到的具体错误是什么? 【参考方案1】:

首先,确保People 类实现了Serializable 接口:

class People : Serializable 
    // your stuff

People 类的内部字段也必须实现Serializable 接口,否则会出现运行时错误。

那么它应该可以工作了:

fun launchNextScreen(context: Context, people: People): Intent 
    val intent = Intent(context, NextScreenActivity::class.java)
    intent.putExtra(EXTRA_PEOPLE, people)
    return intent

要从 Intent 接收人员,您需要致电:

val people = intent.getSerializableExtra(EXTRA_PEOPLE) as? People

【讨论】:

其他activity中如何获取序列化类? @VikashParajuli 在本示例的上下文中,您需要调用 val people = getIntent().getExtras().getSerializableExtra(EXTRA_PEOPLE) as? People 速度较慢,您需要使用 Parcelable 以获得更好的性能 @a2en 这是每个人都在说的话,但没有人确切知道)在小物体上你不会看到任何区别。但是,有一种方法可以使 Serializable 比 Parcelable 更快,有关更多信息,请参阅此线程中的 Farhana 答案:***.com/questions/3323074/…【参考方案2】:

在对象中实现Serializable:

data class Object (
        var param1: Int? = null,
        var param2: String? = null
) : Serializable

class Object : Serializable 
        var param1: Int? = null,
        var param2: String? = null

然后,您可以使用 Intent 传递对象:

val object = Object()
...
val intent = Intent(this, Activity2::class.java)
intent.putExtra("extra_object", object as Serializable)
startActivity(intent)

最后,在 Activity2 中,您可以通过以下方式获得对象:

val object = intent.extras.get("extra_object") as Object

【讨论】:

【参考方案3】:

找到了更好的方法:

在你的毕业典礼中:

apply plugin: 'org.jetbrains.kotlin.android.extensions'

android 
    androidExtensions 
        experimental = true
    

在您的数据类中:

@Parcelize
data class Student(val id: String, val name: String, val grade: String) : Parcelable

在源活动中:

val intent = Intent(context, Destination::class.java)
        intent.putExtra("student_id", student)
        context.startActivity(intent)

在目的地活动中:

student = intent.getParcelableExtra("student_id")

【讨论】:

这可行,但您必须在 build.gradle 中设置:应用插件:'org.jetbrains.kotlin.android.extensions' android androidExtensions experimental = true 【参考方案4】:

从 Kotlin 开始,Parcelize 不再是实验性的1.3.60+

定义一个数据类,添加@Parcelize注解并扩展Parcelable

@Parcelize
data class People(val id: String, val name: String) : Parcelable

添加到意图:

val intent = Intent(context, MyTargetActivity::class.java)
intent.putExtra("people_data", student)
context.startActivity(intent)

MyTargetActivity:

val people: People = intent.getParcelableExtra("people_data")

如果您尚未启用扩展程序,请在应用程序的 build.gradle 中启用。这也启用了data binding 和other great advanced features

apply plugin: 'kotlin-android-extensions'

【讨论】:

解决方案更简洁。 kotlin-android-extensions 现已弃用,您应该为Parcelable implementation generator 使用kotlin-parcelize 插件。【参考方案5】:

我找到了一种使用 Parcelable 将对象从一个活动传递到另一个活动的更好方法,它比序列化更快 Android: Difference between Parcelable and Serializable?

首先,在 build.gradle(app) 中添加这几行代码

apply plugin: 'kotlin-android-extensions' in app.grable 

@Parcelize 
class Model(val title: String, val amount: Int) : Parcelable

Intent 传递--->

val intent = Intent(this, DetailActivity::class.java)
intent.putExtra(DetailActivity.EXTRA, model)
startActivity(intent)

从意图中获取 --->

val model: Model = intent.getParcelableExtra(EXTRA)

【讨论】:

好消息!!它不再是实验性的 这是每个人都在说的话,但没有人确切知道)在小物体上你不会看到任何区别。另外,很高兴有这个 Kotlin 糖,但是好的旧 java 呢?但是,有一种方法可以使 Serializable 比 Parcelable 更快,有关更多信息,请参阅此线程中的 Farhana 答案:***.com/questions/3323074/…【参考方案6】:

这篇文章可能对您打算做的事情有用:

Is there a convenient way to create Parcelable data classes in Android with Kotlin?

基本上,kotlin 提供了一些额外的功能:

@Parcelize
class User(val firstName: String, val lastName: String) : Parcelable

查看帖子了解更多信息。

【讨论】:

【参考方案7】:

在 kotlin 中启动活动并传递一些数据,您可以尝试如下操作:

startActivity(intentFor<NameOfActivity>(STRING to data))

玩得开心

【讨论】:

另外一个类如何接收数据?【参考方案8】:

你必须在里面添加类型 ...它对我有用

val people = intent.getParcelableExtraPeople>(EXTRA_PEOPLE) as People

在您的 PeopleDetailActivity 活动中,在 onCreate 中初始化 viewModel

viewModel = this@PeopleDetailActivity.viewModel.apply  postPeopleId(getPeopleFromIntent().id) 

并且还要初始化这个方法:

private fun getPeopleFromIntent() = intent.getParcelableExtra<People>(peopleId) as People

编写以下代码以传递意图附加内容:

companion object 
        private const val objectId = "people"
        fun startActivityModel(context: Context?, people: People) 
            if (context != null) 
                val intent = Intent(context, PeopleDetailActivity::class.java).apply 
                    putExtra(
                        objectId,
                        people
                    )
                
                context.startActivity(intent)
            
        
    

在您的 PeopleListViewHolder onClick 中调用上述方法

override fun onClick(v: View?) = PeopleDetailActivity.startActivityModel(context(), people)

【讨论】:

如果自定义对象是可解析的,这将起作用。如果您提供一些示例代码会很棒。 用一个例子编辑了答案@MarcelHofgesang【参考方案9】:

你的 People 类需要像这样实现 Parcelable:

class People(): Parcelable
// stuff



android studio 会显示一个错误。只需将光标移动到“人物”,然后按 alt+enter。它现在应该显示生成 Parcelable 实现的选项。

此生成的代码将包含类似

的内容
parcel.writeString(member1)
parcel.writeInt(member2)

还有别的地方

member1=parcel.readString()
member2=parcel.readInt()

确保所有成员都包含在这些方法中,并且在修改它时,确保读取和写入以完全相同的顺序发生。

【讨论】:

以上是关于如何通过 kotlin 中的意图传递自定义对象的主要内容,如果未能解决你的问题,请参考以下文章

当我使用 Serializable 出错时,如何使用意图传递自定义对象列表

通过意图在活动之间传递自定义对象时出错

通过 Intent 传递自定义对象列表

意图选择器屏幕中自定义项目的回调

如何在不捐赠意图或使用快捷方式的情况下利用 Siri 创建自定义对象?

自定义可序列化对象数组列表的意图错误