Issue
I wanted to understand the interaction between activity lifecycle and fragment lifecycle in Android, so I decided to start a new project and copy code from this page.
I then thought that to improve my comprehension it would be useful to test it on a tablet, switch its orientation and see what it happens (although maybe it was not intended for this).
Through logcat I kept track of the main events that are fired both on the activity and on the country fragment, for example in Activity Oncreate I write:
Log.d("TAG", "Activity: 1.onCreate");
This is what I get when I start from the portrait view and then rotate:
TAG: Activity: 1.onCreate
TAG: Activity: 2.onStart
TAG: ## ContryFrag: 1.onAttach
TAG: ## ContryFrag: 2.onCreateView
TAG: ## ContryFrag: 3.onStart
TAG: Activity: 3.onResume
TAG: ## ContryFrag: 4.onResume
TAG: Activity: -3.onPause
TAG: ## ContryFrag: -4.onPause
TAG: Activity: -2.onStop
TAG: ## ContryFrag: -3.onStop
TAG: Activity: -1.onDestroy
TAG: ## ContryFrag: -2.onDestroyView
TAG: ## ContryFrag: -1.onDetach
TAG: Activity: 1.onCreate
TAG: ## ContryFrag: 1.onAttach
TAG: ## ContryFrag: 1.onAttach
TAG: ## ContryFrag: 2.onCreateView
TAG: Activity: 2.onStart
TAG: ## ContryFrag: 2.onCreateView
TAG: ## ContryFrag: 3.onStart
TAG: ## ContryFrag: 3.onStart
TAG: Activity: 3.onResume
TAG: ## ContryFrag: 4.onResume
TAG: ## ContryFrag: 4.onResume
It seems that the fragment that was added via the FragmentManager in the portrait view is still recreated after rotation, despite it was detached before. The event chain to resume it is followed again, even if it won’t be displayed.
Can you help me understand what is happening here?
EDIT
When I check if the fragment isInLayout()
Log.d("TAG", "## ContryFrag: 1.onAttach /" + isInLayout() );
I realize that there are two fragments after rotation: one created with the rotation and a second one who seem to be a remainder of the previous activity (which shouldn't be).
TAG: Activity: 1.onCreate
TAG: ## ContryFrag: 1.onAttach /false
TAG: ## ContryFrag: 1.onAttach /true
TAG: ## ContryFrag: 2.onCreateView /true
TAG: Activity: 2.onStart
TAG: ## ContryFrag: 2.onCreateView /false
TAG: ## ContryFrag: 3.onStart /false
TAG: ## ContryFrag: 3.onStart /true
TAG: Activity: 3.onResume
TAG: ## ContryFrag: 4.onResume /false
TAG: ## ContryFrag: 4.onResume /true
EDIT 2
This is the dummy code I used to get onSelectedCountry(String country), which is not provided:
public void onSelectedCountry(String country)
{
String[] x = {country, "city0", "city1", "city2", "city3", "city4", "city5"};
adapter.clear();
adapter.addAll(x);
}
EDIT 3
Here is my code. Sorry for the delay, it was the first time I used github.
Solution
Once you add a Fragment to the FragmentManager, it remains there until either you remove it manually or until the Activity permanently finishes. (Restarting an Activity such as what occurs when the device rotates does not cause it to Finish)
Rotating the device does not clear the Fragments. If you create a new Fragment and add it to the FragmentManager at any time in the Activity Lifecycle without first checking if the Fragment already exists in the FragmentManager, you will simply add a new Fragment every time you do anything that causes the Activity to be restarted.
For example, this code should only allow one copy of your fragment to be added.
protected void onResume() {
String TAG = "COUNTRYFRAG";
CountryFrag f = (CountryFrag) getSupportFragmentManager().findFragmentByTag(TAG);
if (f == null) {
f = new CountryFrag();
getSupportFragmentManager().beginTransaction()
.add(f, TAG)
.commit();
}
int count = getSupportFragmentManager().getFragments().size();
Log.v("FRAGS", "There are " + count + "fragments in the fragment manager.");
}
whilst this one will add a new one every time you rotate the device.
protected void onResume() {
String TAG = "COUNTRYFRAG";
CountryFrag f = new CountryFrag();
getSupportFragmentManager().beginTransaction()
.add(f, TAG)
.commit();
int count = getSupportFragmentManager().getFragments().size();
Log.v("FRAGS", "There are " + count + "fragments in the fragment manager.");
}
The code at the link seems to be using the presence of savedInstanceState to determine whether to add the Fragment or whether to return from the method. This is not reliable as you may not be saving anything in the state and therefore it could always be null. It is better to specifically check if you have already added the Fragment.
i.e
if (savedInstanceState != null)
return;
Answered By - Kuffs
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.