You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Moshi自动生成适配器时,含自身类型字段导致编译失败求助

解决Moshi自引用类适配器生成的编译问题

嘿,我之前也碰到过类似的情况——Moshi自动生成适配器时,带自引用字段的类居然和Dagger的注解处理器撞车了。虽然Moshi本身是支持自引用类型的(比如这种包含List<CommentModel>的结构),但注解处理器之间的交互或者缓存问题经常会搞出这种奇怪的编译错误,给你几个可以尝试的解决方向:

1. 先把依赖版本更到最新

旧版本的Moshi、Dagger或者KAPT可能存在自引用处理的bug,或者和其他处理器的兼容性问题。建议把Moshi更到1.14.0以上,Dagger更到2.40+,同时确保Kotlin和KAPT的版本匹配,这一步经常能解决很多奇怪的注解处理器问题。

2. 清缓存重启再编译

编译缓存有时候会让注解处理器“失忆”,无法正确解析生成的代码。你可以先执行./gradlew clean(Android项目),删掉build文件夹,然后重启IDE,再重新编译试试看——很多时候这种玄学问题清完缓存就好了。

3. 检查父类ListingItem的注解配置

你的CommentModel继承自ListingItem,如果ListingItem也加了@JsonClass(generateAdapter = true),可能会导致继承关系下的适配器生成出现依赖冲突。可以试试:

  • 如果ListingItem不需要自动生成适配器,直接去掉它的@JsonClass注解
  • 要是ListingItem必须用自动生成,就确认它的字段没有循环依赖,或者有没有其他注解干扰

4. 手动写适配器绕开自动生成

如果自动生成还是搞不定,那就手动写个适配器来处理自引用,虽然麻烦点但绝对靠谱:

class CommentModelAdapter(moshi: Moshi) {
    // 先创建List<CommentModel>的适配器
    private val repliesAdapter: JsonAdapter<List<CommentModel>> = 
        moshi.adapter(TypeToken.getParameterized(List::class.java, CommentModel::class.java))

    @FromJson
    fun fromJson(jsonMap: Map<String, Any?>): CommentModel {
        val comment = CommentModel().apply {
            id = jsonMap["id"] as? String
            body = jsonMap["body"] as? String ?: ""
            created = jsonMap["created"] as? String
            score = jsonMap["score"] as? Int ?: 0
            // 把其他字段也按这个方式处理
            replies = jsonMap["replies"]?.let { repliesAdapter.fromJsonValue(it) }
        }
        return comment
    }

    @ToJson
    fun toJson(comment: CommentModel): Map<String, Any?> {
        return mutableMapOf<String, Any?>().apply {
            put("id", comment.id)
            put("body", comment.body)
            put("created", comment.created)
            put("score", comment.score)
            // 处理其他字段
            comment.replies?.let { put("replies", repliesAdapter.toJsonValue(it)) }
        }
    }
}

然后修改CommentModel的注解,替换成手动适配器:

@JsonAdapter(CommentModelAdapter::class)
class CommentModel: ListingItem() {
    // 字段保持原样就行
}

5. 调整注解处理器的执行顺序

如果是Dagger和Moshi的处理器互相干扰,你可以在Gradle里指定KAPT的处理器顺序,让Moshi先跑完:

kapt {
    arguments {
        arg("moshi.generated", "true")
    }
    // 指定处理器顺序,Moshi在前,Dagger在后
    processors = ["com.squareup.moshi.kotlin.codegen.MoshiProcessor", "dagger.internal.codegen.ComponentProcessor"]
}

试试这些方法,应该能搞定你的编译错误。要是还不行,可以暂时禁用项目里其他的注解处理器(比如Room、DataBinding),排查是不是其他处理器在搞事情。

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

火山引擎 最新活动