2

我正在开发一个 KotlinMultiplatform 应用程序,它将不同的库实现为 NavigationComponent、ktor 到网络调用和 slqDelight 来存储本地数据。

所以我在标签中得到的错误如下:

     Caused by: android.view.InflateException: Binary XML file line #9: Binary XML file line #9: Error inflating class androidx.fragment.app.FragmentContainerView
     Caused by: android.view.InflateException: Binary XML file line #9: Error inflating class androidx.fragment.app.FragmentContainerView
     Caused by: java.lang.RuntimeException: Exception inflating com.jshvarts.kmp.android:navigation/nav_graph line 23


Caused by: java.lang.IllegalArgumentException: com.jshvarts.kmp.model.UnsplashPhoto is not Serializable or Parcelable.

关于这条线是我想在屏幕之间传递的论点:

nav_graph.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/homeFragment">
    <fragment
        android:id="@+id/homeFragment"
        android:name="com.jshvarts.kmp.android.home.HomeFragment"
        android:label="HomeFragment"
        tools:layout="@layout/home_fragment">
        <action
            android:id="@+id/action_navigate_from_home_to_detail"
            app:destination="@+id/detailFragment">
        </action>
    </fragment>

    <fragment
        android:id="@+id/detailFragment"
        android:name="com.jshvarts.kmp.android.detail.DetailFragment"
        android:label="DetailFragment"
        tools:layout="@layout/fragment_detail">
    <argument
        android:name="photo"
        app:argType="com.jshvarts.kmp.model.UnsplashPhoto"
        />
    </fragment>
</navigation>

关于我的模型课:

UnsplashPhoto.kt

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class UnsplashPhoto(
  @SerialName("id") val id: String?,
  @SerialName("description") var description: String?,
  @SerialName("urls") val urls: UnsplashPhotoUrls,
  @SerialName("user") val user: UnsplashUser
)

@Serializable
data class UnsplashPhotoUrls(
  @SerialName("raw") val raw: String,
  @SerialName("full") val full: String,
  @SerialName("regular") val regular: String,
  @SerialName("small")  val small: String,
  @SerialName("thumb")  val thumb: String
)

private val defaultUsername = "username"

@Serializable
data class UnsplashUser(
  @SerialName("name") val name: String,
  @SerialName("username") val username: String = defaultUsername,
  @SerialName("attributionUrl") val attributionUrl:String = "https://unsplash.com/$defaultUsername?utm_source=ImageSearchApp&utm_medium=referral"
)

最后是我的共享、android 和 proyect 模块的 build.gradle.kts 文件:

build.gradle.kts(androidApp)

plugins {
  //kotlin(multiplatform)
  id("com.android.application")
  kotlin("android")
  kotlin("kapt")
  id("kotlinx-serialization")
  id("androidx.navigation.safeargs.kotlin")
}

android {
  compileSdkVersion(Versions.compileSdk)

  compileOptions{
    sourceCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
    targetCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
  }

  kotlinOptions{
    jvmTarget = JavaVersion.VERSION_1_8.toString()
  }

  kapt{
    generateStubs = true
    correctErrorTypes = true
  }

  buildFeatures{
    dataBinding = true
    viewBinding = true
  }

  defaultConfig {
    applicationId = "com.jshvarts.kmp.android"
    minSdkVersion(Versions.minSdk)
    targetSdkVersion(Versions.targetSdk)
    versionCode = 1
    versionName = "1.0"

    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }

  buildTypes {
    getByName("release") {
      isMinifyEnabled = false
      proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
    }
  }

  packagingOptions {
    exclude("META-INF/*.kotlin_module")
  }
}

