The following process is easy to understand and reproduce, but leads to an error:
- activityA starts action B in its
onCreate() method - activityB is created and I call
finish() on my onResume () method - activityB
onDestroy() is called - activityA
onResume() is called - and here, in activityA, I press the menu button to call
finish() - or press the return key. - activityA is deleted, but
onDestroy() NOT called and A is still alive (adp shell dumpsys "myPackageName" indicates too many live actions).
code
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="gleroy.com.algo"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:name=".activity.MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="gleroy.com.algo.activity.FakeA" android:label="@string/app_name"></activity> <activity android:name="gleroy.com.algo.activity.FakeB" android:label="@string/app_name"></activity> </application> </manifest>
Action A:
public class FakeA extends Activity { private final static String TAG = FakeA.class.getCanonicalName(); @Override protected void onCreate(Bundle savedInstanceState) { Log.d(TAG, "onCreate, taskId :" + getTaskId()); super.onCreate(savedInstanceState); Intent intent = new Intent(FakeA.this, FakeB.class); startActivity(intent); } @Override protected void onResume() { Log.d(TAG, "onResume"); super.onResume(); } @Override protected void onDestroy() { Log.d(TAG, "onDestroy"); super.onDestroy(); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override public boolean onCreateOptionsMenu(Menu menu) {
Activity B:
public class FakeB extends Activity { private final static String TAG = FakeB.class.getCanonicalName(); @Override protected void onCreate(Bundle savedInstanceState) { Log.d(TAG, "onCreate, taskId :"+getTaskId()); super.onCreate(savedInstanceState); } @Override protected void onResume() { super.onResume(); Log.d(TAG, "onResume, isFinishing :" + isFinishing()); finish(); } @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); } }
Action A is launched from MainActivity, which contains a simple button:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, FakeA.class); startActivity(intent); } });
So, I know that we cannot be sure what we will call onDestroy() , but here my ActivityA is clearly onDestroy() .
I also noticed that if I use Timer and TimerTask to delay startActivity in ActivityA or finish() in ActivityB, then I no longer have this error.
Here are the events:
- FakeA onCreate, taskId: 154
- Fakea onresume
- FakeA onPause, isFinishing: false
- FakeB onCreate, taskId: 154
- FakeB onResume, isFinishing: false
- Fakea onresume
- Fakeb ondestroy
- end a call or press the return key: FakeA onPause, isFinishing: true
source share