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(); 
     } 
    } 
} 

Page Fragment:

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> 

Manifest:

<?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> 

пс: Я работаю с поддержкой-v4 Lib

Спасибо вам помочь, я буду обновлять свой пост я что-то неясно, так что дайте мне знать.

+1

У вас есть configChanges, объявленные внутри вашего manifest.xml? – Blackbelt

+0

Чтобы было понятно, 'TestItemListFragment' используется в' ViewPager'? – Luksprog

+0

Я не объявлял никаких конфигурационных изменений в манифесте. и да TestItemListFragment используется в представлении пейджера в моем приложении. Но моя ошибка тоже воспроизводится без него (код, показанный здесь, достаточно, чтобы воспроизвести ошибку). Спасибо за помощь –

ответ

2

После поворота экрана ваш фрагмент (видимый на экране) не обновляется, потому что это не тот фрагмент, который детализирует фрагмент.

После поворота экрана, вы создаете новый фрагмент:

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(), но оба они не работают. –

 Смежные вопросы

  • Нет связанных вопросов^_^