Почему метод onResume будет выполняться дважды, если приложение все еще работает с методом onCreate?

Я разрабатываю приложение для Android и в одном из мероприятий я использую MapsActivity, чтобы показать карту. Я видел, что на эмуляторе 2.2 (API8) требуется некоторое время для загрузки карты, и у меня есть время, чтобы нажать кнопку меню, а затем вернуться к приложению, и он все еще загружается на setContentView (), проблема возникает, когда он переходит в onResume (), который будет вызываться дважды.

В соответствии с жизненным циклом деятельности Android, после onPause ()->[onRestart ()-->onStart ()] - >onResume() будет вызываться, если приложение снова выйдет на передний план, а onResume () вызывается после onCreate () - >[onStart ()] при запуске.

но почему не вызывается один раз, если он все еще загружается на setContentView в onCreate() ?

Это то, что меня интересует, потому что я не хотел бы использовать логическое значение каждый раз, когда я использую карты, думая, что его можно выполнить дважды, чтобы избежать проблем, я.e двойное приращение a счетчик.

Я не знаю, является ли это проблемой эмулятора, как вопрос, который я видел о альбомно-портретной ориентации http://code.google.com/p/android/issues/detail?id=2423.

пожалуйста, взгляните на это:

  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>

вы можете воссоздать проблему:

  1. если вы установите точку останова в setContentView, а другой-в super.OnResume().
  2. выполнить и когда представление отладки.
  3. отправить в фоновом режиме приложение и повторно запустить его снова.
  4. завершите выполнение, вы увидите диалоговое окно, показывающее значение: 2.


прочитайте комментарии, сделанные Geobits и G. Blake Meike, эта часть является ответом, чтобы уточнить, если я ошибаюсь.

возможно, пример с картами был плохим из-за асинхронной загрузки карты. Я изменил MapsActivity на Activity, предположим, что телефон перегружен, поэтому 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));
}
}

Если я сверну приложение, когда журнал все еще печатает "спящий"..."и быстро я снова запускаю приложение, которое я вижу "спящий"...", 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): Sleeping...
  • 02-28 20:02:49.655: W / LocationActivity (651): Sleeping...
  • 02-28 20:02:50.678: W / LocationActivity (651): Sleeping...
  • 02-28 20:02:51.673: W / LocationActivity (651): Sleeping...
  • 02-28 20: 02: 52.674: W / LocationActivity (651): Спящий...
  • 02-28 20:02:53.738: W / LocationActivity (651): Sleeping...
  • 02-28 20:02:54.773: W / LocationActivity (651): Sleeping...
  • 02-28 20:02:55.795: W / LocationActivity (651): Sleeping...
  • 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): проверить мобильный Подключение
  • 02-28 20:02:57.134: W / LocationActivity (651): showingToast
  • 02-28 20:02:57.234: W / LocationActivity (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 все еще работает.

Если вместо тоста это диалог, из POV пользователя два диалога не приветствуются.

пожалуйста, выполните код так же, как и я, я достаточно упрям, чтобы не сдаваться :P

1 ответов


- Это дизайн. Если вы отправляете действие в background, это должны вызов onResume(), когда он вернется.

С документация:

имейте в виду, что система вызывает этот метод каждый раз, когда ваша деятельность выходит на передний план, в том числе, когда она создается в первый раз. Таким образом, вы должны реализовать onResume() для инициализации компонентов, освобождение в onPause() и выполнять любые другие инициализации, которые должно происходить каждый раз, когда действие переходит в возобновленное состояние (например, начать анимацию и инициализировать компоненты, используемые только в то время, когда действие имеет фокус пользователя).

также обратите внимание,setContentView() наверное, уже вернулся. Это не займет много времени, даже для MapView. Карта, вероятно, загружается асинхронно, поэтому она не связывает поток пользовательского интерфейса.