首页 > 解决方案 > 引起:java.lang.ClassNotFoundException:在路径:DexPathList 上找不到类“com.example.androidwebapi.network.Movies.Result”

问题描述

我在将数据从一个片段传递到另一个片段时遇到问题。我通过 Safe Args 插件发送数据对象,例如自定义 parcelable。有两个嵌套数据类,当我在 navigation.xml 中将 argType 设置为该数据类的路径时,使用点表示法 (Movies.Result),应用程序崩溃并从标题中显示此错误。它仅适用于 $ 符号 (Movies$Result),但问题在于片段中的其他数据。

数据期望 Movies.Result 但找到Movies$Result。无论错误如何,应用程序都能正常工作,但看到红色下划线很麻烦。如何摆脱这个问题?

MoviesModel.kt

@Parcelize
data class Movies ( val results : List<Result>) : Parcelable {
    @JsonClass(generateAdapter = true)
    @Parcelize
    data class Result(
        val id: Int,
        val title: String,
        val overview: String,
        @Json(name = "poster_path")
        val posterPath: String,
        @Json(name = "vote_average")
        val voteAverage: String
    ): Parcelable
}

导航.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/introFragment">
    <fragment
        android:id="@+id/introFragment"
        android:name="com.example.androidwebapi.screens.intro.IntroFragment"
        android:label="fragment_intro"
        tools:layout="@layout/fragment_intro">
        <action
            android:id="@+id/action_introFragment_to_dataGroupFragment"
            app:destination="@id/dataGroupFragment" />
    </fragment>
    <fragment
        android:id="@+id/dataGroupFragment"
        android:name="com.example.androidwebapi.screens.datagroup.DataGroupFragment"
        android:label="fragment_data_group"
        tools:layout="@layout/fragment_data_group">
        <action
            android:id="@+id/action_dataGroupFragment_to_moviesFragment"
            app:destination="@id/moviesFragment" />
    </fragment>
    <fragment
        android:id="@+id/aboutFragment"
        android:name="com.example.androidwebapi.screens.AboutFragment"
        android:label="AboutFragment"
        tools:layout="@layout/fragment_about" />
    <fragment
        android:id="@+id/moviesFragment"
        android:name="com.example.androidwebapi.screens.movies_overview.MoviesFragment"
        android:label="MoviesFragment"
        tools:layout="@layout/fragment_movies">
        <action
            android:id="@+id/action_showDetails"
            app:destination="@id/detailsFragment" />
    </fragment>
    <fragment
        android:id="@+id/detailsFragment"
        android:name="com.example.androidwebapi.screens.details.DetailsFragment"
        android:label="DetailsFragment"
        tools:layout="@layout/fragment_details">
        <argument
            android:name="selectedMovie"
            app:argType="com.example.androidwebapi.network.Movies$Result" />
    </fragment>

</navigation>

DetailsFragment.kt

package com.example.androidwebapi.screens.details

import android.content.Intent
import android.os.Bundle
import android.view.*
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.androidwebapi.R
import com.example.androidwebapi.databinding.FragmentDetailsBinding
import com.example.androidwebapi.network.Movies

class DetailsFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val application = requireNotNull(activity).application
        val binding = FragmentDetailsBinding.inflate(inflater)
        binding.lifecycleOwner = this

        val movie = DetailsFragmentArgs.fromBundle(requireArguments()).selectedMovie
        val viewModelFactory = DetailsViewModelFactory(movie, application)
        binding.viewModel = ViewModelProvider(
            this, viewModelFactory).get(DetailsViewModel::class.java)

        setHasOptionsMenu(true)

        return binding.root
    }

    // Creating our Share Intent
    private fun getShareIntent() : Intent {
        val args = DetailsFragmentArgs.fromBundle(requireArguments()).selectedMovie
        val shareIntent = Intent(Intent.ACTION_SEND)
        shareIntent.setType("text/*")
            .putExtra(Intent.EXTRA_TEXT, getString(R.string.share_movie_details_text, args))
        return shareIntent
    }

    private fun shareSuccess() {
        startActivity(getShareIntent())
    }

    // Showing the Share Menu Item Dynamically
    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)
        inflater.inflate(R.menu.summary_menu, menu)
        if(getShareIntent().resolveActivity(requireActivity().packageManager)==null){
            menu.findItem(R.id.share).isVisible = false
        }
    }

    // Sharing from the Menu
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId){
            R.id.share -> shareSuccess()
        }
        return super.onOptionsItemSelected(item)
    }

}

这些代码行会导致问题:

val movie = DetailsFragmentArgs.fromBundle(requireArguments()).selectedMovie,      
val viewModelFactory = DetailsViewModelFactory(movie, application)

其中参数电影期望 Movies.Result 但找到 Movies$Result

项目build.gradle

buildscript {
    ext {
        kotlin_version = "1.4.32"
        navigationVersion = "2.3.5"
        version_retrofit = "2.9.0"
        version_recyclerview = "1.0.0"
        version_lifecycle = "2.2.0"
        version_moshi = "1.8.0"
        version_glide = "4.8.0"
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.2.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"


        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

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

task clean(type: Delete) {
    delete rootProject.buildDir
}

模块:build.gradle

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-parcelize'
    id 'kotlin-kapt'
    id 'androidx.navigation.safeargs'
}


android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    android.defaultConfig.vectorDrawables.useSupportLibrary = true
    defaultConfig {
        applicationId "com.example.androidwebapi"
        minSdkVersion 19
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }

    buildFeatures {
        viewBinding true
        dataBinding true
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

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

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.5.0'
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
    implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
    implementation "com.google.android.material:material:$version"
    implementation 'com.jakewharton.timber:timber:4.7.1'

    implementation "com.squareup.moshi:moshi-kotlin:$version_moshi"

    implementation "com.squareup.retrofit2:retrofit:$version_retrofit"
    implementation "com.squareup.retrofit2:converter-moshi:$version_retrofit"

    implementation 'com.android.support:multidex:1.0.3'

    implementation "com.github.bumptech.glide:glide:$version_glide"

}

标签: androidkotlinandroid-intentviewmodelandroid-safe-args

解决方案


推荐阅读