Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android. Fragment stays in activity after screen rotation issue

I have a two variants of activity_main.xml (for portrait/landscape orientation). In this activity, user can choose items and browse detailed information about selected item.

In portraint orientation, fragments added to flFragmentContainer dynamically, after item choosing, details fragment replaces list fragment:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/flFragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></FrameLayout>
</LinearLayout>

In landscape orientation, fragments described in XML file statically:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
        <fragment
            android:id="@+id/frgTaskList"
            android:name="com.exprod.xchecklist.fragments.TaskListFragment"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            tools:layout="@layout/fragment_task_list" />
        <fragment
            android:id="@+id/frgTaskDetails"
            android:name="com.exprod.xchecklist.fragments.TaskDetailsFragment"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            tools:layout="@layout/fragment_task_details">
        </fragment>
    </LinearLayout>
</LinearLayout>

Here is the code of onCreate() method (of MainActivity).

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentManager fragmentManager = getSupportFragmentManager();
        TaskDetailsFragment taskDetailsFragment = (TaskDetailsFragment)fragmentManager.findFragmentById(R.id.frgTaskDetails);
        isDynamicMode = taskDetailsFragment == null || !taskDetailsFragment.isInLayout();
        if(isDynamicMode){
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            Fragment taskListFragment = new TaskListFragment();
            if (savedInstanceState == null) {
                transaction.add(R.id.flFragmentContainer, taskListFragment, TaskListFragment.FRAGMENT_TAG);
            }else{
                transaction.replace(R.id.flFragmentContainer, taskListFragment, TaskListFragment.FRAGMENT_TAG);
            }
            transaction.commit();            
        }
    }

PROBLEM: When I rotate device to landscape orientation, I get twice calls of creation methods in first fragment (TaskListFragment) (onCreateView(), onActivityCreated(), ... ). This indicates that the old fragment remains in activity and recreated on orientation change. How I can finally destroy old fragment?? I did not find the answer on the Internet.

P.S: Sorry for my bad English...

like image 356
V. Moroz Avatar asked Nov 27 '22 03:11

V. Moroz


1 Answers

I see at least two approaches to do what you want.

Handle orientation change yourself:

As described in this document, you can prevent automatic Activity destroy and re-creation and handle orientation change yourself. In this case, you would remove the old Fragment before inflating a new layout into Activity.

Remove the old Fragment after Activity re-creation:

You could also add some logic that determines the orientation as described here (or use your current heuristic that sets isDynamicMode), and manually remove the unnecessary Fragments during onCreate().

The better way:

Although it is possible to do what you want, I can't undertand why would you like to do it this way - you use TaskListFragment in both portrait and landscape configurations, therefore the most logical thing to do is to reuse it. Except for simplifying things, it will also let you keep the state of that Fragment on orientation change (which, I believe, is desirable in your case).

like image 142
Vasiliy Avatar answered Dec 04 '22 13:12

Vasiliy