12

몇 년 전, 내 을 내 onActivityResult() 콜백에 투입하려고 할 때 내 앱 중 하나에서 문제가 발생했습니다. 주위에 인터넷 검색, 내가 onActivityResult()가 호출되는 시점에서onActivityResult() 안에 FragmentTransaction을 저지르는 것이 안전합니까?

this question and answer을 발견, 활동/조각의 상태는 아직 회복되지 않았을 수 있습니다, 따라서이 기간 동안 일어날 모든 거래는 결과로 손실됩니다 .

나는 내 애플 리케이션에 대한 동일한 답변에서 권장되는 솔루션을 채택하고 인생은 좋았다. 그러나 최근의 실험에 따르면 상황이 바뀌 었음을 알 수 있습니다. onActivityResult()에서 FragmentTransaction을 위탁하는 것이 안전합니다.

참고 :

The documentation for (support v4) FragmentManager.beginTransaction()이 같은 트랜잭션에 대한 안전 창을 정의하는 단편 트랜잭션 만 만들 수 있습니다/이전 상태를 절약 활동에 최선을 다하고 있습니다. 당신이 후 FragmentActivity.onSaveInstanceState() (이전 FragmentActivity.onStart 또는 FragmentActivity.onResume()를 수행하면, 오류를 얻을 것이다으로 트랜잭션을 커밋하려고하면.

the documentation for onActivityResult() 읽기, 나는

당신은 onResume() 직전에이 전화를받을 것입니다 참조 귀하의 활동이 다시 시작될 때

이렇게하면 onActivityResult()에서 다음 트랜잭션을 실행하는 것이 안전해야합니다. onStart()이 이미 호출되어 안전 창이 안쪽에 있습니다.

나는 이것을 시험해보기 위해 응용 프로그램을 만들었고, 내가 만든 대화 상자 조각을 성공적으로보고 있습니다. onActivityResult(). 같은 앱에서 활동 라이프 사이클 콜백을 기록하여 순서를 확인할 수 있었고, onStart(), onRestoreInstanceState(), 그리고 onActivityResult()을 매번 볼 수있었습니다.

나는 뭔가를 놓친가요? 또는 프레임 워크가 변경되어 onActivityResult()이 프래그먼트 트랜잭션의 안전한 장소로 보장됩니까? 이 동작은 API 수준에 따라 다릅니다.

문서를 읽는 것처럼 보이는 another question and answer이 있는데, 둘 다 1 년 이상 된 것이므로 특별히 안전한 장소로는 onActivityResult()을 참조하십시오.

+0

http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html – elmorabea

+0

@elmorabea에서 살펴보기 해당 블로그 게시물은 내가 처음 발견했을 때 발견 한 자료 중 하나입니다. 이 문제. 그러나 아래 azizbekian의 답변에 나와 있듯이 더 이상 FragmentTransactions를 실행하는 안전한 창에 대한 정확한 설명이 아닌 것 같습니다. –

답변

14

FragmentManager 클래스 내부 부울 변수가있다 소스

에 약간의 다이빙은 mStatedSaved을했다. 이 변수는 활동의 라이프 사이클 콜백에 따라 저장된 상태를 추적합니다. 즉시이 변수 false로 변경 될 때, 다음 프래그먼트 트랜잭션이 없는지

 

    private void checkStateLoss() { 
     if (mStateSaved) { 
      throw new IllegalStateException(
        "Can not perform this action after onSaveInstanceState"); 
     } 
     ... 
    } 
 

이 수단이 실행될 : Here's있어서, 즉, 공지의 예외를 던진다.이 변수는 활동 상태가 저장 될 때 true이됩니다 (즉, onSaveInstanceState()). 이전에 당신이 onActivityResult()에서 트랜잭션을 커밋 문제가 있다고 위로 질문

당신은 상기


. 즉, 이전에 mStateSavedfalse이 할당되지 않았으며 현재는 그렇습니다. 증서에 그렇습니다. 당신은 젤리 빈의 onActivityResult()이 해제의 구현을 볼 수있다, 반대로

 

    public void noteStateNotSaved() { 
     ... 
     mStateSaved = false; 
     ... 
    } 
 

: noteStateNotSaved()는 다음을 수행 할

 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     mFragments.noteStateNotSaved(); 
     ... 
    } 
 

:

다음은 O 릴리스에서 onActivityResult() 구현의

 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     int index = requestCode>>16; 
     if (index != 0) { 
      index--; 
      if (mFragments.mActive == null || index = mFragments.mActive.size()) { 
       Log.w(TAG, "Activity result fragment index out of range: 0x" 
         + Integer.toHexString(requestCode)); 
       return; 
      } 
      Fragment frag = mFragments.mActive.get(index); 
      if (frag == null) { 
       Log.w(TAG, "Activity result no fragment exists for index: 0x" 
         + Integer.toHexString(requestCode)); 
      } else { 
       frag.onActivityResult(requestCode&0xffff, resultCode, data); 
      } 
      return; 
     } 

     super.onActivityResult(requestCode, resultCode, data); 
    } 
 

변경 사항 없음 그 값은 mStateSaved 필드이며 트랜잭션이 커밋되면 예외가 throw됩니다.

실제로 Kit-Kat 릴리스의 mFragments.noteStateNotSaved()was introduced 줄입니다. 당신은 다이앤 Hackborn에 의해 만들어진 commit's comment에서 볼 수 있듯이 :

ActivityFragment는 이 onNewIntent()를받을 때 상태가 저장되어있는 플래그를 지워야합니다. 활동이 으로 재개되기 전에 일어날 수 있으므로 아직 취소하지 않았을 수 있습니다. onActivityResult()에 대해서도 건을 수행해야합니다.

최대

합계는 onActivityResult() 지금 조각 거래를위한 안전한 장소로 보장되어 있습니까?

2012 년 10 월에 만들어진 commit 4ccc001을 포함하는 소스를 사용한다고 가정 할 때 - 예, 조각 트랜잭션의 안전한 장소입니다.

+5

이 답변을 읽는 것은 순수한 기쁨입니다. 고맙습니다. – Vasiliy

+0

감사합니다, @ Vasiliy, 답변/대화도 즐기고 있습니다. – azizbekian

+1

@azizbekian 매우 통찰력있는 .... 완벽한 답변 .... –