dependencies {
  implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
  implementation(kotlin("stdlib-jdk8", Versions.kotlin))
  implementation(Coroutines.android)
  implementation(AndroidX.appCompat)
  implementation(AndroidX.constraintLayout)
  implementation(AndroidX.recyclerView)
  implementation(AndroidX.lifecycleExtensions)
  implementation(AndroidX.lifecycleViewModelKtx)
  implementation(material)
  implementation(AndroidX.swipeToRefreshLayout)
  implementation(timber)
  implementation(picasso)
  implementation(AndroidX.navigation)
  implementation(AndroidX.navigation_ui)
  implementation(Serialization.runtime)
  //Dependency for googlePay
  implementation("com.google.android.gms:play-services-wallet:16.0.1")
  kapt(databinding)
  implementation(glide){
    exclude( "com.android.support")
  }
  kapt(glide)
  implementation(project(":shared"))

}

build.gradle.kts(共享)

plugins {
  id("com.android.library")
  kotlin("multiplatform")
  id("kotlinx-serialization")
  id("org.jetbrains.kotlin.native.cocoapods")
  id("com.squareup.sqldelight")
}
// CocoaPods requires the podspec to have a version.
version = "1.0"

android {
  compileSdkVersion(Versions.compileSdk)
  buildToolsVersion(Versions.androidBuildTools)

  defaultConfig {
    minSdkVersion(Versions.minSdk)
    targetSdkVersion(Versions.targetSdk)
    versionCode = 1
    versionName = "1.0"
  }
}
version = "1.0"
dependencies {
  implementation("com.google.firebase:firebase-crashlytics-buildtools:2.8.1")
}

kotlin {
  targets {

    val sdkName: String? = System.getenv("SDK_NAME")

    val isiOSDevice = sdkName.orEmpty().startsWith("iphoneos")
    if (isiOSDevice) {
      iosArm64("iOS")
    } else {
      iosX64("iOS")
    }
    android()
  }

  cocoapods {
    // Configure fields required by CocoaPods.
    summary = "Description for a Kotlin/Native module"
    homepage = "Link to a Kotlin/Native module homepage"
  }

  sourceSets {
    all {
      languageSettings.apply {
        useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
      }
    }

    val commonMain by getting {
      dependencies {
        implementation(kotlin("stdlib-common"))
        implementation(Coroutines.Core.core)
        implementation(Ktor.Core.common)
        implementation(Ktor.Json.common)
        implementation(Ktor.Logging.common)
        implementation(Ktor.Serialization.common)
        implementation(SqlDelight.runtime)
        implementation(Serialization.runtime)
        //implementation("org.jetbrains.kotlin:kotlin-reflect:${Versions.kotlin}")
        //implementation("org.jetbrains.kotlin:kotlin-reflect:${Versions.kotlin}")
        //implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
      }
    }

    val commonTest by getting {
      dependencies {
        implementation(Ktor.Mock.jvm)
      }
    }

    val androidMain by getting {
      dependencies {
        implementation(kotlin("stdlib"))
        implementation(Coroutines.Core.core)
        implementation(Ktor.android)
        implementation(Ktor.Core.jvm)
        implementation(Ktor.Json.jvm)
        implementation(Ktor.Logging.jvm)
        implementation(Ktor.Logging.slf4j)
        implementation(Ktor.Mock.jvm)
        implementation(Ktor.Serialization.jvm)
        implementation(Serialization.runtime)
        implementation(SqlDelight.android)


      }
    }

    val androidTest by getting {
      dependencies {
        implementation(kotlin("test-junit"))
        implementation(Ktor.Mock.common)
      }
    }

    val iOSMain by getting {
      dependencies {
        implementation(Coroutines.Core.core)
        implementation(Ktor.ios)
        implementation(Ktor.Core.common)
        implementation(Ktor.Json.common)
        implementation(Ktor.Logging.common)
        implementation(Ktor.Serialization.jvm)
       // implementation(Serialization.runtimeNative)
        implementation(SqlDelight.runtime)
        implementation(Ktor.Mock.common)
      }
    }

    val iOSTest by getting {
      dependencies {
        implementation(Ktor.Mock.native)
      }
    }
  }
}


sqldelight {
  database("PetsDatabase") {
    packageName = "com.jshvarts.kmp.db"
    sourceFolders = listOf("sqldelight")
  }
}

build.gradle.kts(项目)


// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
      google()
      mavenCentral()
      jcenter()
    }

    dependencies {
        classpath("com.android.tools.build:gradle:4.0.0")
        classpath(kotlin("gradle-plugin", version = Versions.kotlin))
        classpath(kotlin("serialization", version = Versions.kotlin))
        classpath("com.squareup.sqldelight:gradle-plugin:${Versions.sqldelight}")
        classpath("com.github.ben-manes:gradle-versions-plugin:0.28.0")
        classpath ("androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.navigation}")


        //classpath ("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}")
        //classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}")
        //classpath("org.jetbrains.kotlin:kotlin-parcelize-runtime:${Versions.kotlin}")
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
        jcenter()
    }
}

//TODO("Probar bajando a kotlin version 1.3.72, y habilitando el android-extensions")
plugins {
  //kotlin("jvm") version "${Versions.kotlin}"
  id("org.jlleitschuh.gradle.ktlint") version "9.2.1"
  id ("com.github.ben-manes.versions") version "0.28.0"
  //kotlin("android") version "${Versions.kotlin}" apply false
  //id("org.jetbrains.kotlin.plugin.parcelize") version "${Versions.kotlin}"
}
apply(from = "quality/lint.gradle") 

所以我想我不能像这样创建一个可序列化的对象,或者我有一些库不兼容导致我的序列化对象不可读,但我该怎么办?

预先感谢 !

[编辑]

添加了 build.gradle.kts(androidApp)

plugins {
  //kotlin(multiplatform)
  id("com.android.application")
  kotlin("android")
  kotlin("kapt")
  id("kotlinx-serialization")
  id("androidx.navigation.safeargs.kotlin")
}

android {
  compileSdkVersion(Versions.compileSdk)

  compileOptions{
    sourceCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
    targetCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
  }

  kotlinOptions{
    jvmTarget = JavaVersion.VERSION_1_8.toString()
  }

  kapt{
    generateStubs = true
    correctErrorTypes = true
  }

  buildFeatures{
    dataBinding = true
    viewBinding = true
  }

  defaultConfig {
    applicationId = "com.jshvarts.kmp.android"
    minSdkVersion(Versions.minSdk)
    targetSdkVersion(Versions.targetSdk)
    versionCode = 1
    versionName = "1.0"

    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }

  buildTypes {
    getByName("release") {
      isMinifyEnabled = false
      proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
    }
  }

  packagingOptions {
    exclude("META-INF/*.kotlin_module")
  }
}

dependencies {
  implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
  implementation(kotlin("stdlib-jdk8", Versions.kotlin))
  implementation(Coroutines.android)
  implementation(AndroidX.appCompat)
  implementation(AndroidX.constraintLayout)
  implementation(AndroidX.recyclerView)
  implementation(AndroidX.lifecycleExtensions)
  implementation(AndroidX.lifecycleViewModelKtx)
  implementation(material)
  implementation(AndroidX.swipeToRefreshLayout)
  implementation(timber)
  implementation(picasso)
  implementation(AndroidX.navigation)
  implementation(AndroidX.navigation_ui)
  implementation(Serialization.runtime)
  //Dependency for googlePay
  implementation("com.google.android.gms:play-services-wallet:16.0.1")
  kapt(databinding)
  implementation(glide){
    exclude( "com.android.support")
  }
  kapt(glide)
  implementation(project(":shared"))

}

4

1 回答 1

1

我会说您正在混合依赖项,您正在使用 ,kotlinx.serialization.Serializable而您需要的是java.io.Serializable.

最后一个没有可用的注释,因此您可以继续执行此操作:

@Serializable
data class UnsplashPhoto(
  @SerialName("id") val id: String?,
  @SerialName("description") var description: String?,
  @SerialName("urls") val urls: UnsplashPhotoUrls,
  @SerialName("user") val user: UnsplashUser
): java.io.Serializable

这应该够了吧。(如果以后要使用,可以保留 json Serializable 注解)

于 2022-01-27T03:29:32.757 回答