프래그먼트를 사용하여 백 스택 지우기


244

내 안드로이드 앱을 허니컴으로 포팅했으며 조각을 사용하기 위해 큰 리팩터링을 수행했습니다. 이전 버전에서는 홈 버튼을 눌렀을 때 ACTIVITY_CLEAR_TOP백 스택을 재설정하기 위해 사용했습니다 .

이제 내 응용 프로그램은 여러 조각으로 구성된 단일 활동이므로 홈 버튼을 누르면 내부 조각 중 하나만 바꿉니다. 플래그 startActivity와 함께 사용하지 않고 백 스택을 지우려면 어떻게 ACTIVITY_CLEAR_TOP해야합니까?


백 스택을 사용하지 마십시오! 실제로 전체 효율성에 도움이되지 않습니다! 탐색 할 때마다 일반 replace () 또는 더 나은 제거 / 추가를 사용하십시오! stackoverflow.com/questions/5802141/…
stack_ved 2018 년

답변:


430

나는 비슷한 것을 여기에 올렸다.

Joachim의 답변, Dianne Hackborn의 답변 :

http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42

나는 단지 다음을 사용하여 끝났다.

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {    
    fm.popBackStack();
}

그러나 다음과 같이 사용할 수도 있습니다.

((AppCompatActivity)getContext()).getSupportFragmentManager().popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)

이름이 지정된 상태로 모든 상태가 팝업됩니다. 그런 다음 조각을 원하는 것으로 바꿀 수 있습니다.


8
뒤로 버튼을 한 번 이상 누르는 것과 같으므로 현재 보이는 조각을 변경합니다. (적어도 내가 시도했을 때)
Peter Ajtai

7
피터와 같은 문제가 있습니다. 많은 의미를 갖는 조각을 순환시키는 대신 모든 조각을 지우고 싶습니다. 예를 들어 스택의 모든 조각을 순차적으로 팝하여 필요하지 않은 수명주기 이벤트를 발생시킵니다.
브라이언 그리피

233
맨 위로 이동하려면 다음을 사용하십시오. fragmentManager.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Warpzit

53
fragmentManager를 사용하여 가치있는 것을 얻으십시오. popBackStackImmediate (null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 프래그먼트 애니메이션이 실행되지 못하도록 막아주었습니다.
roarster

17
이것은 제대로 작동하지 않습니다. – 사이에있는 모든 조각의 onStart에 대한 호출을 트리거합니다
James

165

@Warpzit의 의견에 대한 답변을 만들고 다른 사람들이 더 쉽게 찾을 수 있도록하기 위해.

사용하다:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

14
AppCompatActivity를 사용할 때이 방법으로 백 스택에서 모든 조각을 팝핑하는 것이 최신 v7-appCompat 라이브러리에서 손상되었다고 생각합니다. 내 응용 프로그램을 최신 v7-appCompat 라이브러리 (21.0.0)로 업데이트하고 새 AppCompatActivity를 확장 한 후 위와 같은 방식으로 조각을 터뜨리면 FragmentManager의 백 스택 레코드에 일부 조각이 남습니다. 나는 이것을 사용하지 말 것을 권합니다.
dell116

popBackStackImmediate를 사용할 수 있습니다.
Kannan_SJD

38

모든 관련 당사자에 대한 모든 존중; 얼마나 많은 사람들이 간단한 조각으로 전체 조각 다시 스택을 지울 수 있는지 매우 놀랐습니다.

fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

안드로이드 문서 에 따르면 (논리와 관련 name하여 주장 된 작업 제안서의 "널").

null의 경우, 최상위 상태 만이 팝된다

이제 특정 구현에 대한 지식이 부족하다는 것을 알고 있습니다 (예 : 주어진 시점에 백 스택에있는 항목 수). 잘 정의 된 것을 기대할 때 받아 들여진 대답에 모든 돈을 베팅 할 것입니다 광범위한 장치 및 공급 업체에서의 동작 :

(참고로 이것과 함께 뭔가)

FragmentManager fm = getFragmentManager(); // or 'getSupportFragmentManager();'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {    
    fm.popBackStack();
}

