2013-02-28 5 views
6

Ich entwickle eine Android App und in einer der Aktivitäten verwende ich die MapsActivity um eine Map zu zeigen. Was ich gesehen habe, ist, dass es auf einem 2.2 (API8) Emulator einige Zeit dauert, um die Karte zu laden und ich habe Zeit, die Menüschaltfläche zu drücken und dann wieder auf die appContentView() zu laden Problem kommt, wenn es auf onResume() geht, die zweimal aufgerufen wird.Warum wird die Methode onResume zweimal ausgeführt, wenn die App noch die onCreate-Methode ausführt?

Je nach Lebenszyklus einer Android-Aktivität wird nach einem onPause() -> [onRestart() -> onStart()] -> onResume() aufgerufen, wenn die App wieder in den Vordergrund kommt, und onResume() wird nach onCreate() -> [onStart()] aufgerufen, wenn es gestartet wird.

Aber warum wird nicht einmal aufgerufen, wenn es noch in setContentView in onCreate() geladen wird?

Das ist etwas, das mich interessiert, weil ich nicht jedes Mal ein boolean verwenden möchte, wenn ich Karten verwende, die denken, dass es zweimal ausgeführt werden könnte, um Probleme zu vermeiden, d. H. Eine doppelte Inkrementierung eines Zählers.

Ich weiß nicht, ob es ein Problem des Emulators ist, wie das Problem, das ich über Querformatausrichtung http://code.google.com/p/android/issues/detail?id=2423 gesehen habe.

Bitte nehmen Sie sich einen Blick auf diese:

public class LocationActivity extends MapActivity { 

    private static final String TAG = "LocationActivity"; 
    private static int i; 

    protected void onCreate(Bundle savedInstanceState) { 
     i = 0; 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_location); 
    } 

    protected void onResume(){ 
     super.onResume();  
     i++; 
     Log.w(TAG,String.valueOf(i));   
     showDialogSettings(); 
    } 

    private void showDialogSettings() { 

     AlertDialog.Builder dialog = new AlertDialog.Builder(this); 
     String title = "I-Value:" + String.valueOf(i); 
     String positiveButton = "OK"; 
     final Intent intent = new Intent(Settings.ACTION_SETTINGS); 

     dialog.setTitle(title); 
     dialog.setPositiveButton(positiveButton, new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int which) { 
      Intent settingsIntent = intent; 
      startActivity(settingsIntent); 
     } 
     }); 
     dialog.show(); 
    } 

    @Override 
    protected boolean isRouteDisplayed() { 
     return false; 
    } 
    } 

activity_location.xml

<?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="vertical" > 

     <com.google.android.maps.MapView 
      android:id="@+id/locationactivity" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:apiKey="XXXXXXXXXXXXXXX" 
      android:clickable="false" 
      android:enabled="true" /> 

    </LinearLayout> 

Sie können das Problem neu erstellen:

  1. Wenn Sie einen Haltepunkt an setContentView ein Set ein weiterer bei super.OnResume().
  2. Ausführen und wenn die Debug-Ansicht.
  3. Senden Sie die App an den Hintergrund und führen Sie sie erneut aus.
  4. Beenden Sie die Ausführung, Sie sollten einen Dialog sehen, der einen Wert anzeigt: 2.


die Kommentare von Geobits und G. Blake Meike getan lesen, ist dieser Teil eine Antwort nur zu klären, wenn ich falsch bin.

Vielleicht war das Beispiel mit Karten wegen der asynchronen Belastung der Karte schlecht. Ich habe die MapsActivity für eine Aktivität geändert. Nehmen wir an, dass das Telefon überlastet ist. OnCreate führt also eine Schleife von 8 Sekunden aus (nicht genug Zeit für ein Android, das nicht antwortet).

Und hier der neue Code ein Licht android Layout mit:

public class LocationActivity extends Activity { 

private static final String TAG = "LocationActivity"; 
private static int i; 

protected void onCreate(Bundle savedInstanceState) { 
    i = 0; 
    Log.w(TAG,"onCreate"); 
    super.onCreate(savedInstanceState); 
    setContentView(android.R.layout.simple_spinner_item); 
    Log.w(TAG,"beforeLoop"); 
    try { 
     for(int j = 0; j < 8; j++){ 
      Log.w(TAG,"Sleeping..."); 
      Thread.sleep(1000); 
     } 
    } catch (InterruptedException e) { 
    } 
    Log.w(TAG,"afterLoop"); 
} 

protected void onResume(){ 
    super.onResume(); 
    Log.w(TAG,"onResume" + String.valueOf(i)); 
    i++; 
    Log.w(TAG,"check Mobile Connectivity");  
    ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();  
    if(networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE && networkInfo.isAvailable()){ 
     Toast.makeText(this, "Network available!", Toast.LENGTH_LONG).show(); 
     Log.w(TAG,"showingToast"); 
    } 

} 

protected void onPause(){ 
    super.onPause(); 
    Log.w(TAG,"onPause:" + String.valueOf(i)); 
} 

protected void onStop(){ 
    super.onResume(); 
    Log.w(TAG,"onStop:" + String.valueOf(i)); 
} 
} 

Wenn ich die Anwendung minimiert, wenn das Protokoll nach wie vor „Sleeping ...“ druckt und schnell ich die app ich sehen kann wieder laufen das "Sleeping ...", überprüft onResume zweimal die Konnektivität (dies ist eine korrekte Art der Überprüfung der Netzwerkkonnektivität).

