developer tip

FragmentManager가 이미 트랜잭션을 실행하고 있습니다.

copycodes 2020. 11. 22. 19:57
반응형

FragmentManager가 이미 트랜잭션을 실행하고 있습니다. 커밋 후 호출기를 초기화하는 것이 안전합니까?


두 조각을 호스팅하는 활동이 있습니다. 액티비티는 객체를로드하는 동안 로더를 보여주기 시작합니다. 로드 된 객체는 newInstance 메서드를 통해 인수로 두 조각에 전달되고 해당 조각이 연결됩니다.

final FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.replace(R.id.container1, Fragment1.newInstance(loadedObject));
trans.replace(R.id.container2, Fragment2.newInstance(loadedObject));
trans.commit();

두 번째 조각에는 android.support.v4.view.ViewPager 및 탭이 포함되어 있습니다. onResume 우리는 다음과 같이 초기화합니다.

viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(adapter.getCount()); //the count is always < 4
tabLayout.setupWithViewPager(viewPager);

문제는 Android입니다.

java.lang.IllegalStateException : FragmentManager가 이미 트랜잭션을 실행 중입니다.

이 스택 추적으로 : ( android.support간결성을 위해 패키지 이름을 제거했습니다)

v4.app.FragmentManagerImpl.execSingleAction (FragmentManager.java:1620) at v4.app.BackStackRecord.commitNowAllowingStateLoss (BackStackRecord.java:637) at v4.app.FragmentPagerAdapter.finishUpdate (FragmentPagerAdapter.java:143) at v4.view.ViewPager .populate (ViewPager.java:1235) at v4.view.ViewPager.populate (ViewPager.java:1083) at v4.view.ViewPager.setOffscreenPageLimit (ViewPager.java:847)

데이터 setOffscreenPageLimit(...);는 제거 여부를 보여줍니다 . 이 문제를 피할 수있는 다른 방법이 있습니까?

수명주기에서 조각 트랜잭션이 완료되어 호출기를 설정할 때까지 기다릴 수 있습니까?


SDK 24 이상을 대상으로하는 경우 다음을 사용할 수 있습니다.

FragmentTransaction.commitNow()

대신에 commit()

이전 버전을 대상으로하는 경우 다음을 호출 해보십시오.

FragmentManager.executePendingTransactions()

에 대한 호출 후 commit()


간단하게 사용 childFragmentManger()하기위한 viewpager내부Fragment

mPagerAdapter = new ScreenSlidePagerAdapter(getChildFragmentManager());
mPager.setAdapter(mPagerAdapter);

두 조각을 빠르게 교체하고 executePendingTransactions ()를 사용할 때이 예외가 발생했습니다. 이것을 부르지 않고 예외는 없었습니다.

내 사건은 어땠어? 나는 조각 A를 열고 onResume () (조건 하에서) 조각을 조각 B로 교체하도록 활동에 요청합니다. 그 시점에서 예외가 발생합니다.

내 해결책은 쿼리를 즉시 실행하는 대신 스레드 대기열 끝에 배치하는 Handler.post (runnable)를 사용하는 것입니다. 이렇게하면 이전 트랜잭션이 완료된 후 새 트랜잭션이 실행됩니다.

그래서 내 솔루션은 다음과 같이 간단했습니다.

Handler uiHandler = new Handler();
uiHandler.post(new Runnable()
{
    @Override
    public void run()
    {
        openFragmentB(position);
    }
});

누군가 Robolectric> 3.6을 사용하고 ViewPager와 함께 4.0.2 이상을 사용하는 경우 올바른 코드로도 이것을 볼 수 있습니다.

Robolectric에 대한 문제를 추적하는 이 github 문제 에 관련 정보가 있습니다 .

이 답변을 작성할 때 문제가 해결되지 않았으며 알려진 유일한 해결 방법은 일부에서는 작동하는 것처럼 보이지만 나를 위해 작동하지 않는 @Config (sdk = {27})를 사용하거나 해결 방법으로 ViewPagerShadow를 구현하는 것입니다. github에서 참조 된 다소 긴 코드가 포함 된 테스트 패키지 (더 나은 경우 여기에 포함 할 수 있지만 답변으로 충분하지 않을 수 있습니까?) 및 @Config (shadows = {ShadowViewPager.class} 사용)


비슷한 문제가있었습니다.

mainAcitivity 추가 fragmentA.

그런 다음 FragmentA 콜백 mainactivity는 자신을 fragmentB로 대체합니다.

FragmentB로 트랜잭션을 교체하고 커밋 할 때 MainActivity에서 "fragmentmanager가 이미 트랜잭션을 실행 중"예외를 throw합니다.

문제는 실제로 fragmentB에서 발생합니다.

탭 조각을 추가하려면 getfragmentmanager ()가 필요한 조각 B에 TabHost가 있습니다.

Replace getfragmentmanager() by getchildfragmentmanager() in fragmentB solve the issue.


I used/extended my adapter with FragmentStatePagerAdapter instead of FragmentPagerAdapter this resolved my issue.

Use FragmentStatePagerAdapterif the fragments are dynamic and are changing frequently during run-time.

Use FragmentPagerAdapter if the fragments are static and do NOT change frequently during run-time.

enlightened from this article, https://medium.com/inloopx/adventures-with-fragmentstatepageradapter-4f56a643f8e0

참고URL : https://stackoverflow.com/questions/38722325/fragmentmanager-is-already-executing-transactions-when-is-it-safe-to-initialise

반응형