片段调用片段在屏幕旋转时失去状态
Fragment calling fragments loosing state on screen rotation
您好,我创建了一个带有默认 "Navigation Drawer Activity" 的项目。
所以我有一个带有片段的 MainActivity,菜单上的每个项目都被替换了。
其中一个菜单是 "Customers",其中显示了客户列表。
从客户片段我可以看到这个客户的兴趣,有一个调用兴趣(InterestsListFragment)的片段(CustomerListFragment)。
还有更多的关卡,但要简短就够了。
这是 MainActivity 上的代码,我用它从片段调用片段并在它们之间传递数据
public void passData(Object[] data, Fragment f) {
Bundle args = new Bundle();
args.putSerializable("PASSED_DATA", data);
f.setArguments(args);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, f)
.addToBackStack("")
.commit();
}
我用的是:
mCallbacks.passData(new Object[]{c}, new OpportunityListFragment());
问题是,当我从 activity 的哪个级别旋转 phone 时,它会返回到第一个片段(CustomerListFragment),如果我单击 "Back" 在单元格 phone 上它回到我旋转 phone 时的位置。
我该怎么做才能避免这种问题?如果我正在替换片段,为什么它会回到第一个 activity 唤起?
当您更改屏幕方向时,您的父级 Activity 将被销毁并重新创建。除非您以某种方式坚持关卡结构,否则它将始终显示为您第一次启动 activity 时的样子。您可以使用 bundle 对象,或者对于需要将其持久保存到数据库的更复杂的对象。
无论哪种方式,onSaveInstanceState 都是您的朋友。然后在您的 onCreate 方法中,您需要检查包或数据库,并相应地设置片段。
ste-fu 的回答是正确的,但让我们以编程方式进行探索。 Google 文档 @ Handling Runtime Changes 中有一个很好的工作代码。您必须执行 2 个代码片段。
1) 代码片段:
public class MyActivity extends Activity {
private RetainedFragment dataFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// find the retained fragment on activity restarts
FragmentManager fm = getFragmentManager();
dataFragment = (DataFragment) fm.findFragmentByTag(“data”);
// create the fragment and data the first time
if (dataFragment == null) {
注意:代码使用 FragmentManager 查找当前 Fragment。如果 fragment 为 null,则 UI 或 app 尚未执行。如果不为空,则可以从 RetainedFragment 对象获取数据。
2) 需要保留Fragment状态
public class RetainedFragment extends Fragment {
// data object we want to retain
private MyDataObject data;
// this method is only called once for this fragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
注意:setRetainInstance在OnCreate中使用。建议对 Fragment 进行子类化,将其命名为 RetainedFragment,用于片段 1。
您好,我创建了一个带有默认 "Navigation Drawer Activity" 的项目。 所以我有一个带有片段的 MainActivity,菜单上的每个项目都被替换了。
其中一个菜单是 "Customers",其中显示了客户列表。
从客户片段我可以看到这个客户的兴趣,有一个调用兴趣(InterestsListFragment)的片段(CustomerListFragment)。
还有更多的关卡,但要简短就够了。
这是 MainActivity 上的代码,我用它从片段调用片段并在它们之间传递数据
public void passData(Object[] data, Fragment f) {
Bundle args = new Bundle();
args.putSerializable("PASSED_DATA", data);
f.setArguments(args);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, f)
.addToBackStack("")
.commit();
}
我用的是:
mCallbacks.passData(new Object[]{c}, new OpportunityListFragment());
问题是,当我从 activity 的哪个级别旋转 phone 时,它会返回到第一个片段(CustomerListFragment),如果我单击 "Back" 在单元格 phone 上它回到我旋转 phone 时的位置。
我该怎么做才能避免这种问题?如果我正在替换片段,为什么它会回到第一个 activity 唤起?
当您更改屏幕方向时,您的父级 Activity 将被销毁并重新创建。除非您以某种方式坚持关卡结构,否则它将始终显示为您第一次启动 activity 时的样子。您可以使用 bundle 对象,或者对于需要将其持久保存到数据库的更复杂的对象。
无论哪种方式,onSaveInstanceState 都是您的朋友。然后在您的 onCreate 方法中,您需要检查包或数据库,并相应地设置片段。
ste-fu 的回答是正确的,但让我们以编程方式进行探索。 Google 文档 @ Handling Runtime Changes 中有一个很好的工作代码。您必须执行 2 个代码片段。
1) 代码片段:
public class MyActivity extends Activity {
private RetainedFragment dataFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// find the retained fragment on activity restarts
FragmentManager fm = getFragmentManager();
dataFragment = (DataFragment) fm.findFragmentByTag(“data”);
// create the fragment and data the first time
if (dataFragment == null) {
注意:代码使用 FragmentManager 查找当前 Fragment。如果 fragment 为 null,则 UI 或 app 尚未执行。如果不为空,则可以从 RetainedFragment 对象获取数据。
2) 需要保留Fragment状态
public class RetainedFragment extends Fragment {
// data object we want to retain
private MyDataObject data;
// this method is only called once for this fragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
注意:setRetainInstance在OnCreate中使用。建议对 Fragment 进行子类化,将其命名为 RetainedFragment,用于片段 1。