不了解setRetainInstance(或Xamarin Android中的RetainInstance)是如何工作的?

不了解setRetainInstance(或Xamarin Android中的RetainInstance)是如何工作的?,android,android-fragments,xamarin.android,Android,Android Fragments,Xamarin.android,如果在XML布局文件中声明了一些Fragment,那么看起来SetRetainInstance可以正常工作 但是,如果将片段动态加载到主活动的OnCreate回调中的某个容器中,该怎么办?我不明白在这种情况下,setRetainInstance意味着什么,或者可以做什么 查看此代码: protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); var f = new SomeFragment()

如果在XML布局文件中声明了一些
Fragment
,那么看起来
SetRetainInstance
可以正常工作

但是,如果将
片段
动态加载到主
活动
OnCreate
回调中的某个容器中,该怎么办?我不明白在这种情况下,
setRetainInstance
意味着什么,或者可以做什么

查看此代码:

protected override void OnCreate(Bundle bundle) {
    base.OnCreate(bundle);
    var f = new SomeFragment();
    var ft = FragmentManager.BeginTransaction();
    ft.Replace(Android.Resource.Id.Content, f);
    ft.Commit();
}
您可以看到,每次调用
OnCreate
时(例如当屏幕旋转时),都会创建一个新的
SomeFragment
,并填充活动的主要内容

现在,即使我声明了一个变量(字段),该变量包含对fragment实例的引用,并仅在它为null时创建它,如下所示:

SomeFragment f;
protected override void OnCreate(Bundle bundle) {
    base.OnCreate(bundle);
    if(f == null) {
        f = new SomeFragment(this);
        f.RetainInstance = true;
    }
    var ft = FragmentManager.BeginTransaction();
    ft.Replace(Android.Resource.Id.Content, f);
    ft.Commit();
}
static SomeFragment f;
这也不起作用,每次创建活动时,
f
字段最初仍然为空(未保留)。我在这里找到的唯一解决方案是将字段
f
声明为静态,如下所示:

SomeFragment f;
protected override void OnCreate(Bundle bundle) {
    base.OnCreate(bundle);
    if(f == null) {
        f = new SomeFragment(this);
        f.RetainInstance = true;
    }
    var ft = FragmentManager.BeginTransaction();
    ft.Replace(Android.Resource.Id.Content, f);
    ft.Commit();
}
static SomeFragment f;
有了它,我甚至不需要使用
RetainInstance
(或者Java中的
setRetainInstance
)。事实上,动态加载片段的需求非常普遍,因此在这一点上,
RetainInstance
似乎没有什么帮助


或者我在这里错过了一些简单的东西,仍然可以利用
RetainInstance
?问题是使用
RetainInstance
并动态加载片段,如果您在这里有一些解决方案或模式可供使用,请与我分享,谢谢

虽然我对Xamarin不熟悉,但我可以用Java回答这个问题

而不是使用

replace(int containerViewId, Fragment fragment)
你应该使用

replace(int containerViewId, Fragment fragment, String tag)
比如说,

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment;
fragment = (ExampleFragment) fragmentManager.findFragmentByTag("tag");
if(fragment == null)
    fragment = new ExampleFragment();
fragmentTransaction.replace(R.id.fragment_container, fragment, "tag");
fragmentTransaction.commit();

但只有在后台运行longe任务时,才应使用
setRetainInstance
。你可以看一看。更建议重新创建片段,因为它可以避免意外行为(例如,不初始化某些变量)。

是的,看起来它可以工作,因此对于您的解决方案,我们也不需要使用
setRetainInstance
(尽管目的似乎类似)。感谢您建议我们何时实际使用
setRetainInstance
。对于我的用例,我只需要管理所有打开的片段并在它们之间切换,而无需手动维护状态,并且每次切换到片段时都重新运行一些代码。好吧,我只是尝试了更多的体验,可以找到
片段
实例(某种保留)但是我们仍然需要使用
setRetainInstance
来防止重新创建片段(使用默认的无参数构造函数)。构造函数肯定会被调用,但不知何故它仍然是通过使用FragmentManager的标记找到的,视图的状态(例如某些EditText的文本)仍然保留,但是数据成员(在Fragment类中定义)不会保留。