2013-02-28 116 views
6

我正在開發一個Android應用程序,並且正在使用MapsActivity顯示地圖的活動之一。 我所看到的是在2.2(API8)模擬器上加載地圖需要一些時間,我有時間按下菜單按鈕,然後回到應用程序,它仍然在setContentView()上加載,問題出現在onResume()中,它將被調用兩次。如果應用程序仍在運行onCreate方法,爲什麼onResume方法將被執行兩次?

根據Android活動的生命週期,在onPause() - > [onRestart() - > onStart()] - > onResume()將被調用,如果應用程序再次來到前臺後,並且onResume()在onCreate() - > [onStart()]啓動後調用。

但是爲什麼不調用一次,如果它仍然加載onCreate()中的setContentView?

這是我感興趣的事情,因爲我不想每次使用布爾值時都會使用布爾值,認爲它可以執行兩次以避免問題,即計數器的雙重增量。

我不知道它是否是模擬器的問題,因爲我已經看到關於橫向縱向方向http://code.google.com/p/android/issues/detail?id=2423的問題。如果你的setContentView的設置斷點

  1. 請看看這個:

    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> 
    

    您可以重新創建問題另一個在super.OnResume()。

  2. 執行時和調試視圖。
  3. 發送到後臺應用程序並重新運行一次。
  4. 完成執行,您應該會看到一個對話框,顯示一個值:2。


閱讀Geobits和G.布雷克每棵做了註釋,這部分的答案只是如果我錯了澄清。

也許地圖的例子很糟糕,因爲地圖的異步加載。 我更改了一個Activity的MapsActivity,讓我們假設手機超載,所以onCreate將執行一個8秒的循環(而不是Android的未響應時間)。

在這裏,使用光的Android佈局的新代碼:

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)); 
} 
} 

如果我最小化的應用程序時,日誌仍然打印「睡......」並很快我重新運行該應用程序,我可以看到「Sleeping ...」,onResume將檢查連接性的兩倍(這是檢查網絡連接的正確方法)。

這裏去了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):睡眠...
  • 02-28 20:02:49.655:W/LocationActivity(651):休眠...
  • 02-28 20:02:50.678:W/LocationActivity(651):休眠...
  • 02-28 20:02:51.673:W/LocationActivity(651):休眠...
  • 02-28 20:02:52.674:W/LocationActivity(651):休眠...
  • 02- 28 20:02:53.738:W/LocationAct (651):睡覺...
  • 02-28 20:02:54.773:W/LocationActivity(651):Sleeping ...
  • 02-28 20:02:55.795:W/LocationActivity(651) :休眠...
  • 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 Mobile Connectivity
  • 02-28 20:02:57.134:W/LocationActivity(651):showingToast
  • 02-28 20:02:57.234:W/LocationActiv兩者均(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):檢查移動連接
  • 02-28 20:02:57.324:W/LocationActivity(651):showingToast

吐司將顯示消息的兩倍。

看着logCat的生命週期是正確的,但我只是想考慮一下,有時onCreate可能會因系統重載而延遲,如果onResume被執行兩次,那麼我必須照顧一些初始化,所以我必須使用布爾值,我認爲我不應該使用,因爲onCreate仍在運行。

如果不是Toast,它是一個對話框,從用戶的POV開始,不歡迎兩個對話框。

請執行作爲我做同樣的方式代碼,我有足夠的頑固不放棄:P

+0

有一個執行onCreate然後onResume的線程。在onCreate返回之前,不能調用onResume。如果你排隊了一堆事件,它們會在onCreate退出時依次發生。 Android完全按照你的要求做了:每次啓動時都會出現一個對話框。你開始了兩次。而且,順便說一句,8秒是*方式*足夠長,導致一個ANR ... – 2013-02-28 20:56:08

+0

好了,現在我明白了,謝謝大家。 – AlexBcn 2013-03-01 09:37:49

回答

5

這是由設計。如果您將活動發送到後臺,它將返回時必須請致電onResume()

the documentation

請注意,系統調用這個方法每次你的活動進入前臺,當它首次創建包括時間。因此,您應該實現onResume()來初始化您在onPause()期間釋放的組件,並執行每次活動進入恢復狀態時必須發生的任何其他初始化(例如僅在活動具有用戶時才使用的開始動畫和初始化組件焦點)。

另外請注意,setContentView()已經可能已經返回。它不應該花很長時間,即使是MapView。該映射可能是異步加載的,所以它不會捆綁UI線程。

+0

嗨@Geobits是的一切你說的是對的但如果你按照我提到的步驟你會看到雙重打電話。如果你在setContentView中設置了一個斷點,並且你的活動進入了前臺,那麼系統應該檢測到它,並且在恢復執行onResume之後應該調用一次。 Witout調試我發生。我的筆記本電腦花費了將近15秒的時間來傳遞setContentView地圖,並花費時間最小化並重新運行應用程序,並突然出現一個值爲2的對話框。 – AlexBcn 2013-02-28 17:18:22

+0

@AlexBcn:Geobits完全正確。您似乎認爲,因爲視圖的內容尚未完全顯示,所以setContentView尚未返回。那不是真的!如果這樣工作,每次載入地圖時都會得到一個ANR。您的應用已暫停並恢復正常。地圖加載是異步發生的,你的應用程序*不*仍在onCreate中。 – 2013-02-28 17:43:17

+0

Hi @G。布萊克梅克,我已經添加了一些文字的問題,檢查出來。謝謝。 – AlexBcn 2013-02-28 20:36:10

相關問題