Reputation: 26264
I need to test my apps lifecycle and its destruction and re-creation, because when the keyboard slides in/out (or is rotated), the app is destroyed and re-created. I also need to test for memory leaks when it does this.
I saw in the tutorial http://developer.android.com/tools/testing/activity_test.html#StateManagementTests
Terminate the activity and restart it:
mActivity.finish();
mActivity = this.getActivity();
However this is very simplified. My logging seems to indicate that calling finish() spawns a background thread with a different thread id which then calls onPause(), finish(), onStop(), and onDestroy(). I even tried getInstrumentation().waitForIdleSync();
to try to wait for that background thread to complete, but I still get race conditions when I test for expected values.
Not only that, but when it re-creates the Activity (when the 1st race condition doesn't occur or I comment out the assert), with getActivity(), then it just returns the exact same object that I just finished! I can tell because I log this
in my onXXX...() methods.
This differs from the orientation rotation / keyboard sliding app lifecycle, which always creates a new Activity object.
So how can I test this destruction / reincarnation scenario?
Upvotes: 1
Views: 289
Reputation: 26264
Ok I found it! It involves LOTs of waitForIdleSync() since it is multi-threaded to begin with, and setActivity(null). I could only get within +- 30% of the same memory. I would like to give credit to Peter Carpenter too, because his idea sped up my app and I would never have thought of that!
public void testMemoryLeaks() {
Log.e(TAG, "------------ testMemoryLeaks()");
getInstrumentation().waitForIdleSync();
System.gc();
Main mActivity = getActivity();
Log.d(TAG, "-- Extractor.stop() "+mActivity.getExtractor());
mActivity.getExtractor().stop();
getInstrumentation().waitForIdleSync();
System.gc();
long mem = Runtime.getRuntime().freeMemory();
Log.d(TAG, "-- freeMemory: " + mem);
Log.d(TAG, "-- mActivity.finish()");
mActivity.finish();
getInstrumentation().waitForIdleSync();
Log.d(TAG, "-- setActivity()");
setActivity(null);
getInstrumentation().waitForIdleSync();
System.gc();
Log.d(TAG, "-- getActivity()");
mActivity = getActivity();
assertTrue(mActivity != null);
Log.d(TAG, "-- Extractor.stop() "+mActivity.getExtractor());
mActivity.getExtractor().stop();
getInstrumentation().waitForIdleSync();
System.gc();
long memAfter = Runtime.getRuntime().freeMemory();
Log.d(TAG, "-- freeMemory: " + memAfter);
assertTrue("Memory leak", mem > memAfter * .70 && mem < memAfter * 1.30);
mActivity.finish();
getInstrumentation().waitForIdleSync();
Log.d(TAG, "-- end testMemoryLeaks()");
}
Upvotes: 0
Reputation: 679
The only way I know of to replicate the orientation change is to actually do it. (Keypad #7 key) Perhaps what you're really after is to prevent the app from being killed on orientation change.... ;) You can do this by overriding the onConfigurationChanged() function in your activity. see: http://developer.android.com/guide/topics/resources/runtime-changes.html
Upvotes: 1