5

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?

13
  • stackoverflow.com/questions/49323455/… Commented Oct 29, 2018 at 5:53
  • No, you can't be sure. error is that your realtorImageUrl you specified as non-null gets null for some reason. you might took it as lateinit var which is still not initialized when accessing. Commented Oct 29, 2018 at 5:53
  • @NileshRathod The link which you have provided is the different issue. When accessing java classes in kotlin all the variables are null so you need to use "?" when accessing any java variable. I don't know how parameter in model got null. Commented Oct 29, 2018 at 6:05
  • 1
    @EpicPandaForce I mean to say data is not null when it's displayed. I want to know the reason why it got null. Commented Oct 29, 2018 at 7:00
  • 1
    The problem is may be with Json parsing, Whenever JsonResponse does not have RealtorImageUrl, it will consider it as null Commented Nov 16, 2018 at 13:02

3 Answers 3

3
+100

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.

  • First of all, I highly recommend you to use google Gson.
  • Second, be sure that the json string is not null or empty after configuration changes.
  • Third, be sure that you are using 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
        )
    }
}
Sign up to request clarification or add additional context in comments.

11 Comments

@Rajesh: What is a library with @Json annotation? I have tested it using google Gson and no problem happened in restoring fragment state like phone rotation.
I am using Moshi library. Is there any difference when using Anko library?
I think the problem comes from moshi library. I have updated the answer.
Can you explain why there is problem with moshi library?
Ok, you have defined the realtorImageUrl not null and kotlin does not permit to set it null. The only possible way to do that is to set the null value by reflection. As annotation processor json libraries set values to the fields using reflection, so the problem definitely comes from them.
|
0

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

1 Comment

The problem is not nullity of property, realtorImageUrl makes the issue.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.