API Google maps Android - marker display shaking because of viewpager
<p>I encounter a problem with my maps.</p>

<p>In fact, the markers shake (change position at multiple time) when I enable user location and use LocationListener callback.</p>

<p><s>If I quote my updateUserLocation, it works normally.</p>

<p>I never reload the marker list so I don't understand why marker display is broken.</s></p>

<p>Ok, so it's seems my viewpager is the problem, if I replace my other mapfragment by basic supportfragment, the markers doesn't shake (each of my fragment viewpager have a mapview and are based on MapBaseFragment, just different rest api request).</p>

<p>I know my viewpager load the first fragment and the adjacent basically, does I must prevent this ? And does opengl create a new instance for each fragment or it's share for each (which create this display bug maybe) ?</p>

<p>My MapBaseFragment :</p>

<pre><code>public class MapBaseFragment extends BaseFragment implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

private final String TAG = "MapBaseFragment";
private Polyline polyline;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location mLastLocation;
private GoogleMap googleMap;
private double mLatitude = 50.650;
private double mLongitude = 3.083;
private Fiche fiche;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (mGoogleApiClient == null) {
        mGoogleApiClient = new GoogleApiClient.Builder(getContext())
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }
}

public void findDirections(double fromPositionDoubleLat, double fromPositionDoubleLong, double toPositionDoubleLat, double toPositionDoubleLong, String mode) {
    if (polyline != null)
        polyline.remove();
    Map&lt;String, String&gt; map = new HashMap&lt;&gt;();
    map.put(GetDirectionsAsyncTask.USER_CURRENT_LAT, String.valueOf(fromPositionDoubleLat));
    map.put(GetDirectionsAsyncTask.USER_CURRENT_LONG, String.valueOf(fromPositionDoubleLong));
    map.put(GetDirectionsAsyncTask.DESTINATION_LAT, String.valueOf(toPositionDoubleLat));
    map.put(GetDirectionsAsyncTask.DESTINATION_LONG, String.valueOf(toPositionDoubleLong));
    map.put(GetDirectionsAsyncTask.DIRECTIONS_MODE, mode);

    GetDirectionsAsyncTask asyncTask = new GetDirectionsAsyncTask(this, googleMap);
    asyncTask.execute(map);
}

public void handleGetDirectionsResult(ArrayList&lt;LatLng&gt; directionPoints) {
    PolylineOptions rectLine = new PolylineOptions().width(3).color(Color.BLUE);
    for (int i = 0; i &lt; directionPoints.size(); i++) {
        rectLine.add(directionPoints.get(i));
    }
    polyline = googleMap.addPolyline(rectLine);
}

@Override
public void onStart() {
    mGoogleApiClient.connect();
    super.onStart();
}

@Override
public void onStop() {
    mGoogleApiClient.disconnect();
    super.onStop();
}

@Override
public void onConnected(Bundle bundle) {
    Log.d(TAG, "onConnected");

    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(1000);
    mLocationRequest.setFastestInterval(1000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

    try {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    } catch (SecurityException e) {
        e.printStackTrace();
    }
}

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

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Log.d(TAG, "onConnectionFailed " + connectionResult);
}

public Location getLastLocation() {
    try {
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);
        if (mLastLocation != null) {
            Log.d(TAG, "mLastLocation ! =null");
            return mLastLocation;
        }
    } catch (SecurityException e) {
        e.printStackTrace();
    }
    return null;
}

@Override
public void onLocationChanged(Location location) {
    Log.d(TAG, "onLocationChanged");
    mLastLocation = location;
    updateUserLocation(location);

}

public void updateUserLocation(Location location) {
    Log.d(TAG, "CarteFragment");
    if (!googleMap.isMyLocationEnabled()) {
        try {
            googleMap.setMyLocationEnabled(true);
            Log.d(TAG, "set to true");
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
    mLatitude = location.getLatitude();
    mLongitude = location.getLongitude();
    googleMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(), location.getLongitude()))
            .title("My Location").icon(BitmapDescriptorFactory
                    .defaultMarker(BitmapDescriptorFactory.HUE_RED)));
    if (fiche != null) {
        Log.d(TAG, "fiche != null");
        findDirections(mLatitude, mLongitude, fiche.getLatidude(), fiche.getLongitude(), "walking");
    }
}

public GoogleMap getGoogleMap() {
    return googleMap;
}

public void setGoogleMap(GoogleMap googleMap) {
    this.googleMap = googleMap;
}

public Fiche getFiche() {
    return fiche;
}

public void setFiche(Fiche fiche) {
    this.fiche = fiche;
}

public double getmLatitude() {
    return mLatitude;
}

public void setmLatitude(double mLatitude) {
    this.mLatitude = mLatitude;
}

public double getmLongitude() {
    return mLongitude;
}

public void setmLongitude(double mLongitude) {
    this.mLongitude = mLongitude;
}
</code></pre>

<p>}</p>

<p>A fragment which extend of it : </p>

<pre><code>public class CoachSanteFragment extends MapBaseFragment implements OnMapReadyCallback,
    GoogleMap.OnMarkerClickListener,
    CallAPICallbackInterface {

private final String TAG = "CoachSanteFragment";
private View rootView;
private MapView mapView;
private HashMap&lt;Marker, Fiche&gt; hashMap = new HashMap&lt;&gt;();

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    rootView = inflater.inflate(R.layout.fragment_coach_sante, container, false);
    if(((PratiquesActivity) getActivity()).isReload()) {
        ((PratiquesActivity) getActivity()).recreate();
    }
    Log.d(TAG, "onCreateView");
    mapView = (MapView) rootView.findViewById(R.id.fragment_coach_sante_carte_mapview);
    mapView.onCreate(savedInstanceState);

    mapView.getMapAsync(this);

    initAddingListener();

    return rootView;
}

