조각 내의 조각


145

이것이 실제로 Android API의 버그인지 궁금합니다.

다음과 같은 설정이 있습니다.

┌----┬---------┐
|    |         |
|  1 |    2    |
|    |┌-------┐|
|    ||       ||
|    ||   3   ||
└----┴┴-------┴┘
  1. 오른쪽 창에 조각 # 2 (검색 화면)를로드하는 메뉴입니다.
  2. 결과 목록 인 조각 # 3을 포함하는 검색 화면입니다.
  3. 결과 목록은 여러 곳에서 사용됩니다 (자체적으로 작동하는 고급 조각 포함).

이 기능은 전화기에서 완벽하게 작동합니다 (1 및 2 및 3은 ActivityFragments).

그러나이 코드를 사용했을 때 :

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();       
    Fragment frag = new FragmentNumber2();
    if(toLoad != null) frag.setArguments(toLoad);
    transaction.replace(R.id.rightPane, frag);      
    transaction.commit();

어디에 R.id.leftPaneR.id.rightPane있는 <fragment>수평 선형 레이아웃의.

위의 코드는 상주하는 조각을 제거한 다음 새로운 조각으로 대체한다는 것을 이해합니다. Brilliant ...이 코드가 두 번째로 실행될 때 다음 예외가 발생하기 때문에 발생하지 않습니다.

07-27 15:22:55.940: ERROR/AndroidRuntime(8105): Caused by: java.lang.IllegalArgumentException: Binary XML file line #57: Duplicate id 0x7f080024, tag null, or parent id 0x0 with another fragment for FragmentNumber3

FragmentNumber3의 컨테이너가 복제되었고 더 이상 고유 ID가 없기 때문입니다. 새로운 조각이 추가되기 전에 초기 조각이 파괴되지 않았습니까 (?) 내 마음에 그것은 대체 되지 않았다는 것을 의미합니다 .

이것이 가능한지 누군가 말해 줄 수 있습니까 ( 이 대답 은 그렇지 않다는 것을 제안합니까) 아니면 버그입니까?



6
@rds 이것은 고대의 질문이며, 중복으로 표시하기에는 무의미합니다.
pietv8x

답변:


203

중첩 된 조각은 현재 지원되지 않습니다. 다른 프래그먼트의 UI 내에 프래그먼트를 넣으려고하면 정의되지 않고 작동이 깨질 수 있습니다.

업데이트 : 중첩 된 조각 Android 4.2 (및 Android 지원 라이브러리 개정판 11)부터 지원됩니다 : http://developer.android.com/about/versions/android-4.2.html#NestedFragments

참고 ( 이 문서에 따라 ) : " 참고 : 레이아웃에을 포함하는 경우 레이아웃을 조각으로 팽창시킬 수 없습니다 <fragment>. 중첩 된 조각은 조각에 동적으로 추가 된 경우에만 지원됩니다. "


14
초기 구현의 설계 목표가 아니기 때문에 지원되지 않습니다. 이 기능에 대한 많은 요청을 들었으므로 아마도 어느 시점에서 수행 될 것입니다. 그러나 평소와 같이 우선 순위와 경쟁하는 다른 많은 것들이 있습니다.
hackbod

4
FragmentActivity, FragmentManager 및 FragmentTransaction을 확장하여이를 관리했습니다. 기본 전제는 내 활동에서 DeferringFragmentActivity를 확장하여 동일한 API를 제공하므로 다른 코드 변경은 없습니다. getFragmentManager를 호출하면 DeferringFragmentManager라는 인스턴스가 생성되고 beginTransaction을 호출하면 DeferredTransaction이 발생합니다. 이 트랜잭션은 POJO를 호출 된 메소드 및 인수와 함께 저장합니다. 커밋이 호출되면 보류중인 DeferredTransactions를 먼저 찾습니다. 모든 트랜잭션이 커밋되면 실제 트랜잭션을 시작하고 저장된 모든 메서드를 args와 함께 실행합니다.
dskinner

11
그 시점은 지금입니다. Nested Fragment는 이제 Android API의 일부입니다. developer.android.com/about/versions/... .
Alex Lockwood

9
와우, 악몽 : 조각에 <fragment>를 사용하고 조각이 자식 조각을 사용하는 경우 명확한 오류와 함께 실패하지 않습니다 ( "자식 조각을 레이아웃 조각에 추가 할 수 없음"). "조각이보기를 작성하지 않았습니다"와 같은 예외로 인해 신비하게 실패합니다. 디버깅에는 몇 시간이 걸립니다 ...
Glenn Maynard

6
@ MartínMarconcini는 확실하지만 API가 제공하는 기능을 기반으로하는 것은 아닙니다. 무언가가 허용되지 않으면 명확하게 문서화 되어야 하며, 무언가가 예상대로 작동하지 않기 때문에 개발자가 머리카락을 뽑아 두지 마십시오.
dcow

98

중첩 된 조각은 Android 4.2 이상에서 지원됩니다.

Android 지원 라이브러리 는 이제 중첩 조각을 지원 하므로 Android 1.6 이상에서 중첩 조각 디자인을 구현할 수 있습니다.

프래그먼트를 내포하려면 프래그먼트 를 추가하려는 프래그먼트에서 getChildFragmentManager () 를 호출 하십시오. 그러면 최상위 활동에서 일반적으로하는 것처럼 FragmentManager가 조각 트랜잭션을 생성하는 데 사용할 수 있습니다. 예를 들어, 기존 Fragment 클래스 내에서 조각을 추가하는 코드는 다음과 같습니다.

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

