Fragment를 제거하는 방법, 즉 finish ()와 동등한 방법은 무엇입니까?


230

호환성 라이브러리를 사용하여 조각을 사용하도록 앱을 변환하고 있습니다. 현재 나는 서로 연결되어있는 많은 활동 (ABCD)을 가지고 있습니다 .D에는 'OK'버튼이 있습니다 .'OK '버튼을 누르면 호출이 끝나면 onActivityResult()C와 B를 추가로 파괴합니다.

나의 사전 Honycomb 프래그먼트 버전에서 각 활동은 효과적으로 프래그먼트 Af Bf Cf Df의 래퍼입니다. 모든 활동을 통해 시작되는 startActivityForResult()onActivityResult()조각의 각 행복하게 호출 할 수 있습니다 내getActivity().finish()

내가 겪고있는 문제는 내 Honeycomb 버전에 하나의 활동 (A) 만 있으며 Bf, Cf, Df 조각은을 사용하여로드됩니다 FragmentManager.

내가 이해하지 못하는 것은 조각 Df, Cf 및 Bf를 제거하기 위해 'OK'를 누를 때 Df에서 무엇을해야합니까?

조각 자체가 스택에서 튀어 나오려고 시도했지만 예외가 발생했습니다. onActivityResult()를 사용하여 조각을로드하지 않았기 때문에 쓸모가 없습니다 startActivityForResult().

나는 이것에 대해 완전히 잘못 생각하고 있습니까? 트랜잭션 관리자를 사용하여 팝을 수행하기 위해 부모 조각 또는 활동과 통신하는 일종의 리스너를 구현해야합니까?


7
((YourActivity) getActivity ()). onBackPressed ()는 어떻습니까?
Viswanath Lekshmanan

귀하의 코멘트 답변 @ViswanathLekshmanan 나를 위해 유용합니다 .. (1) 찬성 투표 나로부터
아비 쉑 싱

:) 듣고에 @AbhishekSingh 좋은
비스와 나스 Lekshmanan

@ViswanathLekshmanan :)
Abhishek Singh

답변:


62

내가 이해하지 못하는 것은 조각 Df, Cf 및 Bf를 제거하기 위해 'OK'를 누를 때 Df에서 무엇을해야합니까?

1 단계 : Df가 D에게 "yo! OK 클릭을 받았습니다!" 액티비티 자체 또는 액티비티가 제공 한 인터페이스 인스턴스에서 메소드 호출을 통해.

2 단계 : D를 통해 조각을 제거하도록합니다 FragmentManager.

호스팅 활동 (D)은 활동에 포함 된 다른 조각 (예 : 다른 활동에 있음)을 아는 것입니다. 따라서 프래그먼트 믹스에 영향을 줄 수있는 프래그먼트 내 이벤트가 활동으로 전파되어 적절한 오케스트레이션이 발생합니다.


그러나 허니컴 버전에는 D가 없습니다. FragmentTransaction을 사용하여 Df를로드하는 Cf를로드하는 프래그먼트 Bf를로드하는 활동 A가 있습니다.
PJL

1
@PJL : 죄송합니다. A를 의미했습니다. 이것이 리스너 인터페이스를 사용하는 한 가지 이유이므로 여러 활동이 모두 Df의 "OK click"이벤트에 응답 할 수 있습니다.
CommonsWare

1
현재 이식 중이므로 조각 Df의 onActivityResult 메서드에서 리스너 메서드를 액티비티로 호출했습니다. 그런 다음 FragmentManager에서 popBackStack을 호출했습니다. 그러나 이로 인해 "IllegalStateException : onSaveInstanceState 후에이 작업을 수행 할 수 없습니다"라는 예외가 발생합니다.이를 극복 할 수있는 방법에 대한 아이디어가 있습니까?
PJL

1
@DiegoPalomar : finish()충분해야합니다.
CommonsWare

1
@ user3364963 : 조사 한 지 오래되었지만 IIRC는 백 스택에서 튀어 나오면 파괴됩니다. onDestroy()프래그먼트에 메소드를 추가하고 호출되는지 확인하십시오.
CommonsWare

313

그것이 가장 가까운 접근 방법은 아니지만 지원할 수있는 가장 적합한 방법은 지원 / 호환성 라이브러리입니다.

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

또는

getActivity().getFragmentManager().beginTransaction().remove(this).commit();

그렇지 않으면.

