I have an activity with Navigation Drawer and HomeFragment.
HomeFragment contains two nested fragments (child fragments): SupportMapFragment and ActionFragment.
I declare the GoogleMap object sMap
as static in HomeFragment, so it can be accessed and modified by the nested fragment ActionFragment.
Everything works fine in the first run. The map can be manipulated from within the ActionFragment. But when the HomeFragment is removed and reloaded at a later point of time, the map could only be modified from the HomeFragment (parent fragment) and not from the ActionFragment (nested fragment) anymore.
I am failing to understand why something that works in the first instance doesn't work when the fragment is reloaded. Below are the codes which I have kept to minimum for easier understanding.
HomeFragment.java (Parent fragment)
public class HomeFragment extends Fragment {
private static GoogleMap sMap;
public static GoogleMap getMap() {
return sMap;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate layout
return inflater.inflate(R.layout.f_home, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// Obtain the GoogleMap object
try {
if (sMap == null) {
sMap = ((SupportMapFragment) getActivity().getSupportFragmentManager()
.findFragmentById(R.id.home_map)).getMap();
}
} catch (Exception e) {
e.printStackTrace();
}
// Load child fragment
if (savedInstanceState == null) {
Fragment _actionFragment = new ActionFragment();
FragmentTransaction _ft = getChildFragmentManager().beginTransaction();
_ft.replace(R.id.action_container_bottom, _actionFragment);
_ft.commit();
}
}
@Override
public void onDestroyView(){
super.onDestroyView();
// Remove the map fragment to prevent errors on the next load
if(sMap != null){
try {
getActivity().getSupportFragmentManager()
.beginTransaction()
.remove(getActivity().getSupportFragmentManager()
.findFragmentById(R.id.home_map))
.commit();
sMap = null;
} catch (Exception e){}
}
}
}
f_home.xml (Layout of parent fragment)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/home_map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="@+id/action_container_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</RelativeLayout>
ActionFragment.java (Nested or Child fragment)
public class ActionFragment extends Fragment {
private static GoogleMap sMap = HomeFragment.getMap();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.f_action, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// check if map is created successfully or not
if (sMap != null) {
sMap.clear();
sMap.setPadding(0, 0, 0, 300);
sMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
sMap.setBuildingsEnabled(false);
sMap.setMyLocationEnabled(false);
sMap.getUiSettings().setRotateGesturesEnabled(false);
sMap.getUiSettings().setTiltGesturesEnabled(false);
sMap.getUiSettings().setZoomControlsEnabled(false);
sMap.moveCamera(CameraUpdateFactory.zoomTo(12));
}
}
}
Any help would be immensely appreciated as I am struggling with this for a long time. Thank you!
The problem is that the classloader only loads ActionFragment
once, that's why your static field is only initialized the first round.
What happens in first run:
1) HomeFragment#onActivityCreated()
HomeFragment#sMap
is null -> locate via findViewById()HomeFragment#sMap
= [1]2) classloader for ActionFragment
ActionFragment#sMap
is null -> load from HomeFragment.getMap()
ActionFragment#sMap
= [1]... home gets destroyed ...
3) HomeActivity#onDestroyView()
HomeFragment#sMap
= null... home gets recreated ...
4) HomeFragment#onActivityCreated()
HomeFragment#sMap
is null -> locate via findViewById()HomeFragment#sMap
= [2]Since the class ActionFragment
has already been loaded into memory, the class won't be loaded again and thus the code for your static field ActionFragment#sMap
will not be executed again. it's still refering to the old (invalid) [1] instance.
In order to fix this issue, you can do the following:
public class ActionFragment extends Fragment {
private GoogleMap mMap;
public void onAttach(Activity activity) {
super.onAttach(activity);
mMap = HomeFragment.getMap();
}
public void onDetach() {
super.onDetach() {
mMap = null;
}
}
With this code, each time the ActionFragment
is attached, it will request the latest map-instance of HomeFragment
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With