4
나를 위해 각 은 각 조각 의 onCreateView 로 내부적으로 이동하기 때문에 아닙니다 . 일부 리소스에서 NPE를받는 곳 그러나 fm.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 단순히 모든 백 스택을 죽였습니다.
sud007

1
루프를 사용하여 팝업 할 때 onCreateView 호출을 건너 뛰는 방법에 대한 통찰력이 있습니까?
Ayush Goyal

최상위 조각 (널)을 지우면 백 스택에서 조각 뒤에 오는 모든 조각이 지워집니다.
2b77bee6-5445-4c77-b1eb-4df3e5

18

루프를 사용하지 않고 나를 위해 쉬운 방법으로 작동합니다.

 FragmentManager fragmentManager = getSupportFragmentManager();
 //this will clear the back stack and displays no animation on the screen
 fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

17

받아 들여진 대답으로는 충분하지 않았습니다. 나는 사용해야했다 :

FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
    fm.popBackStackImmediate();
}

2
이것은 다른 대답으로 지적되었지만 주목해야합니다. 이처럼 전체 스택을 루프에 넣으면 스택의 시작과 끝 사이에있는 모든 조각에 대해 수명주기 메소드를 트리거합니다. . 대부분의 사용 사례에서이 구현이 의도하지 않은 결과를 초래할 가능성이 높습니다. 또한 popBackStackImmediate()트랜잭션을 동 기적으로 수행하는 것이 일반적으로 잘못 권장 된다는 점도 지적 할 가치가 있습니다.
Damien Diehl 2018 년

16

루프없이 명확한 백 스택

String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);

여기서 name 은 addToBackStack () 매개 변수입니다.

getSupportFragmentManager().beginTransaction().
                .replace(R.id.container, fragments.get(titleCode))
                .addToBackStack(name)

.frag 조각 스택을 교체하더라도 살아 있지만 보이지 않습니다
Asthme

8

방금 추가하고 싶었습니다 :-

다음을 사용하여 백 스택에서 튀어 나옴

fragmentManager.popBackStack ()

트랜잭션에서 조각을 제거하는 것입니다. 화면에서 조각을 제거하지는 않습니다. 따라서 이상적으로는 보이지 않지만 두 개 또는 세 개의 조각이 서로 겹쳐져있을 수 있으며 뒤로 키를 누르면 UI가 어수선하게 쌓일 수 있습니다.

간단한 예를 들면 다음과 같습니다.

fragmentmanager.replace ()를 사용하여 Fragmnet B를로드하는 fragmentA가 있고 addToBackStack을 수행하여이 트랜잭션을 저장 한다고 가정하십시오 . 흐름은 :-

1 단계-> FragmentA-> FragmentB (FragmentB로 옮겼지만 Fragment A는 백그라운드에 있으며 보이지 않습니다).

이제 fragmentB에서 일부 작업을 수행하고 저장 버튼을 누릅니다. 저장 후 조각 A로 돌아갑니다.

2 단계-FragmentB를 저장하면 FragmentA로 돌아갑니다.

3 단계-> 그래서 일반적인 실수는 ... 조각 B에서 조각 관리자로 조각 관리자 .replace () 조각 B를 수행합니다.

그러나 실제로 일어나는 일은 FragmentB를 대체하여 Fragment A를 다시로드하고 있습니다. 이제 두 개의 FragmentA가 있습니다 (하나는 STEP-1에서, 하나는이 STEP-3에서).

FragmentsA의 두 인스턴스가 서로 겹쳐져 표시되지 않을 수 있지만 거기에 있습니다.

따라서 위의 방법으로 백 스택을 지우더라도 트랜잭션은 지워지지 만 실제 조각은 지워지지 않습니다. 따라서 이상적으로는 저장 버튼을 누르면 fm.popBackStack () 또는 fm.popBackImmediate () 를 수행하여 fragmentA로 돌아 가면됩니다 .

따라서 올바른 Step3-> fm.popBackStack ()은 이미 메모리에있는 fragmentA로 돌아갑니다.


3

