I am developping an Android app and in one of the activities I am using the MapsActivity to show a Map. What I have seen is that on an 2.2 (API8) emulator it takes some time to load the map and I have time to press the menu button and then come back to the app and it is still loading on the setContentView(), the problem comes when it goes to onResume() which is gonna be called twice.
According to the lifecycle of an Android activity, after a onPause()->[onRestart()-->onStart()]-->onResume() is gonna be called if the app comes to the foreground again, and onResume() is called after onCreate()->[onStart()] when is launched.
But why is not called once if the it is still loading on setContentView in onCreate() ?
This is something that interest me because I would not like to use a boolean each time I use maps thinking that it could be executed twice to avoid problems, i.e a double incrementation of a counter.
I do not know if it is a problem of the emulator as the issue I have seen about 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 issue:
Read the comments done by Geobits and G. Blake Meike, this part is an answer just to clarify if I am wrong.
Maybe the example with maps was a bad one because of the asyncronous load of the map. I changed the MapsActivity for an Activity, let's suppose that the phone is overloaded, so onCreate is gonna execute a loop of 8 seconds (not enougth time for an Android Not Responding).
And here the new code using a light android layout:
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 minimize the app when the log is still printing "Sleeping..." and quickly I re-run the app I can see the "Sleeping...", onResume will check two times the Connectivity (this is a correct way of checking the network connectivity).
Here goes the logCat:
Toast will show two times the message.
Looking at the logCat the lifecycle is correct, but I just want to take into consideration that sometimes onCreate could be delayed because of an overloaded system and if onResume is executed twice then I have to take care of some initializations, so I have to use booleans which I consider I should not use because the onCreate was still running.
If instead of a Toast it is a dialog, from the POV of the user two dialogs are not welcome.
Please execute the code in the same way as I do, I am stubborn enough to not give up :P
onResume() will never be called before onCreate() . Show activity on this post. onResume() will always be called when the activity goes into foreground, but it will never be executed before onCreate() .
onResume() is triggered twice, but when I remove requestWindowFeature() , it's only called once.
onResume() When the activity enters the Resumed state, it comes to the foreground, and then the system invokes the onResume() callback. This is the state in which the app interacts with the user. The app stays in this state until something happens to take focus away from the app.
onResume() is called whenever you navigate back to the activity from a call or something else. You can override the onResume method similarly as onCreate() and perform the task.
This is by design. If you send the activity to background, it must call onResume()
when it returns.
From the documentation:
Be aware that the system calls this method every time your activity comes into the foreground, including when it's created for the first time. As such, you should implement onResume() to initialize components that you release during onPause() and perform any other initializations that must occur each time the activity enters the Resumed state (such as begin animations and initialize components only used while the activity has user focus).
Also note, setContentView()
has probably already returned. It shouldn't take long, even for a MapView
. The map is probably loaded asynchronously, so it doesn't tie up the UI thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With