OnCreateView调用两次

时间:2016-11-20 18:51:06

标签: c# android android-fragments android-activity xamarin

我正在尝试创建一个包含两个标签的活动,一个标注FragmentA,一个标记FragmentB。以下是我将片段添加到Activity:

的方法
[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", new FragmentA());
        AddTab("B", new FragmentB());
    }

    private void AddTab(string tabText, Fragment fragment)
    {
        var tab = ActionBar.NewTab();
        tab.SetText(tabText);
        tab.TabSelected += (sender, e) =>
        {
            e.FragmentTransaction.Replace(
                Resource.Id.fragmentContainer, 
                fragment);
        };
        ActionBar.AddTab(tab);
    }
}

当我旋转方向时,我想保持片段中的字段填充相同。我将数据保存在OnSaveInstanceState中并恢复OnActivityCreated中的数据。但是,我注意到每个旋转调用OnCreateViewOnActivityCreated方法两次。第一次包含我填写的Bundle,第二次包含的是null。

我认为我的错误出现在MyActivity课程中,但如果您需要更多信息,请告诉我们!

2 个答案:

答案 0 :(得分:1)

鉴于您在Activity.OnCreate()中创建了片段,您将始终有2次调用,因为在方法中创建了新的调用,并在base.OnCreate()中维护旧调用。您应该做的不是始终创建这些片段,而是可以通过标签或ID搜索现有片段,而是使用选项卡中的片段。

   protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.ConnectionMenu);
        ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;

        if(savedInstanceState == null)
        {
            AddTab("A", new FragmentA());
            AddTab("B", new FragmentB());
        }
        else 
        {
            Fragment a = (FragmentA)SupportFragmentManager.FindFragmentByTag("my_tag_a");
            Fragment b = (FragmentB)SupportFragmentManager.FindFragmentByTag("my_tag_b");
            AddTab("A", a);
            AddTab("B", b);
        }
    }

答案 1 :(得分:0)

我最终解决了这个问题。正如@JonDouglas所说,在创建新片段之前,您需要确保选项卡尚未加载。为此,可以使用标记从FragmentManager类加载片段。在TabSelected事件期间,如果先前未创建片段,则会创建一个新片段并使用该标记将其添加到事件FragmentTransaction。在TabUnselected事件期间,如果片段已创建,则它将被分离。

我还添加了Bundle值以保留最后一个活动标签。

以下是我用来解决问题的代码。

[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);
    }
}