또한 백 스택을 사용하여 팝할 수 있습니다. 그러나 프래그먼트가 백 스택에 없거나 (파편을 가져온 프래그먼트 트랜잭션에 따라 ..) 스택에 가져온 마지막이 아닐 수 있으므로 스택을 팝하면 잘못된 코드가 제거 될 수 있습니다.


11
이 방법이 작동하는 동안 addToBackStack (null)을 사용하는 경우 뒤로 단추 핸들러 +1을 그대로 둡니다. 따라서 두 번 눌러야합니다.
user123321 2018 년

34
FragmentManager에서 조각을 "팝"합니다.
user123321

2
위의 절차를 시도했지만 "java-lang-illegalstateexception-can-not-for-per-form-this-action-after-onaveinstance"오류가 발생합니다. 정확히 조각을 제거해야하는 곳
KK_07k11A0585

6
이 답변은 나쁜 습관이며 투표를해서는 안됩니다. 프래그먼트는 이와 같이 자각하지 않습니다. 그것은 조각의 요점 인 재사용 성을 죽입니다! 프래그먼트는 액티비티에 신호를 보내서 여러 수단을 통해 제거해야합니다. 콜백 인터페이스 방법이 널리 사용됩니다. developer.android.com/training/basics/fragments/…
colintheshots

2
@ManfredMoser 동의하지 않습니다. 이것이 바로 질문의 요점입니다. 그는 제거 할 전체 조각 시퀀스를 가지고 있습니다. 이 코드에는 활동이 연결되어 있는지 여부를 확인하거나 확인하지 않습니다. 프래그먼트가 알지 못하는 너무 많은 것들에 의존하기 때문에 프로덕션에서 깨질 것입니다.
colintheshots

263

아래 방법을 사용할 수 있습니다.

getActivity().getSupportFragmentManager().popBackStack();

44
이 대답은 받아 들인 것보다 10 배나 좋습니다.
nikib3ro

50
또한 허용 된 것보다 디자인과 관련하여 10 배 더 나쁩니다. 조각은 활동에 작은 "조력자"가되어야하며 자신이나 다른 조각을 통제 할 수 없어야합니다.
Patrick

6
@avalancha가 지적했듯이 해결책이 올바르지 않습니다. developer.android.com/guide/components/…를
the_dark_destructor

2
이 메소드 onActivityResult를 사용하고 있으며 "onSaveInstanceState 후에이 조치를 수행 할 수 없습니다"라는 오류가 발생합니다. 어떻게 해결할 수 있습니까?
Jayeshkumar Sojitra

1
popBackStack()조각을 삭제 한 후 작업 표시 줄 제목을 이전 상태로 다시 설정하려는 경우 작동하는 유일한 솔루션입니다. 그렇지 않으면 stackoverflow.com/questions/13472258/의 높은 등급의 솔루션 과 다양한 사용 사례 후에 항상 적절한 조치 표시 줄 제목을 설정하기 위해이 솔루션 을 결합 할 필요가 없습니다 . 뒤로 누르기, 삭제, 바꾸기 추가 등.
Bevor

36

CommonsWare가 말했듯이 활동이 프래그먼트 추가 및 제거를 처리하도록 리스너를 사용하도록해야합니다. 예를 들면 다음과 같습니다.

public class MyActivity extends FragmentActivity implements SuicidalFragmentListener {

    // onCreate etc

    @Override
    public void onFragmentSuicide(String tag) {
        // Check tag if you do this with more than one fragmen, then:
        getSupportFragmentManager().popBackStack();
    }
}

public interface SuicidalFragmentListener {
    void onFragmentSuicide(String tag);
}

public class MyFragment extends Fragment {

    // onCreateView etc

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
           suicideListener = (SuicidalFragmentListener) activity;
        } catch (ClassCastException e) {
           throw new RuntimeException(getActivity().getClass().getSimpleName() + " must implement the suicide listener to use this fragment", e);
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Attach the close listener to whatever action on the fragment you want
        addSuicideTouchListener();
    }

    private void addSuicideTouchListener() {
        getView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              suicideListener.onFragmentSuicide(getTag());
            }
        });
    }
}

5
자살 많은 이모 스타일? "SelfClosing"또는 "AutoClose"또는 "SmartClose"(r)는
어떻습니까

