4

上記の例外を除いて、Androidアプリが時々クラッシュする理由を理解しようとしています。logcat の内容から問題の原因を見つけることができません。

めったに起こりません。

Logcat の出力:

java.lang.IllegalStateException: android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360) で onSaveInstanceState の後にこのアクションを実行できません 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) で android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2577) で android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java) :2584) android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2584) で android.view.ViewGroup.android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1192) で android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1427) で dispatchAttachedToWindow(ViewGroup.java:2584) android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl .java:6231) で Android.view.Choreographer$CallbackRecord.run(Choreographer.java:788) 560) android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:774) で android.os.Handler.handleCallback(Handler.java:808) で android.os.Handler.dispatchMessage(Handler.java:103) でandroid.os.Looper.loop(Looper.java:193) で android.app.ActivityThread.main(ActivityThread.java:5292) で java.lang.reflect.Method.invokeNative(Native Method) で java.lang.com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824) での Reflect.Method.invoke(Method.java:515) com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 640) 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;
    }
}
4

1 に答える 1

1

KitKat で同様の問題が発生していました。しかし、Lollipop では問題なく動作するようです。とにかく、多くの OS バージョンをサポートする必要がありますよね? :)

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はなく、それを行うことも状況を改善するはずです.onPostCreateonCreate

于 2015-03-26T19:42:39.457 に答える