Second instance of activity after orientation change
Asked Answered
A

1

6

I have a strange behaviour in my application on orientation change.

The normal behaviour:
When I open my app my home activity starts. When I go to the next activity (a gallery) it is started normally (with an sliding-in animation from right to left). When I go back using the back key, the current activity (the gallery) is finished (with an sliding-out animation from left to right).

The strange behaviour:

  • When I'm starting the app in portrait mode and change the orientation to landscape. Then there's something like a second instance of the home activity. Because then pressing the back button in landscape mode doesn't close the app like it would without orienation change (the home activity is the first activity in my app) but rahter make a sliding animation from left to right (like starting a new activity) and shows the home activity (but I think another instance) again. Pressing the back button a second time closes the app.
  • When I'm starting the app in landscape mode and change the orienation to portrait mode, press then the back button results in a slide animation from right to left (like closing an activity) and shows the home activity again.
  • When I start the app and make two orientation changes portrait-landscape-portrait, then the back button closes the app like it should be.

So it's like the landscape and the portrait mode are treated like two different activities.

I don't use android:configChanges="orientation|keyboardHidden|screenSize", so an orientation change should follow the normal android activity lifecycle and destroy the "old" portrait (or landscape) version of the activity.
My activites inherit from FragmentActivity. I'm using onSaveInstanceState to pass a parceable (which does not contain any reference to the activity) and I'm using onRetainCustomNonConfigurationInstance (read here) to pass several AsyncTasks. But all references in these tasks (if they have any) are destroyed in onRetainCustomNonConfigurationInstance and restored (with the newly created activity) after getLastCustomNonConfigurationInstance.

Any ideas what could cause this behaviour?

EDIT:
Activity Declaration in Manifest-File:
<activity android:name=".activities.smartphone.HomeSmartphone" android:label="@string/app_name"></activity>

HomeSmartphone extends Home
Home extends MyFragmentActivity
MyFragmentActivity extends android.support.v4.app.FragmentActivity

In MyFragmentActivity I just do some logging/tracking stuff in onCreate, onRestart, onStart, onSaveInstanceState, onPause, onResume, onStop, onDestroy by calling some static methods of a tracking class, which just holds a reference to the application context. Not to the activity context.

Home is an abstract class which is extended by HomeSmartphone and HomeTablet. These two classes do just some special loading/refreshing/initalizing in the different layouts.

The most task are done in the abstract Home class.



    public HomeRetainedObjects retained = new HomeRetainedObjects();

    public boolean adIsShown = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.home);

        Log.i("DEBUG", "onCreate(Home)");

        if (savedInstanceState != null) {
            this.adIsShown = savedInstanceState.getBoolean("adIsShown");
        }

    // write/update values in shared preferences
        this.initPreferences();

    // recover retained objects (mostly AsyncTasks)
        this.recoverRetained();

    // show content / refresh content
        this.init();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putBoolean("adIsShown", this.adIsShown);

        Log.i("DEBUG", "onSaveInstanceState(Home)");
    }

    public void recoverRetained() {
        Object retained = this.getLastCustomNonConfigurationInstance();
        if (retained instanceof HomeRetainedObjects) {
            this.retained = (HomeRetainedObjects) retained;

            if (this.retained.loadMessageTask != null) {
                this.retained.loadMessageTask.restoreContext(this);
            }
        }
    }

    @Override
    public Object onRetainCustomNonConfigurationInstance() {
        if (this.retained.loadMessageTask != null) {
            this.retained.loadMessageTask.destroyContext();
        }

        return this.retained;
    }

I hope this helps?!

Annual answered 5/3, 2012 at 20:56 Comment(2)
... including the Activity declaration in your manifest, plz.Burgin
+1 for a well posed question which show us your efforts :)Derogate
B
0

I ran into a similar issue, and it appears the cause of your problems is overriding onRetainCustomNonConfigurationInstance().

I reviewed my retention state object, and found that it was holding a reference to a Context. I wrapped it in a WeakReference and the normal behavior returned and no strange double instances lingered about.

Perhaps your retention state is also holding a reference to a Context?

Ballistics answered 31/8, 2012 at 19:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.