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
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
Your new
MarsProperty
class does not implement theParcelable
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.Just implement
Parcelable
and add@Parcelize
annotation.Your data class must implement
Serializable
orParcelable
to pass arguments in Navigation Component.