Reputation: 2528
I have a navigation drawer that replaces a framelayout with a supportmapfragment. I am able to load the fragment fine the first time, but pressing that drawer item again gives the dreaded "duplicate binary" error.
I read from Binary XML file line #9: Error inflating class fragment with Google Map Fragment that the error is due to the fact that the map fragment cannot be removed from the navdrawer's fragment if the map fragment exists in the xml. He suggested a programmatic approach so I tried this:
NavDrawerFirstFragment:
@Override
public void onCreate(Bundle savedInstanceState) {
Log.d("DEBUG", "In NavDrawerFirstFragment onCreate()");
super.onCreate(savedInstanceState);
}
public NavDrawerFirstFragment() {
// fragment needs a no arg ctor
}
public static NavDrawerFirstFragment newInstance(Location currentLoc) {
NavDrawerFirstFragment firstFragment = new NavDrawerFirstFragment();
// how to set arguments for this fragment when this method is static
Bundle args = new Bundle();
args.putParcelable("current_loc", currentLoc);
firstFragment.setArguments(args);
return firstFragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("DEBUG", "NavDrawerFirstFragment onCreateView()");
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_nav_drawer_first, container, false);
if (mMap == null) {
mMapFragment = new SupportMapFragment();
FragmentTransaction ft = getChildFragmentManager().beginTransaction();
ft.replace(R.id.mapContainer, mMapFragment);
mMap = mMapFragment.getMap();
}
/*if(mMap == null) {
mMapFragment = (SupportMapFragment)getFragmentManager().findFragmentById(R.id.map);
}*/
return view;
}
@Override
public void onStart() {
Log.d("DEBUG", "NavDrawerFirstFragment onStart()");
super.onStart();
mMap.getUiSettings().setRotateGesturesEnabled(false);
// check for google play services here
MarkerOptions mo = new MarkerOptions();
Location initialLoc = getArguments().getParcelable("current_loc");
LatLng latlong = new LatLng(initialLoc.getLatitude(), initialLoc.getLongitude());
Marker startingMarker = mMap.addMarker(mo.position(latlong).position(latlong).icon(
BitmapDescriptorFactory.defaultMarker(
BitmapDescriptorFactory.HUE_GREEN)));
startingMarker.setDraggable(true);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latlong, 12));
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
Log.d("DEBUG", "NavDrawerFirstFragment onActivityCreated");
super.onActivityCreated(savedInstanceState);
if (mMap == null) {
mMap = mMapFragment.getMap();
}
}
@Override
public void onDetach() {
Log.d("DEBUG", "NavDrawerFirstFragment onDetach()");
super.onDetach();
}
@Override
public void onResume() {
Log.d("DEBUG", "NavDrawerFirstFragment onResume()");
super.onResume();
FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.mapContainer, mMapFragment);
fragmentTransaction.commit();
if (mMapFragment != null)
mMap = mMapFragment.getMap();
}
@Override
public void onPause() {
Log.d("DEBUG", "NavDrawerFirstFragment onPause()");
super.onPause();
if (mMapFragment != null) {
FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.remove(mMapFragment);
fragmentTransaction.commit();
}
}
fragment_nav_drawer_first.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/navBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/hnt_et_location"
android:layout_weight="1"
android:inputType="text" />
<Button
android:id="@+id/btn_find"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/str_btn_find" />
</LinearLayout>
<FrameLayout
android:id="@+id/mapContainer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"></FrameLayout>
</LinearLayout>
This is actually the solution proposed in another SO post: Error opening SupportMapFragment for second time
When I debug it I notice that however long I wait before stepping into onStart(), my GoogleMap mMap is still null. This is driving me bonkers and I would really appreciate the proper solution to consistently accessing a navdrawer fragment that isn't just a map but a searchbar and a map like I have.
Upvotes: 1
Views: 1931
Reputation: 7306
This problem occurs because map already exits and you try to add it again with the same id ..
So you need to remove the map framegnt in onPause
and have to again add it in onResume
:
@Override
public void onResume() {
super.onResume();
FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.mapContainer, mMapFragment);
fragmentTransaction.commit();
if (mMapFragment != null)
mMap= mMapFragment.getMap();
}
@Override
public void onPause() {
super.onPause();
if (mMapFragment != null) {
FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.remove(mMapFragment);
fragmentTransaction.commit();
}
}
Move your onStart
code to onActivityCreated
as shown here :
mMapFragment = new SupportMapFragment() {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initMap();
}
};
public void initMap()
{
if (mMap== null) {
mMap= mMapFragment.getMap();
}
mMap.getUiSettings().setRotateGesturesEnabled(false);
// check for google play services here
MarkerOptions mo = new MarkerOptions();
Location initialLoc = getArguments().getParcelable("current_loc");
LatLng latlong = new LatLng(initialLoc.getLatitude(), initialLoc.getLongitude());
Marker startingMarker = mMap.addMarker(mo.position(latlong).position(latlong).icon(
BitmapDescriptorFactory.defaultMarker(
BitmapDescriptorFactory.HUE_GREEN)));
startingMarker.setDraggable(true);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latlong, 12));
}
Upvotes: 2