16

I am using View pager with Tablayout in my project. I am continuously getting crash report on crashlytics. Below is the stack trace.

java.lang.IllegalStateException: commit already called
   at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:624)
   at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:620)
   at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:161)
   at android.support.v4.view.ViewPager.d(ViewPager.java:1105)
   at android.support.v4.view.ViewPager.d(ViewPager.java:951)
   at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1473)
   at android.view.View.measure(View.java:15635)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4919)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at android.view.View.measure(View.java:15635)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4919)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1411)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:698)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
   at android.view.View.measure(View.java:15635)
   at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:681)
   at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
   at android.view.View.measure(View.java:15635)
   at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:868)
   at android.view.View.measure(View.java:15635)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4919)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at android.support.v7.internal.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:124)
   at android.view.View.measure(View.java:15635)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4919)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1411)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:698)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
   at android.view.View.measure(View.java:15635)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4919)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at android.view.View.measure(View.java:15635)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4919)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1411)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:698)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
   at android.view.View.measure(View.java:15635)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4919)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2200)
   at android.view.View.measure(View.java:15635)
   at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2165)
   at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1249)
   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1443)
   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1139)
   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4872)
   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:776)
   at android.view.Choreographer.doCallbacks(Choreographer.java:579)
   at android.view.Choreographer.doFrame(Choreographer.java:548)
   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:762)
   at android.os.Handler.handleCallback(Handler.java:800)
   at android.os.Handler.dispatchMessage(Handler.java:100)
   at android.os.Looper.loop(Looper.java:194)
   at android.app.ActivityThread.main(ActivityThread.java:5371)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:525)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
   at dalvik.system.NativeStart.main(NativeStart.java)

Here is my xml file

<?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.DrawerLayout       
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/frame_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">

            <include
                android:id="@+id/toolbar"
                layout="@layout/toolbar" />

            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:background="@color/spice_laddooblue"
                app:tabMode="scrollable"
                android:layout_height="wrap_content" />

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <android.support.v4.view.ViewPager 
                    xmlns:android="http://schemas.android.com/apk/res/android"
                    android:id="@+id/pager"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                </android.support.v4.view.ViewPager>

            <android.support.design.widget.FloatingActionButton
                android:id="@+id/fab"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_share_white_24dp"
                android:layout_gravity="bottom|end"
                app:elevation="6dp"
                style="@style/floating_action_button"
                app:backgroundTint="@color/spice_laddooblue"
                app:pressedTranslationZ="12dp"/>
            </FrameLayout>


        </LinearLayout>

        <!--
              <View
            android:id="@+id/upper_view"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:visibility="visible" 
            android:layout_below = "@+id/pager"
            android:layout_above = "@+id/bannerView"/>
        -->

        <RelativeLayout
            android:id="@+id/bannerView"
            android:layout_width="match_parent"
            android:layout_height="58dp"
            android:layout_alignParentBottom="true"
            android:background="@drawable/curved_white_with_blue_border"
            android:visibility="gone">

            <TextView
                android:id="@+id/bannerText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_centerInParent="true"
                android:layout_centerVertical="true"
                android:gravity="center"
                android:padding="3dp"
                android:text="Banner"
                android:visibility="gone" />

            <ImageView
                android:id="@+id/bannerImage"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_alignParentLeft="true"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:gravity="center"
                android:padding="3dp"
                android:scaleType="fitXY"
                android:visibility="gone" />

            <ImageView
                android:id="@+id/bannerClose"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_centerVertical="true"
                android:src="@drawable/cross_icon" />
        </RelativeLayout>
    </RelativeLayout>

    <ExpandableListView
        android:id="@+id/left_drawer"
        android:layout_width="265dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#fff"
        android:choiceMode="singleChoice"
        android:divider="@null"
        android:dividerHeight="0dp"
        android:drawSelectorOnTop="true"
        android:groupIndicator="@null"
        android:scrollbars="@null" />

</android.support.v4.widget.DrawerLayout>

Adapter code

public class TabsPagerAdapter extends FragmentStatePagerAdapter {

    Context context;
    ViewPager pager;
    int count;

    public TabsPagerAdapter(FragmentManager fm, Context context, ViewPager pager ) {
        super(fm);
        this.context = context;
        this.pager = pager;

    }
    @Override
    public CharSequence getPageTitle(int position) {
        return ActivityMain.setdynamicTabsNames.get(position);
    }

