-1

I am Creating a timer app with TabLayout one tab is Timer using a class CountDownTimer and another tab is Stopwatch using a class Chronometer with using MVVM architecture. the app is working properly in portrait mode. when I rotate the screen the app is crashed. The logcat log is given bellow.

2020-11-07 08:28:59.190 29332-29332/com.mpvaitheeswaran.timeranker D/AndroidRuntime: Shutting down VM
2020-11-07 08:28:59.199 29332-29332/com.mpvaitheeswaran.timeranker E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.mpvaitheeswaran.timeranker, PID: 29332
    java.lang.IllegalStateException: FragmentManager is already executing transactions
        at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1778)
        at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1814)
        at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
        at androidx.viewpager2.adapter.FragmentStateAdapter$FragmentMaxLifecycleEnforcer.updateFragmentMaxLifecycle(FragmentStateAdapter.java:726)
        at androidx.viewpager2.adapter.FragmentStateAdapter$FragmentMaxLifecycleEnforcer$3.onStateChanged(FragmentStateAdapter.java:657)
        at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
        at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
        at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
        at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
        at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
        at androidx.fragment.app.Fragment.performStart(Fragment.java:2735)
        at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:365)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1194)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
        at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2583)
        at androidx.fragment.app.Fragment.performStart(Fragment.java:2739)
        at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:365)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1194)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
        at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2583)
        at androidx.fragment.app.FragmentController.dispatchStart(FragmentController.java:258)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:550)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:210)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1391)
        at android.app.Activity.performStart(Activity.java:7165)
        at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2975)
        at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
        at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6718)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

See my full source of this project https://github.com/mpvaitheeswaran/TimeRanker/tree/withTabLayout

  • Have you tried search your error? "FragmentManager is already executing transactions" – xRed Nov 07 '20 at 03:05
  • You need to understand that when your app orientation or screen size changes, it triggers the `onConfigurationChanged()` method. https://stackoverflow.com/questions/48477168/keep-the-countdowntimer-running-after-orientation-change https://stackoverflow.com/questions/11368107/resuming-countdowntimer-after-rotation https://www.youtube.com/watch?v=LMYQS1dqfo8 – ecle Nov 07 '20 at 03:50
  • 1
    Share your code, please – Nazarii Moshenskiy Nov 07 '20 at 04:24
  • what is "this is my full source code".. I don't see it posted in your question. No pictures posting of code is aloud on SO. If the link refers to your complete code you need to update your question with the link and not via comment. Also, post the essential code that relates to your question here. End of Review. – ZF007 Nov 07 '20 at 19:29

1 Answers1

0

Now I solved this problem using Handler The problem is found in the creation of ViewPagerAdapter .

without using thread the app is crashed when configuration changes.

viewPagerAdapter=new ViewPagerAdapter(fragments,
                        requireActivity().getSupportFragmentManager(),
                        getLifecycle());
                viewPager.setAdapter(viewPagerAdapter);
                new TabLayoutMediator(tabLayout,viewPager,(tab, position) -> {
                    //TODO Implement tab Something
                    switch (position){
                        case 0:
                            tab.setText("Timer");
                            break;
                        case 1:
                            tab.setText("Stopwatch");
                            break;
                    }
                }).attach();

with using thread the app is working properly.

//The Handler is very important one Without thread the app crash when the configuration changes.
        Handler handler =new Handler();
        handler.post(new Runnable() {

            @Override
            public void run() {
                viewPagerAdapter=new ViewPagerAdapter(fragments,
                        requireActivity().getSupportFragmentManager(),
                        getLifecycle());
                viewPager.setAdapter(viewPagerAdapter);
                new TabLayoutMediator(tabLayout,viewPager,(tab, position) -> {
                    //TODO Implement tab Something
                    switch (position){
                        case 0:
                            tab.setText("Timer");
                            break;
                        case 1:
                            tab.setText("Stopwatch");
                            break;
                    }
                }).attach();
            }
        });

this app not necessary to restore data when the configuration changes because, I am using ViewModel to get data from CountDownTimer.

But it required on Chronometer I will fix this bug soon.