1

I've a class "MainActivity" which calls the different fragments in particular a fragment which display a GoogleMap called MapsFragment. When this fragment is called for the first time, I had some markers (which are refresh every timeToRefresh. The method startDrawingBomb() is called from the MainActivity class) and everything works perfectly when the user do not change to another fragment.

When a user ask to move to an other fragment I save the the MapsFragment created before in the backStack of the MainActivity (to retrieve it later)

The problem happens when I call this MapsFragment a second time, the fragment is displaying the map but not all the markers I've added before. I imagine it's because the MapView, and the GoogleMap created by the MapsFragment are not the same as before.

My question is : How can I retrieve the map that I draw before easily ? Or I had to stop all my threads (in onPause() for example), create a new MapsFragment, obtain a new MapView, a new GoogleMap object and apply again all the previous threads ?

This is a part of my MapsFragment :

public class MapsFragment extends Fragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener, LocationListener {

private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private OnMessageListener mCallback;
private GoogleMap _googleMap;
private MapView mMapView;
private ArrayList<Marker> markerArrayListScout = new ArrayList<>();
private ArrayList<Circle> markerArrayListBomb= new ArrayList<>();
private ArrayList<String> idToCircleId = new ArrayList<>();
private ArrayList<Integer> idArray = new ArrayList<>();

private boolean isfirstLocation = true;
boolean mustBeScoutLocationEnabled;
boolean mustDrawCircle;

public MapsFragment(){
    super();
}
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.v("MAPS_FRAGMENT","onCreate() called");
    mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    mGoogleApiClient.connect();
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Log.v("MAPS_FRAGMENT","onCreateView() called");
    View rootView = inflater.inflate(R.layout.map, container, false);
    mMapView = (MapView) rootView.findViewById(R.id.mapView);
    mMapView.onCreate(savedInstanceState);
    mMapView.onResume(); // needed to get the map to display immediately
try {
        MapsInitializer.initialize(getActivity().getApplicationContext());
    } catch (Exception e) {
        e.printStackTrace();
    }
    mMapView.getMapAsync(this);
    return rootView;
}
@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 onLowMemory() {
    super.onLowMemory();
    mMapView.onLowMemory();
}
@Override
public void onMapReady(GoogleMap googleMap) {
    Log.v("MAPS_FRAGMENT","onMapReady() called");
    _googleMap = googleMap;
    _googleMap.setMyLocationEnabled(true);
}


@Override
public void onConnected(@Nullable Bundle bundle) {
    Log.v("Location","onConnected");
    mLocationRequest = LocationRequest.create();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(1000); // Update location every second

        //Execute location service call if user has explicitly granted ACCESS_FINE_LOCATION..
        LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this);
}

@Override
public void onConnectionSuspended(int i) {
    Log.v("Location","onConnectionSuspended");
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Log.v("Location","onConnectionFailed");

}

@Override
public void onLocationChanged(Location location) {
    Log.v("Location","location : " + location.toString());
    // Add a marker and move the camera
    if(isfirstLocation) {
        LatLng currentLat = new LatLng(location.getLatitude(), location.getLongitude());
        _googleMap.moveCamera(CameraUpdateFactory.newLatLng(currentLat));
        _googleMap.moveCamera(CameraUpdateFactory.zoomTo(19));
        isfirstLocation = false;
    }
    //if(mCallback != null)
        mCallback.onUpdateLocation(location.getLatitude(),location.getLongitude());
}

/**
 * Draw Bomb and update its view all the timeToRefresh milliseconds.
 * @param timeToRefresh the time in milliseconds which the marker needs to refresh
 * @param id the id of the current bomb we need to work with
 */