geht hier die Logcat:

  • 2-28 20:02:48.643: W/LocationActivity (651): onCreate
  • 2-28 20: 02: 48,646: W/LocationActivity (651): beforeLoop
  • 02-28 20: 02: 48,646: W/LocationActivity (651): Schlafen ...
  • 02-28 20: 02: 49,655: W/LocationActivity (651): Schlafen ...
  • 02-28 20: 02: 50,678: W/LocationActivity (651): Schlafen ...
  • 02-28 20: 02: 51,673: W/LocationActivity (651): Schlafen ...
  • 02-28 20: 02: 52,674: W/LocationActivity (651): Schlafen ...
  • 02- 28 20: 02: 53.738: W/StandortAkt ivity (651): Schlafen ...
  • 02-28 20: 02: 54,773: W/LocationActivity (651): Schlafen ...
  • 02-28 20: 02: 55,795: W/LocationActivity (651) Schlafen ...
  • 02-28: 20: 02: 56,816: W/LocationActivity (651): afterLoop
  • 02-28 20: 02: 56,824: W/LocationActivity (651): onResume0
  • 02- 28 20: 02: 56,824: W/LocationActivity (651): check Mobil Connectivity
  • 02-28 20: 02: 57,134: W/LocationActivity (651): showingToast
  • 02-28 20: 02: 57,234: W/StandortActiv ity (651): onPause: 1
  • 02-28 20: 02: 57,253: W/LocationActivity (651): OnStop: 1
  • 02-28 20: 02: 57,264: W/LocationActivity (651): onResume1
  • 02-28 20: 02: 57,264: W/LocationActivity (651): Check mobile Connectivity-
  • 02-28 20: 02: 57,324: W/LocationActivity (651): showingToast

Toast wird Zeige zweimal die Nachricht.

Mit Blick auf die logCat ist der Lebenszyklus korrekt, aber ich möchte nur berücksichtigen, dass onCreate manchmal wegen eines überlasteten Systems verzögert werden kann und wenn onResume zweimal ausgeführt wird, dann muss ich mich um einige Initialisierungen kümmern, also ich Ich muss Booleans verwenden, die ich nicht benutzen sollte, weil onCreate noch läuft.

Wenn es sich bei einem Toast um einen Dialog handelt, sind aus dem POV des Benutzers zwei Dialoge nicht erwünscht.

Bitte führen Sie den Code in der gleichen Art und Weise wie ich, bin ich stur genug, um nicht bis geben: P

+0

Es gibt einen einzelnen Thread, der OnCreate und onResume ausführt. Bis OnCreate zurückkehrt, kann onResume nicht aufgerufen werden. Wenn Sie eine Reihe von Ereignissen in die Warteschlange stellen, werden sie der Reihe nach ausgeführt, wenn onCreate beendet wird. Android hat genau das getan, was Sie ihm gesagt haben: Jedes Mal, wenn es startet, einen Dialog erstellen. Du hast es zweimal angefangen. Und, btw, 8 Sekunden ist * way * lang genug, um eine ANR zu verursachen ... –

+0

Ok jetzt bekomme ich es, danke allen. – AlexBcn

Antwort

5

Das ist von Entwurf. Wenn Sie die Aktivität an Hintergrund senden, muss onResume() aufrufen, wenn es zurückgibt.

Von the documentation:

Beachten Sie, dass das System diese Methode aufruft, einschließlich jedes Mal Ihre Aktivität in den Vordergrund kommt, wenn es zum ersten Mal erstellt wird. Daher sollten Sie onResume() implementieren, um Komponenten zu initialisieren, die Sie während onPause() freigeben und alle anderen Initialisierungen durchführen, die jedes Mal auftreten müssen, wenn die Aktivität in den Status "Fortgesetzt" eintritt (z. B. Animationen starten und Komponenten initialisieren, die nur verwendet werden, während die Aktivität über Benutzer verfügt) Fokus).

Beachten Sie auch, setContentView() ist wahrscheinlich schon zurückgegeben. Es sollte nicht lange dauern, auch für eine . Die Zuordnung wird wahrscheinlich asynchron geladen, sodass der UI-Thread nicht gebunden wird.

+0

hi @Geobits ja alles was du sagst ist richtig Aber wenn du den Schritten folgst, die ich erwähnt habe, würdest du den Doppelanruf sehen. Wenn Sie bei setContentView einen Haltepunkt setzen und Ihre Aktivität in den Vordergrund tritt, sollte das System dies erkennen und nach der Wiederaufnahme der Ausführung onResume einmal aufgerufen werden. Witout Debugging passiert mir. Mein Laptop benötigt fast 15 Sekunden, um die setContentView-Karte zu übergeben, die Zeit, um die App zu minimieren und erneut zu starten, und plötzlich erscheint ein Dialog mit dem Wert 2. – AlexBcn

+0

@AlexBcn: Geobits hat es genau richtig. Sie scheinen zu denken, dass diese setContentView nicht zurückgegeben wurde, da der Inhalt der Ansicht nicht vollständig angezeigt wurde. Das ist nicht wahr! Wenn es so funktioniert, erhalten Sie jedes Mal eine ANR, wenn Sie eine Karte geladen haben. Ihre App wurde angehalten und ordnungsgemäß fortgesetzt. Die Kartenladung erfolgt asynchron und Ihre App ist * nicht * noch in onCreate. –

+0

Hallo @G. Blake Meike, ich habe der Frage einen Text hinzugefügt, sieh es dir an. Vielen Dank. – AlexBcn

Verwandte Themen