Почему метод 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>
вы можете воссоздать проблему:
- если вы установите точку останова в setContentView, а другой-в super.OnResume().
- выполнить и когда представление отладки.
- отправить в фоновом режиме приложение и повторно запустить его снова.
- завершите выполнение, вы увидите диалоговое окно, показывающее значение: 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
. Карта, вероятно, загружается асинхронно, поэтому она не связывает поток пользовательского интерфейса.