Fragment Oncreateview and Onactivitycreated Called Twice

Fragment onCreateView and onActivityCreated called twice

Ok, Here's what I found out.

What I didn't understand is that all fragments that are attached to an activity when a config change happens (phone rotates) are recreated and added back to the activity. (which makes sense)

What was happening in the TabListener constructor was the tab was detached if it was found and attached to the activity. See below:

mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
if (mFragment != null && !mFragment.isDetached()) {
Log.d(TAG, "constructor: detaching fragment " + mTag);
FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
ft.detach(mFragment);
ft.commit();
}

Later in the activity onCreate the previously selected tab was selected from the saved instance state. See below:

if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
Log.d(TAG, "FragmentTabs.onCreate tab: " + savedInstanceState.getInt("tab"));
Log.d(TAG, "FragmentTabs.onCreate number: " + savedInstanceState.getInt("number"));
}

When the tab was selected it would be reattached in the onTabSelected callback.

public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (mFragment == null) {
mFragment = Fragment.instantiate(mActivity, mClass.getName(), mArgs);
Log.d(TAG, "onTabSelected adding fragment " + mTag);
ft.add(android.R.id.content, mFragment, mTag);
} else {
Log.d(TAG, "onTabSelected attaching fragment " + mTag);
ft.attach(mFragment);
}
}

The fragment being attached is the second call to the onCreateView and onActivityCreated methods. (The first being when the system is recreating the acitivity and all attached fragments) The first time the onSavedInstanceState Bundle would have saved data but not the second time.

The solution is to not detach the fragment in the TabListener constructor, just leave it attached. (You still need to find it in the FragmentManager by it's tag) Also, in the onTabSelected method I check to see if the fragment is detached before I attach it. Something like this:

public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (mFragment == null) {
mFragment = Fragment.instantiate(mActivity, mClass.getName(), mArgs);
Log.d(TAG, "onTabSelected adding fragment " + mTag);
ft.add(android.R.id.content, mFragment, mTag);
} else {

if(mFragment.isDetached()) {
Log.d(TAG, "onTabSelected attaching fragment " + mTag);
ft.attach(mFragment);
} else {
Log.d(TAG, "onTabSelected fragment already attached " + mTag);
}
}
}

Why is my onCreateView method being called twice?

Looks like you're adding the fragment twice. If you declare it in the xml then you don't need to add it programmatically as well.

You can remove this from your Activity's onCreate():

if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new AddCourseFragment()).commit();
}

Android fragment OnCreateView called twice

I am using a FragmentPagerAdapter with fragments. My problem is that
when I call setCurrentItem, the OnCreateView method of the fragment
that is being loaded is called twice. It is important to note however
that the fragment is not recreated, it is simply resumed. I am
desperate to find a solution that causes OnCreateView to only be
called once.

It is not called twice. What you are experiencing is the default behavior of the ViewPager, which caches always at least one of its page (Fragment), depending of the value of setOffscreenPageLimit(int limit). So onCreateView is called once for each instance returned by getItem

OnCreateView Called twice

I ended up solving the issue. as @JonDouglas said you need to make sure the tab wasn't already loaded before creating a new fragment. To do this the fragment can be loaded from the FragmentManager class using a tag. During the TabSelected event if the fragment was not previously create, a new fragment is created and added to the event FragmentTransaction using the tag. During the TabUnselected event, if the fragment was created then it is detached.

I also added in a Bundle value to hold onto the last active tab.

Here is the code I used to solve the issue.

[Activity(Label = "My App")]
public class MyActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.ConnectionMenu);
ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
AddTab("A", "a_fragment", () => new FragmentA());
AddTab("B", "b_fragment", () => new FragmentB());
if (savedInstanceState != null)
{
var selectedTab = savedInstanceState.GetInt(
"ActionBar.SelectedNavigationIndex", 0);
ActionBar.SetSelectedNavigationItem(selectedTab);
}
}

protected override void OnSaveInstanceState(Bundle savedInstanceState)
{
base.OnSaveInstanceState(savedInstanceState);
savedInstanceState.PutInt(
"ActionBar.SelectedNavigationIndex",
ActionBar.SelectedNavigationIndex);
}

private void AddTab<TFragment>(
string tabText,
string tag,
Func<TFragment> ctor) where TFragment : Fragment
{
var tab = ActionBar.NewTab();
tab.SetText(tabText);
tab.SetTag(tag);
var fragment = FragmentManager.FindFragmentByTag<TFragment>(tag);
tab.TabSelected += (sender, e) =>
{
if (fragment == null)
{
fragment = ctor.Invoke();
e.FragmentTransaction.Add(
Resource.Id.fragmentContainer,
fragment,
tag);
}
else
{
e.FragmentTransaction.Attach(fragment);
}
};
tab.TabUnselected += (sender, e) =>
{
if (fragment != null)
{
e.FragmentTransaction.Detach(fragment);
}
};
ActionBar.AddTab(tab);
}
}

Android oncreateview called twice

I figure out what was my problem.

When I was doing:

case FRAGMENT_OPTION2:
fragment = ControlPanelFragment.newInstance();
break;

I was creating a fragment and when I rotated the screen selectItem(int position) was again called so a new instance of the same object was created thus the steps 7 and following. The solution was to check if the fragment was already created and use him instead of creating a new one.
I've saved the initial fragment with a tag and them looked for that tag. If the tag existed, use that fragment otherwise create a new one.

public void selectItem(int position) {
Fragment fragment = null;
switch (position) {
case FRAGMENT_OPTION1:
...
break;
case FRAGMENT_OPTION2:
fragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(position));
if (fragment == null) {
fragment = ControlPanelFragment.newInstance();
}
break;
...
case FRAGMENT_OPTIONN:
...
return;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.fragment_container, fragment,
String.valueOf(position)).commitAllowingStateLoss();
}
}

Android fragment onCreate called twice

I think the Android team in charge of the documentation should really do a better job. I went ahead and just removed the SearchManager from the SearchViewand use the onQueryTextListener directly, only to see that with this approach I also get my listener called twice. But thanks to this post, I saw that apparently it's a bug with the emulator (or with the way SearchView handles the submit event). So if I press the OSK enter button everything works as expected.

Thanks everyone for their help!

onCreate() called twice on configuration change in Fragment with ViewPager

You need to make sure you're not adding your MainFragment a second time after the configuration change. You should update your Activity to look like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

if (savedInstanceState != null) {
return;
}

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, new MainFragment());
fragmentTransaction.commit();
}

The reason for this is that the Activity itself already has a record of the MainFragment being added and will automatically restore it after a configuration change. If you perform the same transaction again, first you'll see the restored MainFragment starting up, then its going to get replaced by the new one from the new Fragment transaction and a new, different MainFragment is going to go through its own initialization process. That results in what appears to be multiple calls to onCreate for MainFragment.



Related Topics



Leave a reply



Submit