Kotlin - IllegalArgumentException: параметр, указанный как ненулевой, является нулем - PullRequest
0 голосов
/ 29 октября 2018

Я передаю данные некоторому фрагменту в связке и при получении выдает исключение Эта ошибка возникает при восстановлении состояния фрагмента.

Ошибка возникает в Intrinsics.checkParameterIsNotNull при вызове createFromParcel . Это происходит со всеми необнуляемыми полями в 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, плагин Android Extensions предоставляет генератор реализации Parcelable с использованием @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)
        }
    }
    ...
}

Что мне нужно сделать, чтобы исправить проблему?

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

Ну, это может быть не идеальное решение, но оно может решить вашу проблему. Вы можете сделать свою собственность обнуляемой и просто добавлять нулевую проверку, когда вы получаете к ним доступ.

Просто инициализируйте переменную следующим образом

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)
    )
}

А в PropertyDetailsFragment.kt

class PropertyDetailsFragment{
    ...
    companion object {
        fun newInstance(property: Property?) = PropertyDetailsFragment().withArgs {
            property?.let{
                putParcelable(INT_EXTRA_PROPERTY, property)
            }
        }
    }
    ...
}
0 голосов
/ 16 ноября 2018

Можете ли вы попробовать использовать @field: Json (name = "RealtorImageUrl") и проверить, работает ли он тогда?

Также проверьте, правильно ли вы добавили фабрику KotlinJsonAdapterFactory ()

 val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()
0 голосов
/ 12 ноября 2018

Так как realtorImageUrl определен не нуль, поэтому kotlin не позволяет установить его в ноль. Поэтому единственный возможный способ сделать это - установить нулевое значение с помощью отражения. Вспомогательные библиотеки Json основаны на обработке аннотаций и использовании отражения для установки значений для полей, поэтому проблема определенно исходит от них.

  • Прежде всего, я настоятельно рекомендую вам использовать Google Gson.
  • Во-вторых, убедитесь, что строка json не является пустой или пустой после изменений конфигурации.
  • В-третьих, убедитесь, что вы используете moshi-kotlin (не просто moshi) в зависимостях и добавляете экземпляр KotlinJsonAdapterFactory в moshi компоновщик.

build.gradle:

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

Тест:

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()

Лучше использовать withArguments из anko , чтобы поставить аргументы для фрагмента:

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
        )
    }
}
...