FragmentTransaction仅在纵向模式下工作

时间:2014-07-11 13:42:34

标签: java android android-fragments android-appcompat

我的Android代码非常奇怪。

实际问题是在代码之后。

我想要做的是让一个应用程序仅在手机上的肖像模式下工作,在平板电脑上以纵向和横向模式工作。为此,我在不同的文件夹中创建了三个bool.xml文件。这个位于文件夹值:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="portrait_only">true</bool>
</resources>

而在值-xlarge和values-sw600dp中,我把

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="portrait_only">false</bool>
</resources>

项目中唯一的活动是在启动时通过附加SplashScreenFragment加载启动画面。这是活动

public class MainActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getResources().getBoolean(R.bool.portrait_only)) 
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    if (getSupportActionBar() != null)
        getSupportActionBar().hide();
    setContentView(R.layout.activity_main);

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
        .add(R.id.container, new SplashScreenFragment()).commit();
    }
}
}

片段本身只是加载一个布局并启动一个更改片段的TimerTask。这是

public class SplashScreenFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_splash_screen, container, false);

        Timer splashScreenTimer = new Timer();
        splashScreenTimer.schedule(new SplashScreenTimerTask(getActivity()), 2000);

        return rootView;
    }

    private class SplashScreenTimerTask extends TimerTask {
        private FragmentActivity activity;

        public SplashScreenTimerTask(FragmentActivity activity) {
            this.activity = activity;
        }

        @Override
        public void run() {
            FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container, new FragmentMain());
            transaction.commit();
        }

    }

}

现在,如果我在手机上启动,应用程序处于纵向模式,一切都运行正常,而如果我在横向模式下使用移动设备启动应用程序,那么第一个片段会完全加载,但是当行

transaction.commit();

执行后,应用程序崩溃,logcat中出现以下错误

E/AndroidRuntime(17433): FATAL EXCEPTION: Timer-0
E/AndroidRuntime(17433): Process: it.assottica.android, PID: 17433
E/AndroidRuntime(17433): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
E/AndroidRuntime(17433):    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1354)
E/AndroidRuntime(17433):    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1372)
E/AndroidRuntime(17433):    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
E/AndroidRuntime(17433):    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
E/AndroidRuntime(17433):    at it.assottica.android.fragments.SplashScreenFragment$SplashScreenTimerTask.run(SplashScreenFragment.java:40)
E/AndroidRuntime(17433):    at java.util.Timer$TimerImpl.run(Timer.java:284)

有没有人知道为什么会这样,以及如何解决?但是,最重要的是,如果我在横向或纵向模式下使用移动设备启动应用程序,为什么一切正常?

1 个答案:

答案 0 :(得分:1)


我通过深入跟踪onPause,onStop中的Activity和Fragment实际执行的方法解决了我自己的问题。

与我的想法不同,当我在横向模式下使用移动设备开始定位时,活动和片段经历了以下过程:onCreateView - &gt; onPause - &gt; onStop - &gt; onDestroy - &gt; onCreateView,这与在方向中启动Activity然后更改屏幕方向时发生的过程完全相同。这导致Fragment被启动,然后被破坏然后重新启动,因此在第一次启动时创建的计时器试图获得实际上不存在的活动的支持片段管理器或者在执行之后执行事务。的onSaveInstanceState。

我通过取消片段的onDestroy()方法中的计时器来解决。