web-dev-qa-db-fra.com

Kotlin - IllegalArgumentException: le paramètre spécifié comme étant non null est null

Je transmets des données à un fragment de la liasse et, lors de la réception, lève l'exception. Cette erreur se produit lors de la restauration de l'état de Fragment.

Une erreur se produit dans Intrinsics.checkParameterIsNotNull lorsque createFromParcel est appelé. Cela se produit avec tous les champs non nullables dans Model.

Caused by Java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.b.h.b, parameter realtorImageUrl
   at com.Android.app.ui.common.model.Property.(Unknown Source:16)
   at com.Android.app.ui.common.model.Property$Creator.createFromParcel(Unknown Source:637)
   at Android.os.Parcel.readParcelable(Parcel.Java:2797)
   at Android.os.Parcel.readValue(Parcel.Java:2691)
   at Android.os.Parcel.readArrayMapInternal(Parcel.Java:3058)
   at Android.os.BaseBundle.unparcel(BaseBundle.Java:257)
   at Android.os.BaseBundle.getInt(BaseBundle.Java:961)
   at me.yokeyword.fragmentation.SupportFragmentDelegate.onCreate(SourceFile:93)
   at me.yokeyword.fragmentation.SupportFragment.onCreate(SourceFile:48)
   at Android.support.v4.app.Fragment.performCreate(SourceFile:2331)
   at Android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1386)
   at Android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(SourceFile:1759)
   at Android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1827)
   at Android.support.v4.app.FragmentManagerImpl.dispatchStateChange(SourceFile:3244)
   at Android.support.v4.app.FragmentManagerImpl.dispatchCreate(SourceFile:3194)
   at Android.support.v4.app.Fragment.restoreChildFragmentState(SourceFile:1444)
   at Android.support.v4.app.Fragment.onCreate(SourceFile:1415)
   at me.yokeyword.fragmentation.SupportFragment.onCreate(SourceFile:47)
   at Android.support.v4.app.Fragment.performCreate(SourceFile:2331)
   at Android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1386)
   at Android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(SourceFile:1759)
   at Android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1827)
   at Android.support.v4.app.FragmentManagerImpl.dispatchStateChange(SourceFile:3244)
   at Android.support.v4.app.FragmentManagerImpl.dispatchCreate(SourceFile:3194)
   at Android.support.v4.app.FragmentController.dispatchCreate(SourceFile:184)
   at Android.support.v4.app.FragmentActivity.onCreate(SourceFile:355)
   at Android.support.v7.app.AppCompatActivity.onCreate(SourceFile:84)
   at me.yokeyword.fragmentation.SupportActivity.onCreate(SourceFile:38)
   at com.Android.app.ui.home.HomeActivity.onCreate(SourceFile:47)
   at Android.app.Activity.performCreate(Activity.Java:7174)
   at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.Java:1220)
   at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2908)
   at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:3030)
   at Android.app.ActivityThread.-wrap11(Unknown Source)
   at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1696)
   at Android.os.Handler.dispatchMessage(Handler.Java:105)
   at Android.os.Looper.loop(Looper.Java:164)
   at Android.app.ActivityThread.main(ActivityThread.Java:6938)
   at Java.lang.reflect.Method.invoke(Method.Java)
   at com.Android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.Java:327)
   at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:1374)

Property.kt

@Parcelize
data class Property(
    ...
    @Json(name = "RealtorImageUrl")
    val realtorImageUrl: String
    ...
) : Parcelable

Kotlin 1.1.4, le plug-in Android Extensions fournit un générateur d'implémentation Parcelable utilisant @Parcelize. 

PropertyListFragment.kt

override fun showPropertyDetails(property: Property) {
    (parentFragment as PropertySearchResultFragment).start(
        PropertyDetailsFragment.newInstance(property)
    )
}

PropertyDetailsFragment.kt

class PropertyDetailsFragment{
    ...
    companion object {
        fun newInstance(property: Property) = PropertyDetailsFragment().withArgs {
            putParcelable(INT_EXTRA_PROPERTY, property)
        }
    }
    ...
}

Que dois-je faire pour résoudre le problème?

4
Rajesh

Puisque la variable realtorImageUrl est définie, et non null, kotlin ne permet pas de la définir comme nulle. Par conséquent, le seul moyen de le faire est de définir la valeur null par réflexion. Les bibliothèques d'assistance Json sont basées sur le traitement des annotations et sur l'utilisation de la réflexion pour définir les valeurs des champs. Le problème vient donc d'eux.

  • Tout d’abord, je vous recommande vivement d’utiliser Google Gson.
  • Deuxièmement, assurez-vous que la chaîne JSON n'est pas nulle ou vide après les modifications de configuration. 
  • Troisièmement, assurez-vous que vous utilisez moshi-kotlin (pas simple moshi) dans les dépendances et ajoutez une instance de KotlinJsonAdapterFactory au générateur moshi.

build.gradle:

implementation 'com.squareup.moshi:moshi-kotlin:1.8.0'

Test:

val json = "{\"RealtorImageUrl\": \"http://www.gstatic.com/tv/thumb/persons/667736/667736_v9_ba.jpg\"}"

val moshi = Moshi.Builder()
        .add(KotlinJsonAdapterFactory()) // com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
        .build()

val jsonAdapter = moshi.adapter(Property::class.Java) as JsonAdapter<Property>
val property = jsonAdapter.fromJson(json) as Property

supportFragmentManager.beginTransaction()
        .replace(R.id.container, PropertyDetailsFragment.newInstance(property))
        .commit()

Il vaut mieux utiliser withArguments de anko pour mettre les arguments du fragment:

PropertyDetailsFragment.kt:

class PropertyDetailsFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val property = arguments?.getParcelable(KEY_EXTRA_PROPERTY) as Property
        val realtorImageUrl = property.realtorImageUrl
    }

    companion object {
        private const val KEY_EXTRA_PROPERTY = "KEY_EXTRA_PROPERTY"

        fun newInstance(property: Property) = PropertyDetailsFragment().withArguments(
                KEY_EXTRA_PROPERTY to property
        )
    }
}
4
aminography

Eh bien, ce n'est peut-être pas la solution parfaite, mais cela peut résoudre votre problème. Vous pouvez rendre votre propriété nullable et ajouter simplement un contrôle nul chaque fois que vous y accédez.

Vous n'avez qu'à initialiser une variable comme celle-ci

Property.kt

@Parcelize
data class Property(
    ...
    @Json(name = "RealtorImageUrl")
    val realtorImageUrl: String
    ...
) : Parcelable

PropertyListFragment.kt

override fun showPropertyDetails(property: Property?) {
    (parentFragment as PropertySearchResultFragment).start(
        PropertyDetailsFragment.newInstance(property)
    )
}

Et dans PropertyDetailsFragment.kt

class PropertyDetailsFragment{
    ...
    companion object {
        fun newInstance(property: Property?) = PropertyDetailsFragment().withArgs {
            property?.let{
                putParcelable(INT_EXTRA_PROPERTY, property)
            }
        }
    }
    ...
}
0
Birju Vachhani

Pouvez-vous essayer d'utiliser @field: Json (name = "RealtorImageUrl") et vérifier si cela fonctionne alors?

Vérifiez également si vous avez ajouté la fabrique appropriée KotlinJsonAdapterFactory ()

 val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()
0
Matej Vukosav