努力去理解Android碎片和设备轮换

时间:2015-03-18 12:25:55

标签: android android-fragments

我构建了一个非常简单的Android应用程序,其中包含用于为托管片段添加FragmentsLinearLayout的按钮。当设备旋转时,片段将以正确的布局恢复。它有效。

但是,如果我在具有更复杂用户界面的Activity中复制上述简单应用程序的代码,则Fragments会在设备旋转时消失。从日志消息中我无法理解为什么。

这是包含片段LinearLayout的布局。

Layout

这是我写过的最长的问题,我希望有人有足够的耐心阅读到最后。

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

这些是典型交互的日志消息。这是第一个屏幕截图:通过点击+图片视图添加片段。

Start

第一个片段是使用标记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

添加了三个片段:您可以从红色背景颜色识别它们。

Three fragments added

此时设备旋转,调用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中的两个,特别是第二个。

First rotation, only one packet

确实,您可以看到设备再次旋转时出现了问题

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标记。在两次轮换之间没有发生任何事情:根本没有用户互动

如果设备再次旋转,则不会显示任何碎片。

After two rotations, no fragments

如果您还在阅读,请注意,当您访问意大利时,您将获得免费的比萨饼和啤酒。

如果你能够解决这个问题,那么我还会在当地一家最好的餐厅吃一顿晚餐 - 但你必须先来意大利。

PS。原谅自动完成引入的拼写错误,语言设置为意大利语。我可以纠正它们,但它们与此问题中讨论的问题无关。

0 个答案:

没有答案