skip to Main Content

My app is working fine when using the data class that i’m currently using from an online exercise:
https://android-kotlin-fun-mars-server.appspot.com/.
But when I try to change it to my own data class and json file (https://opendata.visitflanders.org/tourist/activities/breweries.json) i get this error:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.android.marsrealestate, PID: 26103
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.marsrealestate/com.example.android.marsrealestate.MainActivity}: android.view.InflateException: Binary XML file line #19 in com.example.android.marsrealestate:layout/activity_main: Binary XML file line #19 in com.example.android.marsrealestate:layout/activity_main: Error inflating class fragment
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4166)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4312)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2571)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:226)
        at android.os.Looper.loop(Looper.java:313)
        at android.app.ActivityThread.main(ActivityThread.java:8741)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
     Caused by: android.view.InflateException: Binary XML file line #19 in com.example.android.marsrealestate:layout/activity_main: Binary XML file line #19 in com.example.android.marsrealestate:layout/activity_main: Error inflating class fragment
     Caused by: android.view.InflateException: Binary XML file line #19 in com.example.android.marsrealestate:layout/activity_main: Error inflating class fragment
     Caused by: java.lang.RuntimeException: Exception inflating com.example.android.marsrealestate:navigation/nav_graph line 41

etc.
This is the data class that works fine:

@Parcelize
data class MarsProperty (
        val id: String,
        // used to map img_src from the JSON to imgSrcUrl in our class
        @Json(name = "img_src") val imgSrcUrl: String,
        val type: String,
        val price: Double) : Parcelable {
    val isRental
        get() = type == "rent"
}

This is the one i’m trying to use:

data class MarsProperty (
    val Name: String,
    val imagesURL: String,
    val street: String,
    val city_name: String,
    val phone: String
    )

My OverviewFragment

class OverviewFragment : Fragment() {

    private val viewModel: OverviewViewModel by lazy {
        ViewModelProvider(this).get(OverviewViewModel::class.java)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val binding = FragmentOverviewBinding.inflate(inflater)

        binding.lifecycleOwner = this

        binding.viewModel = viewModel

        binding.photosGrid.adapter = PhotoGridAdapter(PhotoGridAdapter.OnClickListener {
            viewModel.displayPropertyDetails(it)
        })

        viewModel.navigateToSelectedProperty.observe(this, Observer {
            if ( null != it ) {
                // Must find the NavController from the Fragment
                this.findNavController().navigate(OverviewFragmentDirections.actionShowDetail(it))
                // Tell the ViewModel we've made the navigate call to prevent multiple navigation
                viewModel.displayPropertyDetailsComplete()
            }
        })

        return binding.root
    }
}

My OverviewViewModel

class OverviewViewModel : ViewModel() {

    private val _properties = MutableLiveData<List<MarsProperty>>()

    val properties: LiveData<List<MarsProperty>>
        get() = _properties

    private val _navigateToSelectedProperty = MutableLiveData<MarsProperty>()
    val navigateToSelectedProperty: LiveData<MarsProperty>
        get() = _navigateToSelectedProperty

    init {
        getMarsRealEstateProperties()
    }

    private fun getMarsRealEstateProperties() {
        viewModelScope.launch {
            try {
                _properties.value = MarsApi.retrofitService.getProperties()
            } catch (e: Exception) {
                _properties.value = ArrayList()
            }
        }
    }

    fun displayPropertyDetails(marsProperty: MarsProperty) {
        _navigateToSelectedProperty.value = marsProperty
    }

    fun displayPropertyDetailsComplete() {
        _navigateToSelectedProperty.value = null
    }
}

activity_main.xml

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_host_fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:navGraph="@navigation/nav_graph" />

My nav_graph

<?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/overviewFragment">

    <fragment
        android:id="@+id/overviewFragment"
        android:name="com.example.android.marsrealestate.overview.OverviewFragment"
        android:label="fragment_overview"
        tools:layout="@layout/fragment_overview" >
        <action
            android:id="@+id/action_showDetail"
            app:destination="@id/detailFragment" />
    </fragment>

    <fragment
        android:id="@+id/detailFragment"
        android:name="com.example.android.marsrealestate.detail.DetailFragment"
        android:label="fragment_detail"
        tools:layout="@layout/fragment_detail">
        <argument
            android:name="selectedProperty"
            app:argType="com.example.android.marsrealestate.network.MarsProperty"
            />
    </fragment>

</navigation>

My fragment_overview.xml

<layout 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">

    <data>
        <variable
            name="viewModel"
            type="com.example.android.marsrealestate.overview.OverviewViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.android.marsrealestate.MainActivity">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/photos_grid"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:padding="6dp"
            android:clipToPadding="false"
            app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:listData="@{viewModel.properties}"
            app:spanCount="1"
            tools:itemCount="16"
            tools:listitem="@layout/grid_view_item" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

If you need any more files let me know.

3

Answers


  1. You are using a part of the data that you are using but making a data class of only the require parts is not a good idea.
    Create a data class for the whole response and it should work.
    There is a plugin for converting the response to a data class.

    Go to Settings -> Plugins -> Marketplace -> JSON To Kotlin Class
    Plugin for converting the data class

    Login or Signup to reply.
  2. Your new MarsProperty class does not implement the Parcelable interface and does not have the @Parcelize annotation. I guess it can be an issue as the Navigation Component does not support passing such classes as destination arguments – they have to meet some requirements.

    Login or Signup to reply.
  3. Just implement Parcelable and add @Parcelize annotation.

    @Parcelize
    data class MarsProperty: Parcelable (
        val Name: String,
        val imagesURL: String,
        val street: String,
        val city_name: String,
        val phone: String
    )
    

    Your data class must implement Serializable or Parcelable to pass arguments in Navigation Component.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search