我试图弄清楚为什么我的Android应用程序有时会崩溃,但有上述异常。我无法从logcat所说的内容中找到问题的根源。
很少发生。
Logcat输出:
java.lang.IllegalStateException:之后无法执行此操作 onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360) 在 android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1378) 在 android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) 在 android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574) 在 android.support.v4.app.FragmentTabHost.onAttachedToWindow(FragmentTabHost.java:282) 在android.view.View.dispatchAttachedToWindow(View.java:12752)at 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) 在android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1192)at android.view.ViewRootImpl $ TraversalRunnable.run(ViewRootImpl.java:6231) 在 android.view.Choreographer $ CallbackRecord.run(Choreographer.java:788) 在android.view.Choreographer.doCallbacks(Choreographer.java:591)at android.view.Choreographer.doFrame(Choreographer.java:560)at android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:774) 在android.os.Handler.handleCallback(Handler.java:808)处 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) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)at dalvik.system.NativeStart.main(原生方法)
主要活动:
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;
}
}
答案 0 :(得分:1)
我在KitKat上遇到了类似的问题。但是在Lollipop上似乎工作得很好。无论如何,我们必须支持许多操作系统版本,对吧? :)
主要原因似乎是新活动的开始迫使MainActivity
在完成创建之前暂停。当它暂停时,它会立即保存实例状态。但是,由于Fragment
实例在一个奇怪的主线程循环周期中被提交,因此该启动 - 暂停 - 保存周期变得无序,从而导致此崩溃。在某些情况下,它可能是一种竞争条件而且偶尔会发生。
以下是一些似乎在重复测试后修复它的代码:
@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);
}
}
});
}
诀窍是生成一个Handler
并发布到主线程的末尾,以保证在所有Fragment
实例提交后它将发生。在onPostCreate
中而不是在onCreate
中立即执行此操作也可以帮助解决问题。