1

我有一个片段和配置更改(旋转)的问题:我有一个随机更新片段的文本按钮的屏幕。旋转后无法更新动态创建的片段

一切工作正常,直到我旋转设备(配置更改):我可以findFragmentByTag该片段,但其getView()方法返回null。 我正在使用setRetainState(true):所有私有字段都被很好地保留。

在下面的代码中,我动态地创建了片段,因为我处于视图分页器的上下文中(TestItemListFragment引用了ViewPager页面的片段并且TestItemDetailFragment引用了我想要文本的片段点击按钮时更新)。虽然,在这个例子中,显示的代码被简化了,详见代码中的注释。

我错过了什么?我究竟做错了什么 ? (确保我)

编辑:链接到源再现:https://bitbucket.org/bixibu/demo-nestedfragment-android

活动:

public class TestActivity extends FragmentActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    protected void onResumeFragments() { 
     super.onResumeFragments(); 

     Bundle args = new Bundle(); 
     TestItemListFragment frag = TestItemListFragment.newInstance(); 

     if (getSupportFragmentManager().findFragmentByTag("tag") == null) { 
      getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag, "tag").commitAllowingStateLoss(); 
     } 
    } 
} 

页面片段:

public class TestItemListFragment extends Fragment { 


    ItemDetailFragment detailFragment = null; 
    String mCurTitle = null; 

    private SecureRandom random = new SecureRandom(); 

    public static TestItemListFragment newInstance() { 
     TestItemListFragment fragment = new TestItemListFragment(); 
     return fragment; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setRetainInstance(true); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     super.onCreateView(inflater, container, savedInstanceState); 
     return inflater.inflate(R.layout.item_list_fragment_test, container, false); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 

     /** 
     * Addind random string generation while clicking on button 
     * And setting this random String to the fragment 
     */ 
     Button button = (Button) getView().findViewById(R.id.button1); 
     button.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       updateDetail(new BigInteger(130, random).toString(32)); 
      } 
     }); 

     // creating new fragment 
     detailFragment = ItemDetailFragment.newInstance(new Bundle()); 

     // in my XML I don't have any ID because I have to create as many fragment as I have Pages in my ViewPager 
     // so I dynamically creates an ID 
     // in order to have a different fragment for each Page 
     // if I don't do that only my first Page display a fragment (or multiple ones) 
     int fragmentContainerUniqId = 519618565; 
     View fragmentContainer = getView().findViewById(R.id.detailFragmentContainer); 
     fragmentContainer.setId(fragmentContainerUniqId); 

     if (getActivity().getSupportFragmentManager().findFragmentById(fragmentContainerUniqId) == null) { 
      // Add the fragment to the 'detailFragmentContainer' FrameLayout 
      getActivity().getSupportFragmentManager().beginTransaction() 
        .add(fragmentContainerUniqId, detailFragment).commitAllowingStateLoss(); 
     } 

     if (mCurTitle != null) { 
      updateDetail(mCurTitle); 
     } 

    } 

    // May also be triggered from the Activity 
    public void updateDetail(String title) { 
     detailFragment.setTitle(title); 
    } 
} 

详细片段:

public class ItemDetailFragment extends Fragment { 

    public static ItemDetailFragment newInstance(Bundle bundle) { 
     ItemDetailFragment fragment = new ItemDetailFragment(); 
     fragment.setArguments(bundle); 
     return fragment; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

     View view = inflater.inflate(R.layout.item_detail_fragment, container, false); 
     return view; 
    } 

    @Override 
    public void onViewCreated(View view, Bundle savedInstanceState) { 
     super.onViewCreated(view, savedInstanceState); 

     setTitle(getArguments().getString("title")); 
    } 

    public void setTitle(String title) { 
     if (getView() != null && title != null) { 
      TextView view = (TextView) getView().findViewById(R.id.detailsText); 

      view.setText(title); 
     } 
    } 
} 

XML:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="horizontal" > 

    <Button 
     android:id="@+id/button1" 
     android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="populate fragment" 
     /> 


     <FrameLayout 
      android:id="@+id/detailFragmentContainer" 
      android:layout_width="0dp" 
      android:layout_height="match_parent" 
      android:layout_weight="2" /> 


</LinearLayout> 

清单:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.burnside.digital.nestedfragments" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk 
     android:minSdkVersion="8" 
     android:targetSdkVersion="16" /> 

    <application 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <activity 
      android:name="com.burnside.digital.nestedfragments.TestActivity" 
      android:label="@string/title_activity_test" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

PS:我与支持-V4 LIB

工作感谢您的帮助,我会更新我的帖子我的东西是不清楚,所以让我知道。

+1

你有你的manifest.xml中声明的configChanges吗? – Blackbelt

+0

为了说清楚,'TestItemListFragment'用在'ViewPager'中吗? – Luksprog

+0

我没有在清单中声明任何configChanges。和是TestItemListFragment是在我的应用程序中的视图分页器中使用。但是我的bug也没有被复制(这里的代码足以重现这个bug)。感谢您的帮助 –

回答

2

屏幕旋转后,您的片段(屏幕上可见)不会更新,因为它不是detailFragment的片段。

屏幕旋转后,创建一个新的片段:

detailFragment = ItemDetailFragment.newInstance(new Bundle()); 

,但它不会被添加到fragmentContainerUniqId因为

getActivity().getSupportFragmentManager().findFragmentById(fragmentContainerUniqId) 

不为空

通过更改TestItemListFragment代码这和片段将更新

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 

    /** 
    * Addind random string generation while clicking on button 
    * And setting this random String to the fragment 
    */ 
    Button button = (Button) getView().findViewById(R.id.button1); 
    button.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      updateDetail(new BigInteger(130, random).toString(32)); 
     } 
    }); 


    // in my XML I don't have any ID because I have to create as many fragment as I have Pages in my ViewPager 
    // so I dynamically creates an ID 
    // in order to have a different fragment for each Page 
    // if I don't do that only my first Page display a fragment (or multiple ones) 
    int fragmentContainerUniqId = 519618565; 
    View fragmentContainer = getView().findViewById(R.id.detailFragmentContainer); 
    fragmentContainer.setId(fragmentContainerUniqId); 

    if ((detailFragment = (ItemDetailFragment) getActivity().getSupportFragmentManager().findFragmentById(fragmentContainerUniqId)) == null) { 
     // Add the fragment to the 'detailFragmentContainer' FrameLayout 
     // creating new fragment 
     detailFragment = ItemDetailFragment.newInstance(new Bundle()); 
     getActivity().getSupportFragmentManager().beginTransaction() 
       .add(fragmentContainerUniqId, detailFragment).commitAllowingStateLoss(); 
    } 

    if (mCurTitle != null) { 
     updateDetail(mCurTitle); 
    } 
} 
0

在PageFragment,而不是:

getActivity().getSupportFragmentManager(); 

使用:

getSupportFragmentManager(); 

旋转之后,第一种形式仍然指向原来的活动。 第二种形式将正确引用新创建的活动。

+0

getSupportFragmentManager()未定义,我必须选择getChildFragmentManager()或getFragmentManager(),但两者都不起作用。 –