문서를 읽고 프래그먼트 ID가 무엇인지 연구하면 스택 인덱스 인 것처럼 보이므로 다음과 같이 작동합니다.

fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);

0스택의 맨 아래에 0 ( )이 포함되어 있으므로 스택을 비우면 스택이 지워집니다.

주의 사항 : 위의 프로그램에서 위의 작업을 수행하지만 FragmentManager 설명서에 실제로 id가 스택 인덱스라고 명시하지 않기 때문에 조금 주저합니다. 그것이 가능하다는 것이 합리적이며, 모든 디버그 로그는 그것이 사실임을 드러내지 만, 특별한 상황에서는 그렇지 않을 것입니까? 어느 쪽이든이 방법으로 확인할 수 있습니까? 그렇다면 위의 방법이 가장 좋습니다. 그렇지 않은 경우 이것은 대안입니다.

while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }

1
fragmentManager..getBackStackEntryAt(0).getId()0 대신 에 사용 하는 것은 어떻습니까? 백 스택 항목 ID가 스택 인덱스와 다른 지점에 있더라도 작동합니다.
ChristophK

3

이 방법을 사용하고 Context & Fragment 태그를 전달하여 백 스테이크 조각을 제거해야합니다.

용법

clearFragmentByTag(context, FragmentName.class.getName());



public static void clearFragmentByTag(Context context, String tag) {
    try {
        FragmentManager fm = ((AppCompatActivity) context).getSupportFragmentManager();

        for (int i = fm.getBackStackEntryCount() - 1; i >= 0; i--) {
            String backEntry = fm.getBackStackEntryAt(i).getName();
            if (backEntry.equals(tag)) {
                break;
            } else {
                 fm.popBackStack();
            }
        }
    } catch (Exception e) {
        System.out.print("!====Popbackstack error : " + e);
        e.printStackTrace();
    }
}

2

안녕하세요 ~ https://gist.github.com/ikew0ng/8297033 에서 훨씬 더 나은 솔루션을 찾았습니다.

    /**
 * Remove all entries from the backStack of this fragmentManager.
 *
 * @param fragmentManager the fragmentManager to clear.
 */
private void clearBackStack(FragmentManager fragmentManager) {
    if (fragmentManager.getBackStackEntryCount() > 0) {
        FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0);
        fragmentManager.popBackStack(entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }
}

2
이 솔루션이 더 나은 이유에 대한 답변을 확장하십시오.
Simon.SA

그것은 SDK가 자체적으로 제공하는 메커니즘을 사용하며 일부 NPE 문제를 일으키지 않습니다.
Chenxi

1

나는 이것을 이렇게 작동시켰다.

public void showHome() {
    getHandler().post(new Runnable() {
        @Override
        public void run() {
            final FragmentManager fm = getSupportFragmentManager();
            while (fm.getBackStackEntryCount() > 0) {
                fm.popBackStackImmediate();
            }
        }
    });
}

1

그것은 나를 위해 노력하고 있습니다, 이것을 시도하십시오 :

public void clearFragmentBackStack() {
        FragmentManager fm = getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
            fm.popBackStack();
        }
    }

0
    private void clearBackStack(){
        SupportFragmentManaer fm = getSupportFragmentManager();
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

이 메소드를 호출하면 매우 깔끔합니다.

  1. 루프가 필요하지 않습니다.
  2. 조각으로 애니메이션을 사용하는 경우 너무 많은 애니메이션이 표시되지 않습니다. 그러나 루프를 사용합니다.

0
private boolean removeFragFromBackStack() {
    try {
        FragmentManager manager = getSupportFragmentManager();
        List<Fragment> fragsList = manager.getFragments();
        if (fragsList.size() == 0) {
            return true;
        }
        manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

이 코드 스 니펫은 제한적이고 즉각적인 도움이 될 수 있습니다. 적절한 설명은 크게이 문제에 대한 좋은 해결책이 왜 보여 장기적인 가치를 향상 것이고, 다른 유사한 질문을 미래의 독자들에게 더 유용 할 것입니다. 제발 편집 당신이 만든 가정 등 일부 설명을 추가 할 답변을.
Abdelilah El Aissaoui
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.