2013-01-22 13 views
7

Mam problem z Fragmentem, który osadza SuportMapFragment z nowego interfejsu API Map Google. Kiedy tworzony jest mój fragment, pobiera pewne dane w metodzie AsyncTask zaczynając od metody. Podczas gdy tak się dzieje, MapFragment pozostaje poza ekranem, zamiast tego wyświetlany jest pasek postępu.Dlaczego GoogleMap.animateCamera() ulega awarii po onGlobalLayout()?

Po ukończeniu AsyncTask rejestruję się w zdarzeniu mapView z onGlobalLayout. Następnie wyświetlam fragment, co powoduje, że widok mapy jest wyświetlany i układany. onGlobalLayout jest wyzwalane i rozpoczyna się animacja.

To działało dobrze przez jakiś czas, dopóki nie zacząłem optymalizować operacji w zbieraniu danych AsyncTask, aby zakończyć prawie natychmiastowo. Teraz aplikacja często zawiesza się po uruchomieniu, częściej w wersji niż w debugowaniu, dlatego myślę, że mam tu do czynienia z kondycją wyścigową, o której nie wiem.

Wyjątek stanowi:

rozmiar mapy nie powinno być 0. Najprawdopodobniej układ jeszcze nie doszło do widoku mapy.

Wszelkie spostrzeżenia są mile widziane.

Dla odniesienia: Jest to kod, który wydaje się spowodować katastrofę:

// Hide status UI 
this.progressBar.setVisibility(View.INVISIBLE); 
this.statusTextView.setVisibility(View.INVISIBLE); 

// Update state 
this.uraDataDownloadFinished = true; 

// Schedule map translation to occur when layout is complete 
final View mapView = this.mapFragment.getView(); 
if (mapView.getViewTreeObserver().isAlive()) 
{ 
    mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() 
    { 
     @SuppressWarnings("deprecation") 
     @SuppressLint("NewApi") // We check which build version we are using. 
     @Override 
     public void onGlobalLayout() 
     { 
      Log.d(TAG, "onGlobalLayout()"); 
      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) 
      { 
       mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
      } 
      else 
      { 
       mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
      } 

      // here we crash 
      this.map.animateCamera(
        CameraUpdateFactory.newLatLngBounds(
          LatLngBounds.builder() 
           .include(topLeft) 
           .include(topRight) 
           .include(bottomLeft) 
           .include(bottomRight) 
           .build(), 
          0), 
        durationMs, 
        null); 
     } 
    }); 
} 

// Show map (which will eventually trigger onGlobalLayout) 
this.getFragmentManager().beginTransaction().show(this.mapFragment).commit(); 
this.mapFragment.getMap().setOnCameraChangeListener(this); 

Dzięki wielkie!

Odpowiedz

5

Nie jestem pewien, ale ponieważ używasz AsyncTask, prawdopodobnie próbujesz uzyskać granice map, zanim mapa przeszła układ.

Możesz zobaczyć documentation, sugeruje zamiast tego używać newLatLngBounds(boundary, width, height, padding).

+0

Dzięki, że działa. Ponieważ mapa całkowicie wypełnia pojemnik układu, mogę zamiast tego użyć jego wymiarów. Jednak moje pytanie pozostaje. Ponieważ czekam na 'onGlobalLayout()', nie powinienem wpaść na ten problem, czy powinienem? – Chris

+0

Nie, nie sądzę, musisz poczekać, aż mapy zostaną poddane układowi. – jgonza73

+0

... lub edytuj CameraOptions bez granic map – jgonza73

3

Spróbuj tego, że pracuje dla mnie:

map.setOnCameraChangeListener(new OnCameraChangeListener() { 

    @Override 
    public void onCameraChange(CameraPosition arg0) { 
     // Move camera. 
     map.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 10)); 
     // Remove listener to prevent position reset on camera move. 
     map.setOnCameraChangeListener(null); 
    } 
}); 
Powiązane problemy