Android 旋转时保留碎片对象
我在蜂巢中开发了一个应用程序,我正在使用碎片。Android 旋转时保留碎片对象,android,android-fragments,android-3.0-honeycomb,screen-rotation,Android,Android Fragments,Android 3.0 Honeycomb,Screen Rotation,我在蜂巢中开发了一个应用程序,我正在使用碎片。 这是我的应用程序 我有一个活动(比如A1),其中有一个片段 最初,这个片段保存一个片段对象,比如说(F1) 然后根据用户操作,它可能会更改为其他对象F2、F3 我的问题是什么 当用户旋转设备时,会重新创建活动,并使F1成为片段对象,即使在旋转之前它不是 旋转时保留碎片对象的方法是什么? 我使用了setRetainInstance(true)但它对我不起作用 我在我的onCreate函数中按代码添加了片段,如下所示 @Override publi
这是我的应用程序
- 我有一个活动(比如A1),其中有一个片段
- 最初,这个片段保存一个片段对象,比如说(F1)
- 然后根据用户操作,它可能会更改为其他对象F2、F3李>
旋转时保留碎片对象的方法是什么?
我使用了
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();
}
默认情况下,Android将保留片段对象。在代码中,您正在onCreate
函数中设置homeFragment
。这就是为什么在onCreate
中设置的内容总是homeFragment
或fl
因为无论何时旋转,onCreate都会执行,并将片段对象设置为第一个
因此,最简单的解决方案是检查savedInstanceState
bundle是否为null,并设置fragment对象
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(null == savedInstanceState) {
// set you initial fragment object
}
}
您需要为片段提供一个唯一的标记,并检查该片段是否已经添加到您的活动中
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+中可用,不确定早期版本)。打开新活动时,第一个活动将被销毁。当您返回到它时(按back键),它将再次创建,并且savedInstanceState不为null。但是,您的片段不再在活动中,您必须再次添加它
编辑-显示原始原则,但支持FragmentManager
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
),此功能尤其有用我在活动的布局中定义了片段
,片段
中的onSaveInstanceState
确实会被调用,但是片段的oncreateview
中的savedInstanceState
包
为空
原因是我的片段在XML中没有ID:
android:id="@+id/compass_fragment" ...
在活动中使用onAttachFragment()
重新分配对象:
@Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof MyFragment)
this.myFragment = (MyFragment) fragment;
}
您只需在片段类的OnCreate
内设置RetainInstance
属性
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
RetainInstance = true;
}
只需重新布线@Ralf answer,使其更具动态性,无需指定要保留的特定片段,但如果要指定,也可以:
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();
}
}
}
如果我使用带有ViewPager的活动来处理片段,我该怎么办?@androiddeveloper。不,我所做的是:super.onCreate(null);“默认情况下,android将保留片段对象”…不正确。Android将在方向更改时创建新对象,除非调用setRetainInstance(true)
。不要将此与Android自动重新连接片段相混淆。它们不是一回事。检查S.D.在上报告的痕迹。虽然我以前使用过@labeeb提供的答案,但我认为检查唯一的标记是最好的方法。有趣!谷歌似乎需要更新他们的模板代码。我认为他们应该改变这个生命周期。相反,字典中的任何单词都是安卓的生命周期方法。这个标签方法解决了我的问题!每次我想说“new HomeFragment”时,我首先检查是否可以找到一个非空的home fragment,如果找到了,我就使用它,如果没有,我就创建了一个新的:)