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 SearchView
and 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
How to Know My Android Application Has Been Upgraded in Order to Reset an Alarm
What Is the Intent of the Methods Getitem and Getitemid in the Android Class Baseadapter
Where to Find Info on Android's "Service Call" Shell Command
Detect When Recyclerview Reaches the Bottom Most Position While Scrolling
Compiling the Latest Openssl for Android
Is Secure.Android_Id Unique for Each Device
How to Create a Relativelayout Programmatically with Two Buttons One on Top of the Other
How to Change the Fontsize in an Android Webview
The Import Android.Support.V7 Cannot Be Resolved
Android: How to Change Checkbox Size
Tabhost with Fragments and Fragmentactivity
How to Limit the Height of Spinner Drop Down View in Android
How to Get the Android Path String to a File on Assets Folder
Proguard: Can't Find Referenced Class Com.Google.Android.Gms.R