1

I'm trying to display a map view fragment within a tab but for some reason whenever I flick the toggle switch and go to a different tab, the app crashes whenever I return to the tab containing the map. I looked at the onResume() code but I'm not sure what needs to change within the class.

public class FragmentCentralParkLocation extends android.support.v4.app.Fragment implements OnMapReadyCallback {

    public FragmentCentralParkLocation() {
        // Required empty constructor
    }

    GoogleMap mGoogleMap;
    MapView mMapView;

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_centralpark_location, container, false);

        mMapView = (MapView) v.findViewById(R.id.map_centralpark);
        mMapView.onCreate(savedInstanceState);
        mMapView.getMapAsync(this); //this is important

        SwitchCompat swt = (SwitchCompat) v.findViewById(R.id.switch_map_centralpark);
        swt.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked){
                    boolean success = mGoogleMap.setMapStyle(new MapStyleOptions(getResources()
                            .getString(R.string.style_json)));    
                }else{
                    boolean success = mGoogleMap.setMapStyle(null);
                }
            }
        });



        return v;
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
        mGoogleMap.getUiSettings().setZoomControlsEnabled(true);
        mGoogleMap.setBuildingsEnabled(true);
        mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        // Add markers and move the camera
        LatLng knt_location = new LatLng(40.782893, -73.965422);
        mGoogleMap.addMarker(new MarkerOptions()
                .position(knt_location)
        );


        // Updates the location and zoom level of the MapView
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(40.782893, -73.965422), 18);
        mGoogleMap.animateCamera(cameraUpdate);
    }

    @Override
    public void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mMapView.onDestroy();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mMapView.onSaveInstanceState(outState);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mMapView.onLowMemory();
    }
}

Stage 1

enter image description here

Stage 2

enter image description here

Stage 3

enter image description here

Logcat

03-12 16:45:24.965 2328-2328/com.ustravel.parks E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                    Process: com.ustravel.parks, PID: 2328
                                                                                    java.lang.NullPointerException
                                                                                        at com.ustravel.parks.FragmentCentralParkLocation $1.onCheckedChanged(FragmentCentralParkLocation.java:49)
                                                                                        at android.widget.CompoundButton.setChecked(CompoundButton.java:127)
                                                                                        at android.support.v7.widget.SwitchCompat.setChecked(SwitchCompat.java:1062)
                                                                                        at android.widget.CompoundButton.onRestoreInstanceState(CompoundButton.java:381)
                                                                                        at android.view.View.dispatchRestoreInstanceState(View.java:12799)
                                                                                        at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2643)
                                                                                        at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2643)
                                                                                        at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2643)
                                                                                        at android.view.View.restoreHierarchyState(View.java:12777)
                                                                                        at android.support.v4.app.Fragment.restoreViewState(Fragment.java:475)
                                                                                        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1329)
                                                                                        at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
                                                                                        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
                                                                                        at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:757)
                                                                                        at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2355)
                                                                                        at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2146)
                                                                                        at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2098)
                                                                                        at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1979)
                                                                                        at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:626)
                                                                                        at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:166)
                                                                                        at android.support.v4.view.ViewPager.populate(ViewPager.java:1268)
                                                                                        at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:668)
                                                                                        at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:630)
                                                                                        at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:611)

onResume map result

enter image description here

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
wbk727
  • 8,017
  • 12
  • 61
  • 125

1 Answers1

3

I think you're trying to restore the state of your SwitchCompat before your GoogleMap is ready and initialized. Here I modified your code a little bit:

public class FragmentCentralParkLocation extends android.support.v4.app.Fragment implements OnMapReadyCallback {

    public FragmentCentralParkLocation() {
        // Required empty constructor
    }

    GoogleMap mGoogleMap;
    MapView mMapView;
    SwitchCompat swt;

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_centralpark_location, container, false);

        mMapView = (MapView) v.findViewById(R.id.map_centralpark);
        mMapView.onCreate(savedInstanceState);
        mMapView.getMapAsync(this); //this is important

        swt = (SwitchCompat) v.findViewById(R.id.switch_map_centralpark);

        return v;
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
        mGoogleMap.getUiSettings().setZoomControlsEnabled(true);
        mGoogleMap.setBuildingsEnabled(true);
        mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        swt.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
               initMap(isChecked);
            }
        });

        initMap(swt.isChecked());

        // Add markers and move the camera
        LatLng knt_location = new LatLng(40.782893, -73.965422);
        mGoogleMap.addMarker(new MarkerOptions()
                .position(knt_location)
        );


        // Updates the location and zoom level of the MapView
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(40.782893, -73.965422), 18);
        mGoogleMap.animateCamera(cameraUpdate);
    }

    @Override
    public void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mMapView.onDestroy();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mMapView.onSaveInstanceState(outState);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mMapView.onLowMemory();
    }

    private void initMap(boolean isChecked){
          if(isChecked){
                    mGoogleMap.setMapStyle(new MapStyleOptions(getResources()
                            .getString(R.string.style_json)));    
                }else{
                    mGoogleMap.setMapStyle(null);
                }
    }
}

I hope this will help you.

Edit: If you still experience crashing, you can try to remove onCheckedChangeListener of SwitchCompat in onStop or onDestroy by trying the following code:

swt.setonCheckedChangeListener(null);
wbk727
  • 8,017
  • 12
  • 61
  • 125
savepopulation
  • 11,736
  • 4
  • 55
  • 80
  • It almost helps. It no longer crashers BUT the problem I'm now facing is that the map doesn't save it's state. When I go to a different tab and then return to the map tab, the map view switches back to the daytime map rather than staying on the dark map. See the screenshot titled 'onResume map result' – wbk727 Mar 12 '17 at 18:36
  • i changed back to boolean success = mGoogleMap.setMapStyle(null); part in onmapcheckedchange listener. this'll do what ever you want. – savepopulation Mar 12 '17 at 18:40
  • Unfortunately this hasn't made a difference + this warning now appears: `Variable 'success' is never used` – wbk727 Mar 12 '17 at 18:45
  • you can remove boolean success appointment if you will not use. – savepopulation Mar 12 '17 at 18:48
  • Everytime I return to the map tab, the map view keeps resetting itself – wbk727 Mar 12 '17 at 18:51
  • i refactored code a bit more. i think this'll help your problem. – savepopulation Mar 12 '17 at 19:23
  • Although everytime I go back to the tab it seems to refresh the map (tab is black) before showing the dark map (1 second later). Is it possible to prevent this from happening? – wbk727 Mar 12 '17 at 20:43
  • how many tabs you have in your viewpager? for a quick fix you can change viewPager's offsetPageLimit to 2. – savepopulation Mar 12 '17 at 20:49