중첩 된 조각에 대한 자세한 내용을 보려면 다음 자습서를 참조하십시오.
Part 1
Part 2
Part 3

여기 중첩 된 프래그먼트에 대한 모범 사례에 대해 논의하는 SO 게시물이 있습니다.


Nestedfragment의 주요 단점은 childfragment에서 optionmenu를 호출 할 수 없다는 것입니다. (ABS를 사용하는 경우!
LOG_TAG

내 문제를 좀 봐주시겠습니까? 그것과 매우 유사 ... stackoverflow.com/questions/32240138/... . 나를 위해 아이 framnet이 코드에서 부풀려지지 않습니다
Nicks

33

.. 부모 조각의 destroyview메소드 에서 중첩 조각을 정리할 수 있습니다 .

@Override
    public void onDestroyView() {

      try{
        FragmentTransaction transaction = getSupportFragmentManager()
                .beginTransaction();

        transaction.remove(nestedFragment);

        transaction.commit();
      }catch(Exception e){
      }

        super.onDestroyView();
    }

4
SetAlwaysFinish ( bricolsoftconsulting.com/2011/12/23/… )를 사용 하여 수명주기 테스트를 수행 하면 항상 완료된 상태에서 다른 활동이 시작될 때이 코드에서 오류가 발생 함을 알 수 있습니다 (IllegalStateException :이 작업을 수행 할 수 없음) onSaveInstanceState 이후). try / catch에서 위의 코드를 감싸는 것이 가장 우아한 해결책은 아니지만 모든 것이 작동하는 것처럼 보입니다.
Theo

이것은 거의 효과가있었습니다. 나중에 UI 그리기에 Stackoverflow가 생겼습니다. 확실히 중첩 된 조각을 피하십시오 ...
neteinstein

14

조각을 시작하는 작업 표시 줄의 탭과 비슷한 응용 프로그램을 개발 중입니다.이 조각 중 일부에는 조각이 여러 개 있습니다.

응용 프로그램을 실행하려고 할 때 같은 오류가 발생했습니다. 탭을 선택 해제 한 다음 다시 선택하면 xml 레이아웃 내에서 Fragments를 인스턴스화하면 팽창기 오류가 발생합니다.

xml의 ​​모든 조각을 Linearlayouts로 교체 한 다음 조각 관리자 / 조각 트랜잭션을 사용하여 조각을 인스턴스화하기 위해 적어도 테스트 수준에서 모든 것이 올바르게 작동하는 것처럼 보입니다.

이것이 도움이되기를 바랍니다.


누구든지이 방법의 효과에 대해 언급 할 수 있습니까? 조각을 한 레벨 만 사용할 수 있다는 것은 불행한 일입니다. 그때는 전혀 사용하지 않을 수도 있습니다. 플레이스 홀더 뷰 그룹에 프로그래밍 방식으로 추가하면 경고없이 작동합니까?
Rafael Nobre

여전히 나를 위해 일하고있는 것 같습니다. 나는 그들을 뷰 홀더로 바꾸고 문제없이 교환합니다. 한 가지주의 사항 나는 아이스크림 샌드위치와 호환되지 않는 벌집에서만 이것을하고 있습니다.
draksia

4

나는 같은 문제에 직면하여 며칠 동안 어려움을 겪었으며 탭을 선택하거나 선택 취소 할 때 fragment.hide () / fragment.show ()를 사용하는 것이 가장 쉬운 방법이라고 말해야합니다 ().

public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)
{
    if (mFragment != null)
        ft.hide(mFragment);
}

화면 회전이 발생하면 모든 부모 및 자식 조각이 올바르게 파괴됩니다.

이 접근법은 또한 하나의 추가 이점이 있습니다. hide () / show ()를 사용하면 프래그먼트 뷰가 상태를 잃지 않으므로 예를 들어 ScrollView의 이전 스크롤 위치를 복원 할 필요가 없습니다.

문제는 조각이 보이지 않을 때 분리하지 않는 것이 올바른지 여부입니다. TabListener의 공식 예제는 프래그먼트가 재사용 가능하고 메모리로 오염되어서는 안된다는 생각을 염두에두고 설계되었다고 생각합니다.하지만 탭이 몇 개인 경우 사용자가 자주 전환 할 것입니다. 현재 활동에 첨부 된 상태로 유지하는 것이 적절합니다.

더 숙련 된 개발자의 의견을 듣고 싶습니다.


0

중첩 된 조각이 제거되거나 복제되지 않는 경우 (예 : 활동 다시 시작, 화면 회전시) 변경을 시도하십시오.

transaction.add(R.id.placeholder, newFragment);

transaction.replace(R.id.placeholder, newFragment);

위의 방법으로도 도움이되지 않으면 다음을 시도하십시오.

Fragment f = getChildFragmentManager().findFragmentById(R.id.placeholder);

FragmentTransaction transaction = getChildFragmentManager().beginTransaction();

if (f == null) {
    Log.d(TAG, "onCreateView: fragment doesn't exist");
    newFragment= new MyFragmentType();
    transaction.add(R.id.placeholder, newFragment);
} else {
    Log.d(TAG, "onCreateView: fragment already exists");
    transaction.replace(R.id.placeholder, f);
}
transaction.commit();

여기서 배웠다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.