21
그것은 죽지 않아 영원히 죽어가는 ;-(
Blundell

3
이것은 다른 답변보다 훨씬 깨끗한 접근법입니다. 액티비티는 프래그먼트를 생성 및 표시하며 라이프 사이클을 제어해야합니다. 프래그먼트가 더 이상 보이지 않아야 함을 나타내는 무언가가 발생하면 액티비티에 액티비티에게 알리고 액티비티가 제거하도록해야합니다.
Christopher Pickslay

7
기술적으로, 우리가 활동으로 인해 조각을 죽여야한다면 조각은 자살하지 않습니다. 활동은 혐오입니다.
케이시 머레이

17

Activity / AppCompatActivity에서 :

@Override
public void onBackPressed() {
    if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
        // if you want to handle DrawerLayout
        mDrawerLayout.closeDrawer(GravityCompat.START);
    } else {
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            super.onBackPressed();
        } else {
            getFragmentManager().popBackStack();
        }
    }
}

그런 다음 조각을 호출하십시오.

getActivity().onBackPressed();

다른 답변에 언급 된 것처럼 조각에서 이것을 호출하십시오.

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

5

새 탐색 구성 요소를 사용하는 경우 다음과 같이 간단합니다.

findNavController().popBackStack()

모든 FragmentTransaction을 뒤에 수행합니다.


4

DialogFragment가 요구 사항을 충족하는지 확인하십시오. DialogFragment에는 dismiss () 메서드가 있습니다. 내 의견으로는 훨씬 더 깨끗합니다.


3

나는 그것을 위해 간단한 방법을 만듭니다.

popBackStack(getSupportFragmentManager());

내 ActivityUtils 클래스에 배치하는 것보다

public static void popBackStack(FragmentManager manager){
        FragmentManager.BackStackEntry first = manager.getBackStackEntryAt(0);
        manager.popBackStack(first.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

잘 작동하고 재미있게 보내십시오!


2
나는 당신의 방법의 목적을 얻지 못했습니다. 원래 popBackStack이 완전히 적합 해 보입니다.
놀라운 1

1

OnCreate :

//Add comment fragment
            container = FindViewById<FrameLayout>(Resource.Id.frmAttachPicture);
            mPictureFragment = new fmtAttachPicture();

            var trans = SupportFragmentManager.BeginTransaction();
            trans.Add(container.Id, mPictureFragment, "fmtPicture");
            trans.Show(mPictureFragment); trans.Commit();

이것이 클릭 이벤트 1에서 조각을 숨기는 방법입니다.

//Close fragment
    var trans = SupportFragmentManager.BeginTransaction();
    trans.Hide(mPictureFragment);
    trans.AddToBackStack(null);
    trans.Commit();

그런 다음 int 이벤트 2를 다시 표시합니다.

var trans = SupportFragmentManager.BeginTransaction();
            trans.Show(mPictureFragment); trans.Commit();

1

백 스택 히스토리의 네 번째 단편에서 첫 번째 단편으로 팝백해야하는 경우 태그를 사용하십시오 !!!

첫 번째 조각을 추가 할 때 다음과 같은 것을 사용해야합니다.

getFragmentManager.beginTransaction.addToBackStack("A").add(R.id.container, FragmentA).commit() 

또는

getFragmentManager.beginTransaction.addToBackStack("A").replace(R.id.container, FragmentA).commit()

그리고 조각 B, C 및 D를 표시하려면 다음을 사용하십시오.

getFragmentManager.beginTransaction.addToBackStack("B").replace(R.id.container, FragmentB, "B").commit()

다른 편지들 ...

FragmentA로 돌아가려면 popBackStack(0, "A")예를 호출 하고 추가 할 때 지정한 플래그를 addToBackStack()사용하십시오. 그리고 대체 또는 추가 명령에 사용 된 플래그가 아니라 명령에서 동일한 플래그 여야합니다 .

천만에요 ;)


'popBackStack (0, "A")'을 테스트했으며 내 앱이 프래그먼트 A로 돌아 왔지만 해당 프래그먼트 만 Back Stack에서 제거하고 싶습니다 ... 화면에 표시하지 않고 Stack에서 프래그먼트를 제거하는 방법은 무엇입니까 ??
KryNaC

1

같은 조각 안에있는 동안 조각을 닫으려면

getActivity().onBackPressed();

-9

왜 그냥 :

getActivity (). finish ();


4
조각 만이 아니라 전체 활동이 완료됩니다.
Murtadha S.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.