48

我在 Honeycomb 中开发了一个应用程序,我正在使用片段。
这是我的应用

  • 我有一个活动(说 A1),其中有一个片段
  • 最初这个片段持有对象一个片段对象说(F1)
  • 然后根据用户操作,它可能会更改为其他对象 F2、F3 ....

我的问题是什么

当用户旋转设备时,将重新创建活动,并使 F1 作为片段对象,即使在旋转之前它不是 我使用的,但它对我不起作用 我已经通过代码在我的函数中添加了片段,就像这样
What is the way to retain the fragment object while rotating?
setRetainInstance(true);
onCreate

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);

   FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();

   Fragment homeFragment = new Home();
   fragmentTransaction.add(R.id.mainFragement, homeFragment);
   fragmentTransaction.commit();
}
4

6 回答 6

69

默认情况下,Android 将保留片段对象。在您的代码中,您正在设置homeFragment函数onCreate。这就是为什么你设置的总是一些homeFragment或任何东西。flonCreate

因为每当您旋转时, onCreate 都会执行并将您的片段对象设置为第一个

因此,对您来说最简单的解决方案是检查savedInstanceStatebundle 是否为 null 并设置片段对象

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(null == savedInstanceState) {
        // set you initial fragment object 
    }
 }
于 2011-03-02T08:14:52.130 回答
41

你需要给你的 Fragment 一个唯一的标签,并检查这个 Fragment 是否已经添加到你的 Activity 中。

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    String tag = "my_fragment";
    FragmentManager fragmentManager = getFragmentManager();
    if(fragmentManager.findFragmentByTag(tag) == null) {
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        Fragment homeFragment = new Home();
        fragmentTransaction.add(R.id.mainFragement, homeFragment, tag);
        fragmentTransaction.commit();
    }
}

检查是否savedInstanceState为 null 不是检查您的片段是否已设置的安全方法 - 它在大多数情况下都可以工作,但在某些情况下(例如当设备内存不足时),Android 可能会杀死您的 Activity,这可能会中断你的申请。

要查看实际情况,请在设备的开发选项中勾选“不保留活动”(该设置在 Android 4.0+ 中可用,不确定早期版本)。当您打开一个新活动时,您的第一个活动将被销毁。当您返回它(通过按回)时,它会再次创建,并且 savedInstanceState为空。但是,您的片段不再在活动中,您必须再次添加它。

编辑 - 显示原始原理,但使用 SupportFragmentManager

public class ActivityAwesome extends AppCompatActivity
{
    private final String TAG = getClass().getSimpleName();
    private FragmentHome mHomeFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_layout);

        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(TAG);
        if(fragment == null)
        {
            // Create the detail fragment and add it to the activity using a fragment transaction.
            mHomeFragment = new FragmentHome();
            fragmentManager.beginTransaction()
                    .add(R.id.fragment_container, mHomeFragment, TAG)
                    .commit();
        }
        else
        {
            // get our old fragment back !
            mHomeFragment = (FragmentHome)fragment;
        }
    }
}

mHomeFragment如果您想在旋转设备后操纵片段(在这种情况下),这将特别有用

于 2012-11-02T09:44:52.510 回答
3

onAttachFragment()在您中使用Activity以重新分配对象:

@Override
public void onAttachFragment(Fragment fragment) {
    if (fragment instanceof MyFragment)
        this.myFragment = (MyFragment) fragment;
}
于 2015-01-26T17:07:28.477 回答
0

Fragment在活动的布局onSaveInstanceState中定义了一个,Fragment确实被调用了,但savedInstanceState Bundle片段中的onCreatView为空。

原因是我Fragment在 XML 中没有 ID:

android:id="@+id/compass_fragment" ...
于 2013-04-13T23:23:54.817 回答
0

只需重新布线@Ralf 答案以使其更具动态性,无需指定要保留的某个片段,但如果您想指定,也可以:

 public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //set Home/Main/default fragment
        changeFragmentTo(HomeFragment.newInstance(), FRAGMENT_TAG_HOME_FRAGMENT);


        if (getCurrentFragment() != null) {
            //if screen rotated retain Fragment
            changeFragmentTo(getCurrentFragment(), getCurrentFragment().getTag());

        }

    }


    private Fragment getCurrentFragment() {
//fl_main_container is FarmeLayout where I load my Fragments
        return getSupportFragmentManager().findFragmentById(R.id
                .fl_main_container);
    }



    /**
     * changeFragmentTo(Fragment fragmentToLoad, String fragmentTag)
     *
     * @param fragmentToLoad : dataType > v4.app.Fragment :: the object of the fragment you want to load in form of MyFragment() or MyFragment().newInstance()
     * @param fragmentTag    :  dataType > String :: a String which identify the "tag" of the fragment in form of "FRAGMENT_TAG_MY_FRAGMENT", Value must be stored in {@link models.MyConstants}
     */


    public void changeFragmentTo(Fragment fragmentToLoad, String fragmentTag) {

        if (getSupportFragmentManager().findFragmentByTag(fragmentTag) == null) {
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.fl_main_container, fragmentToLoad, fragmentTag)
                    .setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .addToBackStack(fragmentTag)
                    .commit();

        } else {
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.fl_main_container, fragmentToLoad, fragmentTag)
                    .setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .commit();
        }
    }



}
于 2019-04-14T05:37:28.890 回答
-1

您可以简单地在片段类中设置RetainInstance属性。OnCreate

public override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    RetainInstance = true;
}

旋转时保留 Fragment 对象

于 2018-04-26T20:40:30.467 回答