我构建了一个非常简单的Android应用程序,其中包含用于为托管片段添加Fragments
和LinearLayout
的按钮。当设备旋转时,片段将以正确的布局恢复。它有效。
但是,如果我在具有更复杂用户界面的Activity
中复制上述简单应用程序的代码,则Fragments
会在设备旋转时消失。从日志消息中我无法理解为什么。
这是包含片段LinearLayout
的布局。
这是我写过的最长的问题,我希望有人有足够的耐心阅读到最后。
Activity
有两个用于附加Fragment
实例的字段:
protected static String FRAGMENT_TAG = "tag_";
protected int fragmentIndex = 10000;
当用户使用此侦听器点击Button
时,会创建新片段:
addPacketIV = (ImageView) findViewById(R.id.addPacketIV);
addPacketIV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addNewPacketFragment();
}
});
protected void addNewPacketFragment() {
Log.d(TAG, "");
int currentFragmentIndex= fragmentIndex++;
String tagForFragment = FRAGMENT_TAG + currentFragmentIndex;
Log.d(TAG, "\n** Creating new Packet Editor TAG= " + tagForFragment);
addPacketEditor(tagForFragment);
}
protected void addPacketEditor(String fragmentTag) {
if(fragmentTag == null) {
Log.d(TAG, "Received a null fragmentTag - should never happen!");
return;
}
PacketEditorFragment fragment = (PacketEditorFragment)
getSupportFragmentManager().findFragmentByTag(fragmentTag);
if(fragment == null) {
Log.d(TAG, "No fragment found for tag " + fragmentTag + " - create new one");
fragment = PacketEditorFragment.newInstance();
fragment.setRetainInstance(true);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.packetsFragmentContainer, fragment, fragmentTag)
.commit();
Log.d(TAG, "New fragment created and added to linear layout: " + fragmentTag);
} else {
Log.d(TAG, "Fragment " + fragmentTag + " already attached to this activity");
}
Log.d(TAG, "Adding this fragment to allFragments: " + fragment.getTag());
allFragments.add(fragment);
Log.d(TAG, "Printing fragments:");
int nFrags = allFragments.size();
for(int i=0; i<nFrags; i++) {
Log.d(TAG, "Fragment " + i + " - tag " + allFragments.get(i).getTag());
}
Log.d(TAG, "Num of attached fragment allFragments.size(): " + allFragments.size());
Log.d(TAG, "Num of attached fragment packetContainer.childCount(): " + packetFragmentContainerVG.getChildCount());
} // addPacketEditor
添加片段时,我会打印List allFragments
中存储的片段数,并检查有多少片段附加到其容器R.id.packetFragmentContainerVG
。
当设备旋转时,我将片段标签存储在状态Bundle
:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "onSaveInstanceState called");
Log.d(TAG, "packetContainer.childCount() " + packetFragmentContainerVG.getChildCount());
// Store the index for future fragments
outState.putInt(KEY_STATE_FRAGMENT_INDEX, fragmentIndex);
Log.d(TAG, "Saved current fragment index: " + fragmentIndex);
int nPackets = allFragments.size();
// Store the number of packet fragments
outState.putInt(KEY_STATE_N_PACKET_EDITORS, nPackets);
Log.d(TAG, "onSaveInstanceState: " + nPackets + " packets");
// for each attached fragment store its tag
for(int i=0; i<nPackets; i++) {
String fragmentTag = allFragments.get(i).getTag();
Log.d(TAG, "Saving fragment " + i +") " + fragmentTag);
outState.putString(KEY_STATE_PACKET_FRAGMENT + i, fragmentTag);
} // for
} // onSaveInstanceState
这是onRestoreInstanceState(.)
:
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, "onRestoreInstanceState");
fragmentIndex = savedInstanceState.getInt(KEY_STATE_FRAGMENT_INDEX);
Log.d(TAG, "Restored index for fragments: " + fragmentIndex);
restorePacketEditors(savedInstanceState);
}
protected void restorePacketEditors(Bundle savedInstanceState) {
int nSavedPackets = savedInstanceState.getInt(KEY_STATE_N_PACKET_EDITORS);
Log.d(TAG, "Restoring packets, number: " + nSavedPackets);
for(int i = 0; i<nSavedPackets; i++) {
String fragmentTag = savedInstanceState.getString(KEY_STATE_PACKET_FRAGMENT+i);
Log.d(TAG, i+") has tag " + fragmentTag);
addPacketEditor(fragmentTag);
}
} // restorePacketEditors
这些是典型交互的日志消息。这是第一个屏幕截图:通过点击+
图片视图添加片段。
第一个片段是使用标记tag_10000
No fragment found for tag tag_10000 - create new one
New fragment created and added to linear layout: tag_10000
Adding this fragment to allFragments: tag_10000
Printing fragments:
Fragment 0 - tag tag_10000
Num of attached fragment allFragments.size(): 1
Num of attached fragment packetContainer.childCount(): 0
这些是添加其他两个片段时打印的日志消息:
No fragment found for tag tag_10001 - create new one
New fragment created and added to linear layout: tag_10001
Adding this fragment to allFragments: tag_10001
Printing fragments:
Fragment 0 - tag tag_10000
Fragment 1 - tag tag_10001
Num of attached fragment allFragments.size(): 2
Num of attached fragment packetContainer.childCount(): 1
No fragment found for tag tag_10002 - create new one
New fragment created and added to linear layout: tag_10002
Adding this fragment to allFragments: tag_10002
Printing fragments:
Fragment 0 - tag tag_10000
Fragment 1 - tag tag_10001
Fragment 2 - tag tag_10002
Num of attached fragment allFragments.size(): 3
Num of attached fragment packetContainer.childCount(): 2
添加了三个片段:您可以从红色背景颜色识别它们。
此时设备旋转,调用onSaveInstanceState
onSaveInstanceState called
packetContainer.childCount() 3
Saved current fragment index: 10003
onSaveInstanceState: 3 packets
Saving fragment 0) tag_10000
Saving fragment 1) tag_10001
Saving fragment 2) tag_10002
OnStop called
... onRestoreInstanceState被称为
onRestoreInstanceState
Restored index for fragments: 10003
Restoring packets, there are: 3
0) has tag tag_10000
Fragment tag_10000 already attached to this activity
Adding this fragment to allFragments: tag_10000
Printing fragments:
Fragment 0 - tag tag_10000
Num of attached fragment allFragments.size(): 1
Num of attached fragment packetContainer.childCount(): 3
1) has tag tag_10001
Fragment tag_10001 already attached to this activity
Adding this fragment to allFragments: tag_10001
Printing fragments:
Fragment 0 - tag tag_10000
Fragment 1 - tag tag_10001
Num of attached fragment allFragments.size(): 2
Num of attached fragment packetContainer.childCount(): 3
2) has tag tag_10002
Fragment tag_10002 already attached to this activity
Adding this fragment to allFragments: tag_10002
Printing fragments:
Fragment 0 - tag tag_10000
Fragment 1 - tag tag_10001
Fragment 2 - tag tag_10002
Num of attached fragment allFragments.size(): 3
Num of attached fragment packetContainer.childCount(): 3
There are 3 fragments
0) tag_10000
1) tag_10001
2) tag_10002
即使一切正常,只显示三个Fragment
中的两个,特别是第二个。
确实,您可以看到设备再次旋转时出现了问题
onSaveInstanceState called
Saved current fragment index: 10003
onSaveInstanceState: 3 packets
Saving fragment 0) null
Saving fragment 1) tag_10001
Saving fragment 2) null
OnStop called
如您所见,三个Fragments
中有两个现在有一个null
标记。在两次轮换之间没有发生任何事情:根本没有用户互动
如果设备再次旋转,则不会显示任何碎片。
如果您还在阅读,请注意,当您访问意大利时,您将获得免费的比萨饼和啤酒。
如果你能够解决这个问题,那么我还会在当地一家最好的餐厅吃一顿晚餐 - 但你必须先来意大利。
PS。原谅自动完成引入的拼写错误,语言设置为意大利语。我可以纠正它们,但它们与此问题中讨论的问题无关。