public void startDrawingBomb(final int timeToRefresh,final int id){
    mustDrawCircle = true;
    Log.v("JOSE","passe1");
    final Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                while (mustDrawCircle) {
                    Log.v("JOSE","update bomb");
                    mCallback.updateBombs();
                    //Log.v("JOSE","bomb updated ?");
                    Thread.sleep(timeToRefresh);
        // This method is called from the MainActivity
                    final CircleOptions circleOptions = mCallback.drawBombCircle(id);
                    final String idToCompare = getIdCircle(id);
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            boolean isCenterSet = false;
                            if (circleOptions != null) {
                                Log.v("JOSE","size marker : " +markerArrayListBomb.size());
                                for(int i=0;i<markerArrayListBomb.size();i++){
                                    Log.v("JOSE","Id to compare : " +idToCompare);
                                    Log.v("JOSE","Id markearray : " +markerArrayListBomb.get(i).getId());
                                    if((markerArrayListBomb.get(i).getId()).equals(idToCompare)){
                                        // si c'est la même chose, il suffit de updater
                                        markerArrayListBomb.get(i).setCenter(circleOptions.getCenter());
                                        markerArrayListBomb.get(i).setVisible(true);
                                        isCenterSet = true;
                                    }
                                }
                                // il faut creer une nouvelle bombe
                                if(!isCenterSet) {
                                    Circle newCircle = _googleMap.addCircle(circleOptions);
                                    markerArrayListBomb.add(newCircle);
                                    newIdCircle(id, newCircle.getId());
                                    //Log.v("JOSE", "New bomb drawn id : " + newCircle.getId());
                                }

                            }
                        }
                    });
                }
                String idToCompare = getIdCircle(id);
                for(int i=0;i<markerArrayListBomb.size();i++){
                    if((markerArrayListBomb.get(i).getId()).equals(idToCompare)){
                        final int index = i;
                        getActivity().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                markerArrayListBomb.get(index).setVisible(false);
                            }
                        });
                    }
                }
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    });
    thread.start();
}
public void cancelDrawingBomb(){mustDrawCircle = false;}

// Container Activity must implement this interface
public interface OnMessageListener {
    public void onUpdateLocation(double lat,double lon);
    public void getAllOtherScoutsLocation();
    public void updateBombs();
    public CircleOptions drawBombCircle(int id);
}

/**
 *
 * @param id de la bombe dans la classe Bomb
 * @return le cercle créé associé. Sinon, return null
 */
private String getIdCircle(int id){
    if(idArray.size() == 0)
        return null;
    for(int i=0 ; i<idArray.size();i++){
        if(idArray.get(i) == id)
            return idToCircleId.get(i);
    }
    return null;
}

/**
 * Si une bombe est supprimée, il faut appeler cette méthode
 * @param id
 */
private void removeIdCircle(int id){
    for(int i=0 ; i<idArray.size();i++){
        if(idArray.get(i) == id) {
            idToCircleId.remove(i);
            idArray.remove(i);
        }
    }
}

/**
 * A appeler à chaque fois u'une bombe est créée
 * @param id l'id de la classe BOMB
 * @param ids l'id créé grâce à la classe Circle de google
 */
private void newIdCircle(int id,String ids){
    idToCircleId.add(ids);
    idArray.add(id);
}

}

And this how I called the second time my MapsFragment :

 if (id == R.id.map) {
        if(fragmentManager.findFragmentByTag(MAPS_FRAGMENT) != null){
            MapsFragment fragment =          (MapsFragment)fragmentManager.findFragmentByTag(MAPS_FRAGMENT);
            fragmentManager.beginTransaction().replace(R.id.frame_container, fragment,MAPS_FRAGMENT).addToBackStack(MAPS_FRAGMENT).commit();
        }
    }

Thanks a lot everyone, and sorry for my bad English. If you want more information, or a better explanation, don't hesitate to tell me !

renaudyes
  • 41
  • 4

1 Answers1

0

Implement save to bundle functionality at Onpause() for your MapFragment. Then in onCreateView() always check your bundle.

If the bundle is empty then it's a new fragment. If the bundle is not empty this means it was previously created.

Hope this helps :

For saving and restoring to bundle : Saving Android Activity state using Save Instance State

Community
  • 1
  • 1
Amr Yousef
  • 554
  • 1
  • 10
  • 27