예외 가져오기 "IlgalStateException:SaveInstanceState 이후에는 이 작업을 수행할 수 없습니다."
저는 라이브 안드로이드 애플리케이션을 가지고 있고 시장에서 스택 추적을 받았는데 애플리케이션 코드에서 발생하지 않는 이유를 알 수 없지만 애플리케이션의 일부 또는 다른 이벤트로 인해 발생합니다(추정).
프래그먼트를 사용하고 있지는 않지만, 프래그먼트 매니저의 레퍼런스가 있습니다.만약 누군가가 이런 종류의 문제를 피하기 위해 몇몇 숨겨진 사실들을 밝힐 수 있다면:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1109)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:399)
at android.app.Activity.onBackPressed(Activity.java:2066)
at android.app.Activity.onKeyDown(Activity.java:1962)
at android.view.KeyEvent.dispatch(KeyEvent.java:2482)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1720)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1258)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2851)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2824)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2011)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
이것은 내가 지금까지 본 것 중에 가장 바보 같은 벌레입니다.API < 11, API > 11에 대해 완벽하게 작동하는 애플리케이션을 가지고 있었습니다.
저는 그들이 내부에서 무엇을 바꾸었는지 정말 알 수가 없었습니다.Activity통화 중 라이프사이클saveInstance, 이 문제를 해결한 방법은 이렇습니다.
@Override
protected void onSaveInstanceState(Bundle outState) {
//No call for super(). Bug on API Level > 11.
}
나는 단지 전화를 하지 않을 뿐입니다..super()그리고 모든게 잘 작동합니다.이것이 당신의 시간을 절약할 수 있기를 바랍니다.
편집: 좀 더 조사한 결과 지원 패키지의 알려진 버그입니다.
인스턴스를 저장하고 해당 인스턴스에 추가해야 하는 경우outState Bundle다음을 사용할 수 있습니다.
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
super.onSaveInstanceState(outState);
}
EDIT2: 이 문제는 다음에 트랜잭션을 수행하려는 경우에도 발생할 수 있습니다.Activity백그라운드에서 사라졌습니다.이를 방지하려면 다음을 사용해야 합니다.commitAllowingStateLoss()
EDIT3: 내가 기억하는 바로는 위의 솔루션들은 초기 지원.v4 라이브러리들의 문제들을 해결하고 있었습니다.그러나 여전히 문제가 있는 경우 @AlexLockwood 블로그: Fragment Transactions & Activity State Loss도 읽어봐야 합니다.
블로그 게시물 요약 (단, 꼭 읽어보길 강력히 추천합니다) :
- 하지 마십시오.
commit()이후의 거래onPause()허니컴 전에, 그리고onStop()허니컴 이후에 - 내부거래시 주의
Activity라이프사이클 메소드. 사용onCreate(),onResumeFragments()그리고.onPostResume() - 비동기 콜백 메서드 내에서 트랜잭션 수행 안 함
- 사용하다
commitAllowingStateLoss()궁여지책으로
이 문제의 원인이 무엇인지에 대한 Android 소스 코드를 살펴보니 플래그 mStateSaved inFragmentManagerImplclass(Activity에서 사용 가능한 인스턴스)의 값이 true입니다.호출 시 백스택이 저장(SaveAllState)되면 true로 설정됩니다.Activity#onSaveInstanceState 후 에서 전화가 . 그 후 활동에서 전화가 걸려온 내용스레드에서 사용 가능한 재설정 방법을 사용하여 이 플래그를 재설정하지 않음FragmentManagerImpl#noteStateNotSaved()그리고.dispatch().
제가 보기에 앱이 무엇을 하고 사용하는지에 따라 사용 가능한 수정 사항이 몇 가지 있습니다.
좋은 방법들
다른 무엇보다도:알렉스 락우드 기사를 광고하고 싶습니다.그럼 지금까지 해온 일을 보면 다음과 같습니다.
상태 정보를 보관할 필요가 없는 단편 및 활동에 대해서는 commit을 호출합니다.상태 손실을 허용합니다.문서에서 가져온 내용:
활동 상태가 저장된 후에 커밋을 실행할 수 있습니다.나중에 활동 상태를 복원해야 할 경우 커밋이 손실될 수 있기 때문에 위험하므로 UI 상태가 사용자의 상태에서 예기치 않게 변경되어도 무방한 경우에만 사용해야 합니다.프래그먼트에 읽기 전용 정보가 표시되는 경우 사용해도 괜찮은 것 같습니다.또는 편집 가능한 정보를 표시하더라도 콜백 메소드를 사용하여 편집된 정보를 유지합니다.
거래가 커밋된 직후(방금 전화를 걸었습니다) 로 전화를 걸으십시오.
권장되지 않는 방법:
위에 언급된 Ovidiu Latcu와 같이, 전화하지 마세요.
super.onSaveInstanceState()을 의미합니다 하지만 이것은 당신이 파편 상태와 함께 전체 활동 상태를 잃게 된다는 것을 의미합니다.덮어쓰기
onBackPressed그리고 그 안에서만finish(). 응용 프로그램이 프래그먼트 API를 사용하지 않는 경우에는 이 방법이 좋습니다.super.onBackPressed에 대한 요구가 있습니다.FragmentManager#popBackStackImmediate().Fragments API를 모두 사용하고 있고 활동 상태가 중요/중요한 경우 reflection API를 사용하여 호출을 시도할 수 있습니다.
FragmentManagerImpl#noteStateNotSaved()도 있습니다 하지만 이건 해킹이고, 아니면 누군가는 이것이 해결책이라고 말할 수도 있습니다.마음에 들지 않지만, 저 같은 경우는 사용하지 않는 코드를 사용하는 레거시 앱의 코드를 가지고 있기 때문에 상당히 허용됩니다 (TabActivity은연중에LocalActivityManager).
아래는 반사를 사용하는 코드입니다.
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
invokeFragmentManagerNoteStateNotSaved();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void invokeFragmentManagerNoteStateNotSaved() {
/**
* For post-Honeycomb devices
*/
if (Build.VERSION.SDK_INT < 11) {
return;
}
try {
Class cls = getClass();
do {
cls = cls.getSuperclass();
} while (!"Activity".equals(cls.getSimpleName()));
Field fragmentMgrField = cls.getDeclaredField("mFragments");
fragmentMgrField.setAccessible(true);
Object fragmentMgr = fragmentMgrField.get(this);
cls = fragmentMgr.getClass();
Method noteStateNotSavedMethod = cls.getDeclaredMethod("noteStateNotSaved", new Class[] {});
noteStateNotSavedMethod.invoke(fragmentMgr, new Object[] {});
Log.d("DLOutState", "Successful call for noteStateNotSaved!!!");
} catch (Exception ex) {
Log.e("DLOutState", "Exception on worka FM.noteStateNotSaved", ex);
}
}
건배!
프래그먼트 활동 후 프래그먼트 전환을 수행하려고 하면 이러한 예외가 발생합니다.onSaveInstanceState()부름을 받습니다.
이런 일이 일어날 수 있는 한 가지 이유는, 만약 당신이 그 일을 떠난다면,AsyncTask(또는Thread활동이 중지되면 실행됩니다.
이후의 전환onSaveInstanceState()는 시스템이 리소스에 대한 활동을 회수하고 나중에 다시 생성할 경우 잠재적으로 손실될 수 있습니다.
조각을 표시하기 전에 postResume()에서 super.를 호출하거나 postResume()을 호출한 후에 postResume() 메서드에서 코드를 이동하면 됩니다.이렇게 하면 문제가 해결됩니다!
전화를 걸 때도 이 문제가 발생할 수 있습니다.dismiss()화면이 잠겨 있고 활동 + 대화상자의 인스턴스 상태가 저장된 후 대화상자 조각에 저장됩니다.전화를 끊으려면 다음과 같이 하십시오.
dismissAllowingStateLoss()
말 그대로 내가 대화를 무시할 때마다 나는 더 이상 대화 상태에 관심이 없기 때문에, 이것은 해도 괜찮습니다. 당신은 실제로 어떤 상태도 잃지 않습니다.
짧고 효과적인 솔루션:
간단한 단계를 따릅니다.
1단계 : 각 프래그먼트에서 SaveInstanceState 상태를 재정의합니다.그리고 거기서 슈퍼 메소드를 제거합니다.
@Override
public void onSaveInstanceState(Bundle outState) {
};
2단계 : 단편 작업 중 커밋() 대신 커밋AllowingStateLoss()를 사용합니다.
fragmentTransaction.commitAllowingStateLoss();
라이프사이클 상태가 Android 지원 lib v26.1.0부터 시작되는 이러한 충돌을 방지하는 데 도움이 될 수 있다고 생각합니다.
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)){
// Do fragment's transaction commit
}
또는 다음을 시도할 수 있습니다.
Fragment.isStateSaved()
여기 https://developer.android.com/reference/android/support/v4/app/Fragment.html#isStateSaved() 에서 더 많은 정보를 보실 수 있습니다.
이게 내겐 통했어요제가 알아서 알아냈는데...도움이 되기를 바랍니다!
1) 글로벌 "static" FragmentManager / FragmentTransaction이 없습니다.
2) Create에서는 항상 Fragment Manager를 다시 초기화합니다!
아래 샘플 :-
public abstract class FragmentController extends AnotherActivity{
protected FragmentManager fragmentManager;
protected FragmentTransaction fragmentTransaction;
protected Bundle mSavedInstanceState;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedInstanceState = savedInstanceState;
setDefaultFragments();
}
protected void setDefaultFragments() {
fragmentManager = getSupportFragmentManager();
//check if on orientation change.. do not re-add fragments!
if(mSavedInstanceState == null) {
//instantiate the fragment manager
fragmentTransaction = fragmentManager.beginTransaction();
//the navigation fragments
NavigationFragment navFrag = new NavigationFragment();
ToolbarFragment toolFrag = new ToolbarFragment();
fragmentTransaction.add(R.id.NavLayout, navFrag, "NavFrag");
fragmentTransaction.add(R.id.ToolbarLayout, toolFrag, "ToolFrag");
fragmentTransaction.commitAllowingStateLoss();
//add own fragment to the nav (abstract method)
setOwnFragment();
}
}
onActivityForResult() 메서드에서 fragment를 표시하려고 하면 항상 다음과 같은 문제가 발생했습니다.
- 내 활동이 일시 중지되고 중지되었습니다. 즉, SaveInstanceState()가 이미 호출되었음을 의미합니다(Honeycomb 이전 장치와 Honeycomb 이후 장치 모두에 대해).
- 만일의 경우 프래그먼트를 표시/숨기기 위해 트랜잭션을 수행했고, 이로 인해 이 LegalState Exception이 발생합니다.
제가 만든 것은 다음과 같습니다.
- 원하는 작업이 수행되었는지 여부를 결정하기 위한 추가 값(예: 카메라에서 사진 촬영 - isPhotoTaken) - 필요한 트랜잭션의 양에 따라 부울 값 또는 정수 값이 될 수 있습니다.
- Resume Fragments() method를 오버라이드하여 내 값을 확인하고 프래그먼트 트랜잭션을 수행한 후 필요한 값을 확인했습니다.이 경우 ResumeFragments() 메서드에서 상태가 반환되었기 때문에 SaveInstanceState 이후 commit()가 수행되지 않았습니다.
on configuration이 변경되어 문제를 해결하였습니다.Android 활동 수명 주기에 따라 intent(카메라 intent 또는 다른 intent)를 명시적으로 호출하면 활동이 일시 중지되고 저장된 인스턴스가 호출됩니다.장치를 활동이 활성화된 위치가 아닌 다른 위치로 회전할 때 fragment commit와 같은 fragment 작업을 수행하면 불법 상태 예외가 발생합니다.그것에 대한 불만이 많습니다.그것은 안드로이드 활동 라이프사이클 관리와 적절한 메소드 호출에 관한 것입니다.이 문제를 해결하기 위해 다음 작업을 수행했습니다. 1-활동의 저장된 인스턴스 메서드를 재정의하고 현재 화면 방향(세로 또는 가로)을 결정한 다음 활동이 일시 중지되기 전에 화면 방향을 설정합니다.이렇게 하면 활동이 다른 활동에 의해 회전된 경우에 대비하여 화면 회전을 잠급니다. 2-활동 재개 방법을 재정의하고 지금 방향 모드를 센서로 설정하여 onsaved 메서드가 호출된 후 제대로 회전을 처리하도록 설정합니다.
이 코드를 작업에 복사/붙여넣어 처리할 수 있습니다.
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Toast.makeText(this, "Activity OnResume(): Lock Screen Orientation ", Toast.LENGTH_LONG).show();
int orientation =this.getDisplayOrientation();
//Lock the screen orientation to the current display orientation : Landscape or Potrait
this.setRequestedOrientation(orientation);
}
//A method found in stackOverflow, don't remember the author, to determine the right screen orientation independently of the phone or tablet device
public int getDisplayOrientation() {
Display getOrient = getWindowManager().getDefaultDisplay();
int orientation = getOrient.getOrientation();
// Sometimes you may get undefined orientation Value is 0
// simple logic solves the problem compare the screen
// X,Y Co-ordinates and determine the Orientation in such cases
if (orientation == Configuration.ORIENTATION_UNDEFINED) {
Configuration config = getResources().getConfiguration();
orientation = config.orientation;
if (orientation == Configuration.ORIENTATION_UNDEFINED) {
// if height and widht of screen are equal then
// it is square orientation
if (getOrient.getWidth() == getOrient.getHeight()) {
orientation = Configuration.ORIENTATION_SQUARE;
} else { //if widht is less than height than it is portrait
if (getOrient.getWidth() < getOrient.getHeight()) {
orientation = Configuration.ORIENTATION_PORTRAIT;
} else { // if it is not any of the above it will defineitly be landscape
orientation = Configuration.ORIENTATION_LANDSCAPE;
}
}
}
}
return orientation; // return value 1 is portrait and 2 is Landscape Mode
}
@Override
public void onResume() {
super.onResume();
Toast.makeText(this, "Activity OnResume(): Unlock Screen Orientation ", Toast.LENGTH_LONG).show();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
동일한 문제가 발생했습니다. 불법 상태 예외를 얻지만 커밋할 모든 호출을 커밋으로 바꿉니다.상태 손실()을 허용해도 도움이 되지 않았습니다.
범인은 DialogFragment.show()로 전화를 걸었습니다.
에워싸고 있습니다.
try {
dialog.show(transaction, "blah blah");
}
catch(IllegalStateException e) {
return;
}
그것도 해냈습니다.좋아요, 대화상자를 보여주지는 못하겠지만, 이 경우에는 괜찮았습니다.
내 앱에서 프래그먼트 매니저에게 처음 전화를 걸었던 곳은 그곳뿐이었습니다.beginTransaction()이지만 commit()을 호출한 적이 없어서 "commit()"을 찾을 때 찾지 못했습니다.
재미있는 것은 사용자가 앱을 절대 떠나지 않는다는 것입니다.대신에 살인자는 애드몹의 간교성 광고가 나타났습니다.
그 문제에 대한 나의 해결책은
프래그먼트 추가 메서드의 경우:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
guideMapFragment = (SupportMapFragment)a.getSupportFragmentManager().findFragmentById(R.id.guideMap);
guideMap = guideMapFragment.getMap();
...
}
@Override
public void onDestroyView() {
SherlockFragmentActivity a = getSherlockActivity();
if (a != null && guideMapFragment != null) {
try {
Log.i(LOGTAG, "Removing map fragment");
a.getSupportFragmentManager().beginTransaction().remove(guideMapFragment).commit();
guideMapFragment = null;
} catch(IllegalStateException e) {
Log.i(LOGTAG, "IllegalStateException on exit");
}
}
super.onDestroyView();
}
나쁠 수도 있지만 더 좋은 것을 찾을 수 없었습니다.
이 문제가 생겼어요.하지만 나는 이 문제가 커밋과 커밋과는 관련이 없다고 생각합니다.상태 손실을 허용합니다.
다음 스택 추적 및 예외 메시지는 commit()에 관한 것입니다.
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
그러나 이 예외는 onBackPressed()로 인해 발생했습니다.
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(Unknown Source)
at android.support.v4.app.FragmentActivity.onBackPressed(Unknown Source)
모두 checkStateLoss()로 인해 발생했습니다.
private void checkStateLoss() {
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
SaveInstanceState에 있는 후 mStateSaved가 true가 됩니다.
이런 문제는 거의 일어나지 않습니다.저는 이 문제에 대해 한 번도 접해본 적이 없습니다.문제가 재발할 수 없습니다.
25517호를 찾았습니다.
다음과 같은 상황에서 발생했을 수 있습니다.
Back 키는 SaveInstanceState 이후에 호출되지만 새 작업이 시작되기 전에 호출됩니다.
그 문제의 근원이 무엇인지 잘 모르겠습니다.그래서 저는 못난 방법을 썼습니다.
@Override
public void onBackPressed() {
try{
super.onBackPressed();
}catch (IllegalStateException e){
// can output some information here
finish();
}
}
제 앱에도 같은 문제가 있습니다.저는 이 문제를 해결했습니다.super.onBackPressed();지난 수업에서 전화를 했습니다.commitAllowingStateLoss()그 조각들을 가지고 있는 현재의 클래스에서.
사용자가 새 방향과 관련된 리소스를 로드할 수 있도록 화면을 돌리면 onSaveInstance가 호출됩니다.
이 사용자가 화면을 회전한 후 뒤로 버튼을 눌렀을 수 있습니다(이 사용자가 앱을 사용하는 동안 전화기를 더듬었을 수도 있기 때문입니다)
이 문제를 해결하기 위한 또 다른 라이프사이클 방법은 최신 출시된 라이프사이클-ktx를 kotlin과 함께 사용하는 것입니다.
lifecycleScope.launchWhenResumed {
// your code with fragment or dialogfragment
}
종료는 재개 상태 이후에 진행되기 때문에 이 방법도 중단 후에 호출하기 때문에 다음 이력서가 오면 안전하게 종료됩니다.
다음과 같이 선택할 수도 있습니다.
lifecycleScope.launchWhenCreated
// or
lifecycleScope.launchWhenStarted
상황에 맞게 말입니다.
파괴가 오면 코드가 취소됩니다.
구글 문서 링크: https://developer.android.com/kotlin/ktx#lifecycle
http://chris-alexander.co.uk/on-engineering/dev/android-fragments-within-fragments/ 읽기
기사.fragment.isResume() 검사를 수행하면 SaveInstanceState 메서드를 사용하여 DestroyView에 액세스할 수 있습니다.
저도 같은 문제로 하루 동안 모든 기사, 블로그 및 스택 오버플로를 분석한 결과 간단한 해결책을 찾았습니다.저장된 InstanceState를 전혀 사용하지 마십시오. 코드 한 줄이 있는 조건입니다.프래그먼트 코드에 대해:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
.....
프래그먼트를 로드하려고 할 때 작업 상태가 onPause()로 변경될 때마다 발생합니다.예를 들어 데이터를 가져와 작업에 로드하려고 할 때 사용자가 일부 버튼을 클릭하고 다음 작업으로 이동할 때 발생합니다.
두 가지 방법으로 해결할 수 있습니다.
transaction.commit을 사용할 수 있습니다.transaction.commit() 대신 StateLoss()를 허용하여 단편을 로드하지만 수행된 커밋 작업이 손실될 수 있습니다.
아니면
프래그먼트를 로드할 때 활동이 재개 상태이고 일시 중지 상태가 되지 않는지 확인합니다.부울을 만들고 활동이 Pause() 상태로 진행되지 않는지 확인합니다.
@Override
public void onResume() {
super.onResume();
mIsResumed = true;
}
@Override
public void onPause() {
mIsResumed = false;
super.onPause();
}
프래그먼트를 로드하는 동안 액티비티가 존재하는지 확인하고 액티비티가 포그라운드인 경우에만 로드합니다.
if(mIsResumed){
//load the fragment
}
감사합니다 @gunar 하지만 더 좋은 방법이 있다고 생각합니다.
문서에 따르면:
* If you are committing a single transaction that does not modify the * fragment back stack, strongly consider using * {@link FragmentTransaction#commitNow()} instead. This can help avoid * unwanted side effects when other code in your app has pending committed * transactions that expect different timing. * * @return Returns true if there were any pending transactions to be * executed. */ public abstract boolean executePendingTransactions();
을 합니다.commitNow교체할 항목:
fragmentTransaction.commit();
FragmentManager.executePendingTransactions()
글쎄, 위의 모든 해결책을 성공적으로 시도한 후에 (기본적으로 나는 거래가 없기 때문에).
제 경우에는 AlertDialogs 및 ProgressDialog를 fragment로 사용하고 있었는데 Fragment Manager를 요청할 때 오류가 발생하기도 합니다.
저는 몇 가지 유사한 게시물을 혼합하는 방법을 발견했습니다.
이 솔루션은 3단계 솔루션으로, 모두 FragmentActivity에 대해 수행됩니다(이 경우 GenericActivity라고 함).
private static WeakReference<GenericActivity> activity = null; //To avoid bug for fragments: Step 1 of 3
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//To avoid bug for fragments: Step 2 of 3
activity = new WeakReference<GenericActivity>(this);
}
@Override
public FragmentManager getSupportFragmentManager(){
//To avoid bug for fragments: Step 3 of 3
if (this == activity.get()) {
return super.getSupportFragmentManager();
}
return activity.get().getSupportFragmentManager();
}
하나의 프래그먼트에서 start activity를 사용하면 이 예외가 발생합니다.
start activity를 결과에 사용하도록 변경하면 예외가 사라집니다 :)
그래서 쉽게 수정할 수 있는 방법은 startActivityForResult api :)를 사용하는 것입니다.
지도 조각 작업에서 인텐트 선택을 취소하기 위해 뒤로 버튼을 누를 때 이 예외가 발생했습니다.onResume()의 코드(프래그먼트 초기화 및 커밋 트랜잭션)를 onStart()로 교체하여 해결하였으며, 현재 앱은 정상적으로 동작하고 있습니다.도움이 되길 바랍니다.
이는 Android 4.2에서 수정되었으며 지원 라이브러리의 소스로도 수정되었습니다.[*]
원인(및 해결 방법)에 대한 자세한 내용은 Google 버그 보고서(http://code.google.com/p/android/issues/detail?id=19917 를 참조하십시오.
지원 라이브러리를 사용하는 경우 이 버그에 대해 오랫동안 걱정할 필요가 없습니다.[*].그러나 지원 라이브러리의 Fragment Manager를 사용하지 않고 직접 API를 사용하는 경우(즉, 지원 라이브러리의 Fragment Manager를 사용하지 않는 경우) Android 4.2 이하의 API를 대상으로 하는 경우 해결 방법 중 하나를 시도해야 합니다.
[*] 작성 당시 Android SDK Manager는 여전히 이 버그가 나타나는 이전 버전을 배포하고 있습니다.
편집 나는 분명히 여기에 해명을 덧붙이려고 합니다. 왜냐하면 나는 누가 이 답변을 반대했든 간에 분명히 혼란스러웠기 때문입니다.
이 예외를 삭제할 수 있는 몇 가지 다른(그러나 관련된)위의 제 답변은 질문에서 논의된 구체적인 사례, 즉 안드로이드의 버그가 수정된 것을 언급하는 것입니다.다른 이유로 이 예외가 발생하는 경우, 프래그먼트 상태가 저장된 후에 프래그먼트를 추가/제거하기 때문입니다.이러한 상황에 처한 경우 "Nested Fragments - IrgalState Exception "Can't perform this action on SaveInstanceState"가 도움이 될 수 있습니다.
이 문제에 대한 해결책은 좀 더 연구한 후에 당신의 프래그먼트 커밋을 온 이력서에 하는 것입니다.
출처 : https://wenchaojames.wordpress.com/2013/01/12/illegalstateexception-from-onactivityresult/
나의 사용 사례:청취자를 단편적으로 사용하여 어떤 일이 발생했음을 활동에 알렸습니다.콜백 방식으로 새로운 프래그먼트 커밋을 했습니다.이것은 처음부터 완벽하게 잘 작동합니다.그러나 방향 변경 시 저장된 인스턴스 상태로 작업이 다시 생성됩니다.이 경우 프래그먼트가 다시 생성되지 않으면 프래그먼트에 리스너가 있음을 의미하며, 이는 오래된 파괴된 활동입니다.어쨌든 콜백 메소드는 작업 시 트리거됩니다.파괴된 활동으로 연결되어 문제가 발생합니다.해결책은 현재 라이브 활동으로 청취자를 단편적으로 재설정하는 것입니다.이렇게 하면 문제가 해결됩니다.
제가 발견한 것은 만약 다른 앱이 대화형이고 배경 앱으로 터치를 보낼 수 있다면 거의 모든 배경 앱이 이 오류와 함께 충돌한다는 것입니다.인스턴스를 저장하거나 복원한 경우 트랜잭션을 수행할 때마다 확인해야 할 것 같습니다.
같은 오류 예외로 "onBackPressed()"를 실행 파일에 넣었습니다(보기를 사용할 수 있음).
myView.post(new Runnable() {
@Override
public void run() {
onBackPressed()
}
});
왜 그런지는 모르겠지만, 효과는 있어요!
활동이 일시 중지되었을 때 fragmentManager.popBackStackImmediate()를 호출할 수 있습니다.활동이 완료되지 않았지만 일시 중지되었으며 포그라운드가 아닙니다.popBackStackImmediate() 전에 활동이 일시 중지되었는지 여부를 확인해야 합니다.
아주 흥미로운 것을 발견했습니다.제 앱에 전화기의 갤러리를 열 수 있는 옵션이 있는데 기기가 어떤 앱을 사용할지 묻습니다. 거기서 대화상자에서 떨어진 회색 영역을 클릭하면 이 문제가 발생합니다.작업이 일시 중지에서 SaveInstanceState에서 다시 Resume으로 어떻게 진행되는지 확인했습니다. CreateView에서는 방문하지 않습니다.저는 이력서에서 거래를 하고 있습니다.그래서 제가 하게 된 것은 일시 중지에서는 무효화되지만 CreateView에서는 진실이라는 플래그를 설정하는 것입니다.플래그가 Resume에 참이면 on Commit을 수행하고, 그렇지 않으면 commit을 수행합니다.상태 손실 허용.계속해서 시간을 낭비할 수도 있지만 라이프사이클을 확인하고 싶었습니다.저는 sdk version 23이라는 장치를 가지고 있고, 이 문제는 없지만, 21이라는 다른 장치를 가지고 있고, 거기에 그것이 보입니다.
언급URL : https://stackoverflow.com/questions/7469082/getting-exception-illegalstateexception-can-not-perform-this-action-after-onsa
'programing' 카테고리의 다른 글
| 포인터 + 1이 4를 추가하는 이유 (0) | 2023.10.26 |
|---|---|
| jQuery.jax()에서 반환된 데이터를 필터링하려면 어떻게 해야 합니까? (0) | 2023.10.26 |
| 게시 시 Wordpress 게시 상태 수정 (0) | 2023.10.26 |
| inside spring-boot--application.yml-특수문자 사용법 # (0) | 2023.10.26 |
| 텍스트 상자에 레이블이 아닌 값을 자동으로 적용 (0) | 2023.10.26 |