You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含LineChart的MyCard数据类Kotlin序列化及Intent传递问题求助

解决MyCard序列化问题(含MPChart LineChart)

核心问题:LineChart是Android视图组件,本身无法被序列化——它持有Context、View树引用、绘制状态等不可序列化的对象,直接放进Serializable或Kotlin序列化会抛出异常。

下面是两种可行的解决方案:


方案1:拆分数据与视图(推荐)

不要把LineChart直接放在数据类里,抽离出LineChart的配置数据(可序列化),在目标页面拿到数据后重新初始化LineChart。

步骤1:定义可序列化的图表配置类

用@Parcelize实现Parcelable(Android推荐的跨页面传递方式,比Serializable更高效):

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class LineChartConfig(
    val entries: List<Pair<Float, Float>>, // 用Pair存储x/y值,替代不可序列化的Entry
    val chartLabel: String,
    val lineColor: Int,
    val textColor: Int
) : Parcelable

步骤2:修改MyCard数据类

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class MyCard(
    val imgResource: Int,
    val cardTitle: String,
    val cardDate: String,
    val cardDescription: String,
    val chartConfig: LineChartConfig
) : Parcelable

步骤3:跨页面传递与重建LineChart

  • 发送方传递对象:
intent.putExtra(intent__MYCARD_OBJ, myCard)
  • 接收方获取对象并重建LineChart:
val myCard = intent.getParcelableExtra<MyCard>(intent__MYCARD_OBJ) ?: return

// 把Pair转成MPChart的Entry
val entries = myCard.chartConfig.entries.map { com.github.mikephil.charting.data.Entry(it.first, it.second) }
val dataSet = com.github.mikephil.charting.data.LineDataSet(entries, myCard.chartConfig.chartLabel).apply {
    color = myCard.chartConfig.lineColor
    valueTextColor = myCard.chartConfig.textColor
}
val lineData = com.github.mikephil.charting.data.LineData(dataSet)

// 给页面中的LineChart设置数据
binding.lineChart.apply {
    data = lineData
    invalidate() // 刷新图表
}

方案2:自定义序列化忽略LineChart

如果一定要保留LineChart在MyCard中,通过自定义序列化忽略LineChart,反序列化后手动重建它。

步骤1:修改MyCard并标记LineChart为临时字段

import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import com.github.mikephil.charting.charts.LineChart

@Serializable(with = MyCardAsStringSerializer::class)
data class MyCard(
    val imgResource: Int,
    val cardTitle: String,
    val cardDate: String,
    val cardDescription: String,
    @Transient // 标记该字段不参与序列化
    val lineChart: LineChart? = null
)

步骤2:实现完整的自定义序列化器

import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.descriptors.element
import kotlinx.serialization.encoding.CompositeDecoder
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

object MyCardAsStringSerializer : KSerializer<MyCard> {
    override val descriptor = buildClassSerialDescriptor("MyCard") {
        element<Int>("imgResource")
        element<String>("cardTitle")
        element<String>("cardDate")
        element<String>("cardDescription")
    }

    override fun serialize(encoder: Encoder, value: MyCard) {
        encoder.encodeStructure(descriptor) {
            encodeIntElement(descriptor, 0, value.imgResource)
            encodeStringElement(descriptor, 1, value.cardTitle)
            encodeStringElement(descriptor, 2, value.cardDate)
            encodeStringElement(descriptor, 3, value.cardDescription)
        }
    }

    override fun deserialize(decoder: Decoder): MyCard {
        return decoder.decodeStructure(descriptor) {
            var imgRes = 0
            var title = ""
            var date = ""
            var desc = ""

            while (true) {
                when (val index = decodeElementIndex(descriptor)) {
                    0 -> imgRes = decodeIntElement(descriptor, 0)
                    1 -> title = decodeStringElement(descriptor, 1)
                    2 -> date = decodeStringElement(descriptor, 2)
                    3 -> desc = decodeStringElement(descriptor, 3)
                    CompositeDecoder.DECODE_DONE -> break
                    else -> error("未知序列化索引: $index")
                }
            }
            MyCard(imgRes, title, date, desc, null)
        }
    }
}

步骤3:通过JSON字符串传递

  • 发送方:
import kotlinx.serialization.json.Json

val myCardJson = Json.encodeToString(myCard)
intent.putExtra(intent__MYCARD_OBJ, myCardJson)
  • 接收方:
val myCardJson = intent.getStringExtra(intent__MYCARD_OBJ) ?: return
val myCard = Json.decodeFromString<MyCard>(myCardJson)

// 手动重建LineChart并设置数据(需要提前保存图表的配置数据)
// 这里需要你自己补充图表数据的恢复逻辑,比如从MyCard的其他字段或额外参数获取

内容的提问来源于stack exchange,提问作者Steak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:42:22