0

I have an abstract base class for activities which instantiate exactly one fragment:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/fragmentContainer" android:layout_width="match_parent" android:layout_height="match_parent" >
</FrameLayout>


public abstract class SingleFragmentActivity extends Activity {
    protected abstract Fragment createFragment();

    private Fragment m_fragment;
    public Fragment getSingleFragment() { return m_fragment; }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);

        FragmentManager fm = getFragmentManager();
        m_fragment = fm.findFragmentById( R.id.fragmentContainer );
        Log.d("SingleFragment", "fetching a fragment");
        if ( m_fragment == null ) {
            Log.d("SingleFragment", "SingleFragment requires creating a new one");
            m_fragment = createFragment();
            fm.beginTransaction().add( R.id.fragmentContainer, m_fragment ).commit();
        } else {
            Log.d("SingleFragment", "SingleFragment reusing one from fragment manager");
        }
    }
}

...plus a simple activity and fragment:

public class LoginActivity extends SingleFragmentActivity {
    private static final String TAG = "LOGIN ACTIVITY";

    private LoginFragment m_loginFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.d(TAG,"onCreate");
        super.onCreate(savedInstanceState);

        m_loginFragment = (LoginFragment) getSingleFragment();
        Log.d(TAG,"...login fragment foo = "+m_loginFragment.getFoo());
        m_loginFragment.setFoo( "Here's a new foo");
    }

    @Override
    public void onPause() { super.onPause(); Log.d(TAG,"onPause"); }

    @Override
    public void onDestroy() { super.onDestroy(); Log.d(TAG,"onDestroy"); }

    @Override
    public void onResume() { super.onResume(); Log.d(TAG,"onResume"); }


    @Override
    protected Fragment createFragment() {
        Log.d(TAG,"createFragment()");
        return new LoginFragment();
    }
}

public class LoginFragment extends Fragment {
    private static final String TAG = "LOGIN FRAGMENT";

    private String foo = "not set yet";
    public String getFoo() { return foo; }
    public void setFoo(String s) { foo = s; }

    @Override
    public void onCreate( Bundle savedInstanceState ) {
        super.onCreate(savedInstanceState);
        Log.d(TAG,"onCreate");
    }

    @Override
    public void onPause() { super.onPause(); Log.d(TAG,"onPause"); }

    @Override
    public void onDestroy() { super.onDestroy(); Log.d(TAG,"onDestroy"); }

    @Override
    public void onResume() { super.onResume(); Log.d(TAG,"onResume"); }
}

If I run this code, and rotate the phone after it launches, I see the following log:

08-07 15:02:51.310: LOGIN ACTIVITY: onCreate
08-07 15:02:51.340: SingleFragment: fetching a fragment
08-07 15:02:51.340: SingleFragment: SingleFragment requires creating a new one
08-07 15:02:51.340: LOGIN ACTIVITY: createFragment()
08-07 15:02:51.340: LOGIN ACTIVITY: ...login fragment foo = not set yet
08-07 15:02:51.340: LOGIN FRAGMENT: onCreate
08-07 15:02:51.340: LOGIN ACTIVITY: onResume
08-07 15:02:51.340: LOGIN FRAGMENT: onResume
08-07 15:02:59.799: LOGIN FRAGMENT: onPause
08-07 15:02:59.799: LOGIN ACTIVITY: onPause
08-07 15:02:59.809: LOGIN FRAGMENT: onDestroy
08-07 15:02:59.809: LOGIN ACTIVITY: onDestroy
08-07 15:02:59.829: LOGIN ACTIVITY: onCreate
08-07 15:02:59.829: LOGIN FRAGMENT: onCreate
08-07 15:02:59.869: SingleFragment: fetching a fragment
08-07 15:02:59.869: SingleFragment: SingleFragment reusing one from fragment manager
08-07 15:02:59.869: LOGIN ACTIVITY: ...login fragment foo = not set yet
08-07 15:02:59.869: LOGIN ACTIVITY: onResume
08-07 15:02:59.869: LOGIN FRAGMENT: onResume

Everything works as expected: rotating the phone causes activity and fragment to be destroyed and recreated; I see the fragment manager restores something, but my question is "what?" The member variable foo is not retained, so what is it that is being restored?

tshepang
  • 12,111
  • 21
  • 91
  • 136

1 Answers1

0

Me too had the same problem, and posted a question sometimes ago - After screen rotation, findFragmentById() returns a fragment, even if there's no such ID inside the layout

At that time, the documentation at http://developer.android.com/training/basics/fragments/creating.html was mentioning this:

When a configuration change causes the activity hosting these fragments to restart, its new instance may use a different layout that doesn't include the same fragments as the previous layout. In this case all of the previous fragments will still be instantiated and running in the new instance. However, any that are no longer associated with a tag in the view hierarchy will not have their content view created and will return false from isInLayout(). (The code here also shows how you can determine if a fragment placed in a container is no longer running in a layout with that container and avoid creating its view hierarchy in that case.)

Now this part doesn't exist on that document.

You can check with isInLayout() if this fragment is already added to the layout.

Community
  • 1
  • 1
Vishnu Haridas
  • 7,355
  • 3
  • 28
  • 43