我在Honeycomb开发了一个应用程序,我正在使用片段 这是我的应用
我的问题是什么
当用户旋转设备时,重新创建活动并将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();
}
答案 0 :(得分:61)
默认情况下,Android会保留片段对象。在您的代码中,您在homeFragment
函数中设置了onCreate
。这就是为什么在homeFragment
中设置的fl
或onCreate
总是如此。
因为无论何时旋转,onCreate都会执行并将您的片段对象设置为第一个
所以简单的解决方案是检查savedInstanceState
bundle是否为null并设置片段对象
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(null == savedInstanceState) {
// set you initial fragment object
}
}
答案 1 :(得分:38)
您需要为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
是否为空并不是检查您的片段是否已设置的安全方法 - 在大多数情况下它会起作用,但在某些情况下(例如当设备处于低内存时),Android可以杀死你的活动,这可能会破坏你的申请。
要查看此操作,请在设备的开发选项中选中“不要保留活动”(此设置在Android 4.0及更高版本中可用,不确定早期版本)。当您打开新活动时,您的第一个活动将被销毁。当您返回它(通过按回)时,它会再次创建,savedInstanceState 不 null。但是,您的片段不再存在于活动中,您必须再次添加它。
编辑 - 显示原始原则,但使用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
),这会非常有用
答案 2 :(得分:3)
在onAttachFragment()
中使用Activity
重新分配对象:
@Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof MyFragment)
this.myFragment = (MyFragment) fragment;
}
答案 3 :(得分:0)
我在活动的布局中定义了Fragment
,onSaveInstanceState
中的Fragment
会被调用,但片段{{1}中的savedInstanceState
Bundle
来自null。
原因是我的onCreatView
在XML中没有ID:
Fragment
答案 4 :(得分:0)
您只需在片段类的RetainInstance
内设置OnCreate
属性即可。
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
RetainInstance = true;
}
答案 5 :(得分: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();
}
}
}