Issue
In my android application I created map fragment with MapsFragment class
class MapsFragment : Fragment() {
val callback = OnMapReadyCallback { googleMap ->
val sydney = LatLng(-34.0, 151.0)
googleMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
}
private val viewModel: MapViewModel by lazy {
ViewModelProvider(this).get(MapViewModel::class.java)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding = FragmentMapsBinding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
mapFragment?.getMapAsync(callback)
}
}
and fragment_maps.xml layout file
<?xml version="1.0" encoding="utf-8"?>
<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.mobile.viewmodels.MapViewModel" />
</data>
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MapsFragment" />
</layout>
I use
buildFeatures {
dataBinding true
}
option for creating binding. Then when I try bind my MapViewModel in line
val binding = FragmentMapsBinding.inflate(inflater)
I get an error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mobile, PID: 331
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
at androidx.databinding.ViewDataBinding.mapBindings(ViewDataBinding.java:1201)
at androidx.databinding.ViewDataBinding.mapBindings(ViewDataBinding.java:719)
at com.mobile.databinding.FragmentMapsBindingImpl.<init>(FragmentMapsBindingImpl.java:25)
at com.mobile.DataBinderMapperImpl.getDataBinder(DataBinderMapperImpl.java:58)
at androidx.databinding.MergedDataBinderMapper.getDataBinder(MergedDataBinderMapper.java:74)
at androidx.databinding.DataBindingUtil.bind(DataBindingUtil.java:199)
at androidx.databinding.DataBindingUtil.inflate(DataBindingUtil.java:130)
at androidx.databinding.ViewDataBinding.inflateInternal(ViewDataBinding.java:1368)
at com.mobile.databinding.FragmentMapsBinding.inflate(FragmentMapsBinding.java:68)
at com.mobile.databinding.FragmentMapsBinding.inflate(FragmentMapsBinding.java:54)
at com.mobile.ui.MapsFragment.onCreateView(MapsFragment.kt:45)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2600)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881)
at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManagerImpl.java:2100)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1874)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1830)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I/Process: Sending signal. PID: 331 SIG: 9
How to bind viewModel class properly? Is it possible?
Solution
Sorry, I might be late to answer this question but as they say, "Better Late than never."
So for the past two days, I have been trying to do the same thing, i.e., using DataBinding and Maps Fragment together.
I tried using both the methods, i.e., DataBindingUtil and as you did FragmentMapsBinding.
So, there were many errors I can across while trying to implement Data Binding, for starters, there was no DataBinding class generated, which is usually not a problem, except in this case. So, the workaround was to force the compiler to generate DataBinding class by introducing a variable, in your case viewModel in the XML file.
Now the data binding class is finally generated but we get this funny error, saying
Index Out of Bound
Now looking at the last error line which was generated
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
at androidx.databinding.ViewDataBinding.mapBindings(ViewDataBinding.java:1201)
and inspecting the code further inside the file ViewDataBinding.java, we see this.
if (isRoot && tag != null && tag.startsWith("layout")) {
final int underscoreIndex = tag.lastIndexOf('_');
if (underscoreIndex > 0 && isNumeric(tag, underscoreIndex + 1)) {
final int index = parseTagInt(tag, underscoreIndex + 1);
//ERROR IS GENERATED HERE
if (bindings[index] == null) {
bindings[index] = view;
}
indexInIncludes = includes == null ? -1 : index;
isBound = true;
} else {
indexInIncludes = -1;
}
}
Not what I think the problem was is that the bindings file which we had told the complier to forcefully generate doesn't really have any Views in it and the bindings index.
Data Binding Class -
- No. of Views = 0
- Index = 0
Now trying to access it gives an error.
BUT WAIT A MINUTE, one might say there is a view present, i.e., fragment. What about this?
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MapsFragment" />
After going through a few of the android docs, I think Fragment is not a View.
So, the workaround I would suggest is using either of the two methods.
- replace
fragmentwithandroidx.fragment.app.FragmentContainerView-> This will remove the error and as the documentation says
FragmentContainerView is a customized Layout designed specifically for Fragments. It extends FrameLayout, so it can reliably handle Fragment Transactions, and it also has additional features to coordinate with fragment behavior.
- have another view in your XML file, an example would be.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MapsFragment" />
</androidx.constraintlayout.widget.ConstraintLayout>
Or you can use both, that's up to you.
Hope this answers your question. Have a great day.
UPDATE : As per Android Developer Docs:
kotlin.Any
↳ androidx.fragment.app.Fragment
kotlin.Any
↳ android.view.View
↳ android.view.ViewGroup
↳ android.widget.FrameLayout
↳ androidx.fragment.app.FragmentContainerView
It is evident that fragment does not have View as a SuperClass. Thus, this error is thrown.
The above 2 methods are the best ways to avoid this error since in DataBinding it requires at least 1 View.
Either change fragment tag with androidx.fragment.app.FragmentContainerView
or wrap around fragment with another View or ViewGroup like LinearLayout, FrameLayout, etc.
Answered By - lets start coding
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.