@Override
public void onMapReady(GoogleMap googleMap) {
    setGoogleMap(googleMap);
    initGoogleMap();
}

@Override
public boolean onMarkerClick(Marker marker) {
    Log.d(TAG, "OnMarkerClick");
    if(marker.getTitle() == null || !marker.getTitle().equals("My Location")) {
        InformationsFragment informationsFragment = new InformationsFragment();
        informationsFragment.setOnItineraireSelected(new InformationsFragment.OnItineraireSelected() {
            @Override
            public void showItineraire(Fiche fiche) {
                setFiche(fiche);
                findDirections(getmLatitude(), getmLongitude(), fiche.getLatidude(), fiche.getLongitude(), "walking");
            }
        });
        Bundle args = new Bundle();
        args.putParcelable("fiche", hashMap.get(marker));
        informationsFragment.setArguments(args);
        informationsFragment.show(getFragmentManager(), null);
    }
    return true;
}

@Override
public void apiCallback(Integer responseCode, String responseMessage, List&lt;?&gt; data, Integer delegateCode) {
    Log.d(TAG, "apiCallback");
    if (data != null &amp;&amp; data.size() != 0) {
        if (delegateCode == FicheDelegate.DELEGATE_CODE &amp;&amp; responseCode == 200) {
            if (data.get(0) instanceof Fiche) {
                initMarkers((List&lt;Fiche&gt;) data);
            }
        }
    }
}

private void initGoogleMap() {
    getGoogleMap().setMapType(GoogleMap.MAP_TYPE_HYBRID);
    getGoogleMap().getUiSettings().setZoomControlsEnabled(true);
    getGoogleMap().setOnMarkerClickListener(this);
    MapsInitializer.initialize(this.getActivity());

    //Coordonnées de la France
    LatLng latLng = new LatLng(46.227638, 2.213749);
    getGoogleMap().animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 5f));

    new CallAPI(rootView.getContext(), this,
            new FicheDelegate(rootView.getContext(),
                    "fiche", "Service gastro-pédiatrie",
                    "50.650", "3.083", null
            ))
            .execute();
}

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

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

private void initMarkers(List&lt;Fiche&gt; ficheList) {
    Log.d(TAG, "initMarkers");
    Marker marker;
    for (Fiche fiche : ficheList) {
        marker = getGoogleMap().addMarker(new MarkerOptions()
                .position(new LatLng(fiche.getLatidude(), fiche.getLongitude()))
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_c_160)));
        hashMap.put(marker, fiche);
    }
}

private void initAddingListener() {
    TextView textViewAdding = (TextView) rootView.findViewById(R.id.fragment_coach_sante_textview_add);
    textViewAdding.setText(textViewAdding.getText().toString().toUpperCase());
    final FormulaireCreationPratiquesFragment formulaireCreationPratiquesFragment = new FormulaireCreationPratiquesFragment();
    Bundle args = new Bundle();
    args.putString("formulaireType", "Service gastro-pédiatrie");
    formulaireCreationPratiquesFragment.setArguments(args);
    textViewAdding.setText(textViewAdding.getText().toString().toUpperCase());
    textViewAdding.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ((PratiquesActivity) getActivity()).showFormulaire(formulaireCreationPratiquesFragment);
        }
    });
}
</code></pre>

<p>}</p>

<p>My ViewPagerAdapter :</p>

<pre><code>public class PratiquesViewPagerAdapter extends FragmentStatePagerAdapter {

private Context context;

public PratiquesViewPagerAdapter(Context context, FragmentManager fm) {
    super(fm);
    this.context = context;
}

@Override
public Fragment getItem(int position) {
    Fragment fragment;
    switch (position) {
        case 0 :
            fragment = new HopitauxFragment();
            break;
        case 1:
            fragment = new Fragment();
            //fragment = new DieteticienneFragment();
            break;
        case 2:
            fragment = new Fragment();
            //fragment = new CoachSanteFragment();
            break;
        case 3:
            fragment = new Fragment();
            //fragment = new TabacologueFragment();
            break;
        default :
            fragment = new HopitauxFragment();
            break;
    }
    return fragment;
}

@Override
public int getCount() {
    return 4;
}

@Override
public CharSequence getPageTitle(int position) {
    String title;
    switch (position) {
        case 0 :
            title = context.getResources().getString(R.string.hopitaux).toUpperCase();
            break;
        case 1 :
            title = context.getResources().getString(R.string.dieteticienne).toUpperCase();
            break;
        case 2 :
            title = context.getResources().getString(R.string.coach_sante).toUpperCase();
            break;
        case 3 :
            title = context.getResources().getString(R.string.tabacologue).toUpperCase();
            break;
        default:
            title = context.getResources().getString(R.string.hopitaux).toUpperCase();
            break;
    }
    return title;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);

    if (position &lt;= getCount()) {
        FragmentManager manager = ((Fragment) object).getFragmentManager();
        FragmentTransaction trans = manager.beginTransaction();
        trans.remove((Fragment) object);
        trans.commit();
    }
}
</code></pre>

<p>}</p>

<p>My gradle dependencie : </p>

<pre><code>compile 'com.google.android.gms:play-services-maps:8.4.0'
</code></pre>

<p>Thanks in advance for your replys :)</p>

<p>Edit : video of my problem : <a href="http://fr.tinypic.com/r/259flnn/9" rel="nofollow">http://fr.tinypic.com/r/259flnn/9</a></p>