[英]IllegalStateException: Can not perform this action after onSaveInstanceState - Android
I am trying to figure out why my android app crashes sometimes, with the above exception. 我试图弄清楚为什么我的Android应用程序有时崩溃,上面的例外。 I can't find the source of the problem from what the logcat says. 我无法从logcat所说的内容中找到问题的根源。
It happens rarely. 它很少发生。
Logcat output: Logcat输出:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360) at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1378) at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574) at android.support.v4.app.FragmentTabHost.onAttachedToWindow(FragmentTabHost.java:282) at android.view.View.dispatchAttachedToWindow(View.java:12752) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2577) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2584) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2584) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2584) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1427) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1192) at and java.lang.IllegalStateException:在android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360)在android.support.v4.app.FragmentManagerImpl.enqueueAction(之后的onSaveInstanceState无法执行此操作FragmentManager.java:1378 )在android.support.v4.app.BackStat.et.FotmentTabHost的android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)。 onAttachedToWindow(FragmentTabHost.java:282)在android.view.View.dispatchAttachedToWindow(View.java:12752)在android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2577)在android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java :2584)在android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2584)在android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2584)在android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1427)在机器人.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1192)at和 roid.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6231) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:788) at android.view.Choreographer.doCallbacks(Choreographer.java:591) at android.view.Choreographer.doFrame(Choreographer.java:560) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:774) at android.os.Handler.handleCallback(Handler.java:808) at android.os.Handler.dispatchMessage(Handler.java:103) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:5292) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640) at dalvik.system.NativeStart.main(Native Method) roid.view.ViewRootImpl $ TraversalRunnable.run(ViewRootImpl.java:6231)at android.view.Choreographer $ CallbackRecord.run(Choreographer.java:788)at android.view.Choreographer.doCallbacks(Choreographer.java:591)at android .view.Choreographer.doFrame(Choreographer.java:560)位于android.view上的android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:774)android.os.Handler.handleCallback(Handler.java:808)。在android.app.Looper.loop(Looper.java:193)上的Handler.dispatchMessage(Handler.java:103)位于android.app.ActivityThread.main(ActivityThread.java:5292)的java.lang.reflect.Method.invokeNative (本地方法)位于com.android.internal.os的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:824)的java.lang.reflect.Method.invoke(Method.java:515) .zygoteInit.main(ZygoteInit.java:640)at dalvik.system.NativeStart.main(Native Method)
Main Activity: 主要活动:
public class MainActivity extends FragmentActivity {
private FragmentTabHost mTabHost;
private UiLifecycleHelper uiHelper;
LocationClient mClient;
LocationRequest mRequest;
private String user;
private String userId;
private ImageButton addPlaceBtn;
private SQLiteDataSource datasource;
private TextView notifTextView;
private boolean appIsOn = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
setContentView(R.layout.activity_main);
datasource = new SQLiteDataSource(this);
datasource.open();
uiHelper = new UiLifecycleHelper(this, null);
uiHelper.onCreate(savedInstanceState);
if (isFacebookLoggedIn()) {
System.out.println("We are logged in!");
} else {
showLogin();
}
if (datasource.getAllImageItems().isEmpty()) {
Intent splash = new Intent(this, SplashActivity.class);
startActivity(splash);
}
addPlaceBtn = (ImageButton) findViewById(R.id.addPlace1);
uiHelper = new UiLifecycleHelper(this, null);
uiHelper.onCreate(savedInstanceState);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(),
android.R.id.tabcontent);
mTabHost.addTab(
mTabHost.newTabSpec("tab1").setIndicator("PREPARATE", null),
OffersFragmentActivity.class, null);
mTabHost.addTab(
mTabHost.newTabSpec("tab2").setIndicator("CATEGORII", null),
CategoriesActivity.class, null);
mTabHost.addTab(mTabHost.newTabSpec("tab3")
.setIndicator("CAIETE", null), BooksFragmentActivity.class,
null);
for (int i = 0; i < mTabHost.getTabWidget().getChildCount(); i++) {
mTabHost.getTabWidget().getChildAt(i)
.setBackgroundResource(R.drawable.tab_text_selector);
mTabHost.getTabWidget().setDividerDrawable(R.drawable.divider);
final TextView tv = (TextView) mTabHost.getTabWidget()
.getChildAt(i).findViewById(android.R.id.title);
if (tv == null)
continue;
else
tv.setTextColor(0xFFFFFFFF);
}
mTabHost.setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
switch (mTabHost.getCurrentTab()) {
case 0:
addPlaceBtn.setVisibility(View.VISIBLE);
break;
case 1:
addPlaceBtn.setVisibility(View.GONE);
break;
case 2:
addPlaceBtn.setVisibility(View.GONE);
break;
default:
break;
}
}
});
addPlaceBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (user != null && isOnline()) {
Intent i = new Intent(getApplication(),
CameraActivity.class);
startActivity(i);
} else if (user == null) {
// If user is not logged in, start login activity
Intent i = new Intent(getApplication(), LoginActivity.class);
startActivity(i);
} else if (!isOnline()) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
MainActivity.this);
alertDialogBuilder.setTitle("Internetul este oprit");
alertDialogBuilder
.setMessage("Pentru actualizarea continutului aveti nevoie de internet. Porniti acum?");
alertDialogBuilder.setPositiveButton("Da",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
// go to a new activity of the app
Intent settingsIntent = new Intent(
Settings.ACTION_DATA_ROAMING_SETTINGS);
settingsIntent
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(settingsIntent);
finish();
}
});
// set negative button: No message
alertDialogBuilder.setNegativeButton("Nu",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
// cancel the alert box and put a Toast to
// the user
finish();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
});
if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(this));
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search)
.getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
final Menu m = menu;
final MenuItem item = menu.findItem(R.id.action_notifications);
View actionView = item.getActionView();
notifTextView = (TextView) actionView.findViewById(R.id.notifTextView);
String unreadNotifs = datasource.countUnreadNotif();
if (!unreadNotifs.equals("0")) {
notifTextView.setText(unreadNotifs);
} else {
notifTextView.setVisibility(View.GONE);
}
item.getActionView().setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
m.performIdentifierAction(item.getItemId(), 0);
}
});
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_user) {
Intent i = new Intent(this, UserProfile.class);
i.putExtra("user", user);
i.putExtra("userId", userId);
startActivity(i);
return true;
}
if (id == R.id.action_notifications) {
Intent i = new Intent(this, Notifications.class);
startActivity(i);
return true;
}
return super.onOptionsItemSelected(item);
}
private boolean isFacebookLoggedIn() {
Session session = Session.getActiveSession();
if (session != null) {
// Session can be open, check for valid token
if (!session.isClosed()) {
if (!session.getAccessToken().equalsIgnoreCase("")) {
return true;
}
}
}
return false;
}
// FB Login Session and user info
public void showLogin() {
Intent i = new Intent(this, LoginActivity.class);
startActivity(i);
}
@Override
protected void onResume() {
super.onResume();
uiHelper.onResume();
appIsOn = true;
invalidateOptionsMenu();
if (!isOnline()) {
showGpsButton();
}
SharedPreferences preferences = getSharedPreferences("USERINFO",
Context.MODE_PRIVATE);
user = preferences.getString("name", null);
userId = preferences.getString("userId", null);
userId = preferences.getString("userId", null);
GCMActivity gcm = new GCMActivity(this);
gcm.registerIfNeeded();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
uiHelper.onSaveInstanceState(outState);
}
@Override
public void onPause() {
super.onPause();
uiHelper.onPause();
appIsOn = false;
}
@Override
public void onDestroy() {
super.onDestroy();
uiHelper.onDestroy();
datasource.deleteAllRows();
}
public void showGpsButton() {
LinearLayout buttonLayout = (LinearLayout) findViewById(R.id.gpsWarning);
buttonLayout.setVisibility(View.VISIBLE);
buttonLayout.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent settingsIntent = new Intent(
Settings.ACTION_DATA_ROAMING_SETTINGS);
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(settingsIntent);
finish();
}
});
}
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
return true;
}
return false;
}
}
I was experiencing a similar issue on KitKat. 我在KitKat上遇到了类似的问题。 But on Lollipop it seems to work fine. 但是在Lollipop上似乎工作得很好。 Regardless, we have to support many OS versions, right? 无论如何,我们必须支持许多操作系统版本,对吧? :) :)
The primary cause seems to be that the starting of a new activity is forcing the MainActivity
to pause before it's even completely finished creating. 主要原因似乎是新活动的开始迫使MainActivity
在完成创建之前暂停。 When it pauses, it saves the instance state right away. 当它暂停时,它会立即保存实例状态。 But since Fragment
instances get committed in a weird end-of-main-thread cycle, that start-pause-save cycle becomes out of order throwing this crash. 但是,由于Fragment
实例在一个奇怪的主线程循环周期中被提交,因此该开始 - 暂停 - 保存周期变得无序,从而导致崩溃。 And in some cases, it could be a race condition and happen sporadically. 在某些情况下,它可能是一种竞争条件,偶尔也会发生。
Here's some code that seems to fix it after repeated testing: 以下是一些似乎在重复测试后修复它的代码:
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
Handler hanlder = new Handler();
hanlder.post(new Runnable() {
@Override
public void run() {
if (isFacebookLoggedIn()) {
System.out.println("We are logged in!");
} else {
showLogin();
}
if (datasource.getAllImageItems().isEmpty()) {
Intent splash = new Intent(MainActivity.this, SplashActivity.class);
startActivity(splash);
}
}
});
}
The trick is to spawn a Handler
and post to the end of the main thread to guarantee it will happen after all Fragment
instances have been committed. 诀窍是生成一个Handler
并发布到主线程的末尾,以保证在所有Fragment
实例提交后它将发生。 Doing it in onPostCreate
instead of immediately in onCreate
should help the situation as well. 在onPostCreate
而不是在onCreate
中立即执行它也应该有助于这种情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.