【发布时间】:2014-09-23 15:08:01
【问题描述】:
所以我在开发项目中遇到了另一个障碍。
这一次涉及到关于改变方向和保持其保存的实例状态的片段。如果它涉及两个问题,但它们涉及相同的问题催化剂,即方向变化,请原谅我。我会尽量详细,所以请多多包涵。
我有一堆片段使用单个活动作为主机。在我看来,我的片段是按部分分组的,尽管它们仍然是模块化/可按代码重用的。
所以我有 3 个片段托管在一个实现抽屉导航的片段中。逻辑流程是这样的:
Frag1 ->(按下一步)-> Frag2 ->(按下一步)-> Frag3
Frag2 和 Frag3 的创建调用 addToBackStack() 在 FragmentManager 中提交事务。 问题是当我在 Frag2 或 Frag3 然后更改设备方向时,片段消失然后显示 Frag1。
另一个问题是我在Frag1中,然后在EditText中键入一些文本,然后更改方向,尽管实现了onSaveInstanceState(Bundle bundle),但文本消失了。
这是我的相关代码sn-ps:
在Activity.java中创建Frag1的代码sn-p
@Override
public void onNavigationDrawerItemSelected(int position) {
// init the fragment (with a default fragment, not null)
rootFragment = PlaceholderFragment.newInstance(position + 1);
// Position number from navigation sidebar starts from 0.
// Since position starts from 0, add 1 to match section number
// as implemented in {@link #onSectionAttached()}
switch (position) {
case 0: // Other section
rootFragment = PlaceholderFragment.newInstance(position + 1);
break;
case 1: // Frag1
rootFragment = new AddPointsFragment().newInstance(position + 1, "");
break;
case 2: // Other section
rootFragment = new CheckPointsFragment().newInstance(position + 1, "");
break;
default:
break;
}
// update the main primary content by replacing fragments
FragmentManager fragmentManager = getFragmentManager();
// clear all fragments from previous section from the back stack
fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
// replace all currently added fragments in container and replace with the new fragment
// don't add to back stack since these serve as "root" fragments
fragmentManager.beginTransaction()
.replace(R.id.container, rootFragment, rootFragment.getClass().getName())
.commit();
}
在Activity.java中创建Frag2的代码sn-p
public void startAddPointsSuccessFragment(int sectionNumber, String cardNo, int points) {
// Create fragment and give it its arguments
// Since this is not a major fragment,
// I just used its major parent fragment (AddPointsFragment)
// section number to follow the action bar title
AddPointsSuccessFragment addPointsSuccessFragment =
new AddPointsSuccessFragment().newInstance(sectionNumber, cardNo, points);
// Replace whatever is in the container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, addPointsSuccessFragment)
.addToBackStack(AddPointsSuccessFragment.class.getName())
.commit();
}
在Activity.java中创建Frag3的代码sn-p
public void onOkButtonAddPointsSuccessFragmentInteraction(int sectionNumber, String cardNo, int points) {
int minimumPoints = 10;
if (points < minimumPoints) {
// Go back to previous fragment (AddPointsFragment)
// by simulating a back press from host activity.
this.onBackPressed();
}
else {
// Create fragment and give it its arguments
// Since this is not a major fragment,
// I just used its major parent fragment (AddPointsFragment)
// section number to follow the action bar title
RedeemRewardFragment redeemRewardFragment =
new RedeemRewardFragment().newInstance(sectionNumber, cardNo, points);
// Replace whatever is in the container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, redeemRewardFragment)
.addToBackStack(RedeemRewardFragment.class.getName())
.commit();
}
}
关于方向改变后碎片消失的问题,我还没有想出可能的解决方案。
关于在方向改变时保存的实例状态的持久性,我尝试在 Frag1 类中实现 onSaveInstanceState(Bundle bundle),如下所示:
AddPointsFragment.java 的代码 sn-p
EditText cardNoEditText;
@Override
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putInt(ARG_SECTION_NUMBER, mSectionNumber);
bundle.putString(ARG_CARD_NO, cardNoEditText.getText().toString());
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mSectionNumber = getArguments().getInt(ARG_SECTION_NUMBER);
mCardNo = getArguments().getString(ARG_CARD_NO);
}
if (savedInstanceState != null) {
mSectionNumber = savedInstanceState.getInt(ARG_SECTION_NUMBER);
mCardNo = savedInstanceState.getString(ARG_CARD_NO);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_add_points, container, false);
cardNoEditText = (EditText) view.findViewById(R.id.cardNoEditText);
cardNoEditText.setText(mCardNo);
Button enterCardNoButton = (Button) view.findViewById(R.id.enterCardNoButton);
enterCardNoButton.setOnClickListener(this);
Button scanCardNoButton = (Button) view.findViewById(R.id.scanCardNoButton);
scanCardNoButton.setOnClickListener(this);
return view;
}
我尝试在代码中运行有关在更改方向期间失败的持久性的调试器,并且经过检查,onSaveInstanceState(Bundle bundle) 确实有效并且能够将数据传递给 EditText。但是,我还发现 Activity 在更改方向时也会调用 onNavigationDrawerItemSelected(int position),正如您在其中的代码中看到的那样,它会擦除 Frag1 的 FragmentManager 并将其替换为不具有值的新 Frag1还没有卡。
我想这里的基本问题是在这种情况下实现 onSaveInstanceState(Bundle bundle) 的最佳方式是什么?我尝试在 Fragments 中实现它,但我可能犯了一个错误?还是应该在 Activity 中实现它,例如保存现有片段的实例?
提前感谢那些愿意回答的人。 :)
【问题讨论】:
标签: java android android-fragments