    @Override
    public Fragment getItem(int index) {

        if (ActivityMain.setdynamicTabs.get(index).equalsIgnoreCase("HOME")) {
            return new FragmentIndex();
        else {
            return new FragmentDynamicTab(index);
        }
    }

        @Override
public int getCount() {
    return ActivityMain.setdynamicTabs.size();
}

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // supertabLayout.destroyItemsetupWithViewPager(container, position, objectviewPager);
    }

    public void setCount(int count) {
        this.count = count;
    }
}

I am setting tablayout like this in java code

 if (viewPager != null) {
     viewPager.setAdapter(tabAdapter);
     tabLayout.setupWithViewPager(viewPager);
  }

I have gone through all possible solutions available for this error..But none of them is working. I am unable to trace what is causing this exception.Any help will be appreciated.

Harry Sharma
  • 2,190
  • 2
  • 15
  • 41
  • Provide some code, how do you setup your TabLayout, at what line does it crash? This is not really helpful. – Marko Sep 01 '15 at 06:07
  • please see my edited question..I cant see where it crashes as i am not getting crash on my devices but on crashlytics i am getting this crash.. – Harry Sharma Sep 01 '15 at 06:13
  • Can you add the code for adapter aswell, you are probably adding Fragments there. – Marko Sep 01 '15 at 06:45
  • Check you are not trying to set any data with `null` or `blank` – MAC Sep 01 '15 at 06:58
  • about which part of code you are talking about.. – Harry Sharma Sep 01 '15 at 07:03
  • 2
    Can you post your code for `FragmentIndex`, `FragmentDynamicTab` and `ActivityMain.setdynamicTabs`? – random Sep 02 '15 at 09:03
  • show main activity. also – Elltz Sep 05 '15 at 01:37
  • try removing @Override public void destroyItem(ViewGroup container, int position, Object object) { // supertabLayout.destroyItemsetupWithViewPager(container, position, objectviewPager); } – JAAD Feb 08 '16 at 07:32

2 Answers2

3

Apparently commit() or commitAllowingStateLoss() happens twice inside FragmentStatePagerAdapter. Here what I found out from android sources:

The only place from where the transaction of this adapter is commited is FragmentStatePagerAdapter.finishUpdate() and it's commitAllowingStateLoss() version of commit(). Hence, finishUpdate() is called twice. This method is called from 3 places:

  • ViewPager.setAdapter();
  • ViewPager.dataSetChanged();
  • ViewPager.populate().

Now, finishUpdate() is protected by if (mCurTransaction != null) check and inside this check mCurTransaction is nulled. Hence we cannot really commit the same transaction twice. Unless we have multiple threads working on it. mCurTransaction field is not volatile, which leads me to idea that you're probably calling (directly or indirectly) one of the methods listed above from the worker thread and sometimes it leads to a race condition around mCurTransaction field, which leads to a second commitAllowingStateLoss() call.

Make sure you're referencing your adapter and related objects only from main (UI) thread.

Dmide
  • 6,422
  • 3
  • 24
  • 31
-1

This piece of code looks very familiar.

It looks like my project MaterialAppBase in github, but this is not my code.

I read your code, if I am not being wrong, you have an activity which implements a navigation drawer at the same time, a tablayout is implemented.

This is not a good idea anyway. I see you are dealing with an app which maybe having a very complicated layout.

What you are doing is against the android design guideline, of cause against the normal UX design. You should never have two slidable view as a navigation within an activity. And the swipe gesture between NavigationDrawer and ViewPager may be conflict. Think about it, nobody does this.

However, you many have your reasons to do this. If you consist to do this, I see something wrong in your code, but i am not sure if your problem is caused by this error.

@Override
public Fragment getItem(int index) {

    if (ActivityMain.setdynamicTabs.get(index).equalsIgnoreCase("HOME")) {
        return new FragmentIndex();
    else {
        return new FragmentDynamicTab(index);
    }
}

Problem is you should not create a new fragment every time the page item renders.

What you should do is:

  • You should have your fragments created in advance.
  • Add your fragments in a ArrayList or something like this.
  • Pass this list to the adapter and so that it can make the fragments reusable.

Look at my code the adapter code

  • The example code of [using the adapter](https://github.com/DanielShum/MaterialAppBase/blob/master/app/src/main/java/com/daililol/material/appbase/example/ExampleTabbarActivity.java) – Daniel Martin Shum Sep 06 '15 at 13:49