I am developing an Android application and in one of the activities that I use MapsActivity to show a map. I saw that on emulator 2.2 (API8) it takes some time to load the map, and I have time to press the menu button and then return to the application and still load setContentView (), the problem comes when it goes to onResume ( ), which will be called twice.
According to the Android activity life cycle, after onPause () β [onRestart () β onStart ()] β onResume () will be called if the application reappears in the foreground and onResume () is called after onCreate () β [onStart ()] at startup.
But why isn't it called once if it still loads on setContentView in onCreate ()?
This is what interests me, because I would not want to use a boolean every time I use cards, thinking that it can be executed twice to avoid problems, i.e. double increase counter.
I donβt know if the emulator problem is a problem that I saw in the landscape portrait orientation http://code.google.com/p/android/issues/detail?id=2423 .
Please take a look at this:
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>
You can re-create the problem:
- If you set a breakpoint in setContentView another in super.OnResume ().
- Run and view debugging.
- Put the app in the background and run it again.
- Complete the execution, you will see a dialog box showing the value: 2.
Read the comments made by Geobits and G. Blake Meike, this part is only an answer to clarify if I am wrong.
Perhaps the map example was bad due to the asynchronous loading of the map. I changed MapsActivity for Activity, let's say that the phone is overloaded, so onCreate will execute a cycle of 8 seconds (no latency for Android does not respond).
And here is the new code using the lightweight layout for 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)); } }
If I hide the application when the log still prints "Sleeping ..." and I quickly launch the application, I can see "Sleeping ...", onResume will check the connection twice (this is the correct way to check the network connection).
Here goes 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): Sleeping ...
- 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): check your mobile connection
- 02-28 20: 02: 57.134: W / LocationActivity (651): showToast
- 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): check your mobile connection
- 02-28 20: 02: 57.324: W / LocationActivity (651): showToast
The toast will show the message twice.
Looking at logCat, the life cycle is correct, but I just want to take into account that sometimes onCreate can be delayed due to an overloaded system, and if onResume is executed twice, then I have to take care of some initializations, so I have to use boolean elements, which, in my opinion, I should not use, because onCreate still works.
If instead of Toast this is a dialog, from the user's POV two dialogs are not welcome.
Please execute the code just like me, I'm stubborn enough not to give up: P