Reputation: 12861
I am passing data to some fragment in bundle and while receiving it throws the exception. This error occurs while restoring Fragment's state.
Error occurs in Intrinsics.checkParameterIsNotNull when createFromParcel is called. This happen with all non-nullable fields in 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 plugin provides Parcelable implementation generator using @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)
}
}
...
}
What do I need to do to fix the issue?
Upvotes: 5
Views: 5696
Reputation: 666
Can u try using @field:Json(name = "RealtorImageUrl") and check if it works then?
Also, check if you have added proper factory KotlinJsonAdapterFactory()
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
Upvotes: 0
Reputation: 22832
Since the realtorImageUrl
is defined not null, so kotlin does not permit to set it to null. Therefore the only possible way to do that is to set the null value by reflection. Json helper libraries are based on annotation processing and using reflection for setting value to the fields, so the problem definitely comes from them.
Gson
.moshi-kotlin
(not simple moshi
) in dependencies and adding an instance of KotlinJsonAdapterFactory
to the moshi
builder.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()
It is better to use withArguments
from anko to put arguments for the 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
)
}
}
Upvotes: 3
Reputation: 6373
Well, this might not be the perfect solution but it can solve your issue. You can make your property nullable and just add a null check whenever you access them.
Just initialize you variable like this
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)
)
}
And in PropertyDetailsFragment.kt
class PropertyDetailsFragment{
...
companion object {
fun newInstance(property: Property?) = PropertyDetailsFragment().withArgs {
property?.let{
putParcelable(INT_EXTRA_PROPERTY, property)
}
}
}
...
}
Upvotes: 0