stepstone-tech / android-material-stepper

This library allows to use Material steppers inside Android applications.
Apache License 2.0
1.78k stars 261 forks source link

Crash when attempting to use tab stepper. #172

Closed quirkfly closed 7 years ago

quirkfly commented 7 years ago

Hi there,

First of all thanks a lot for the great library!

I am experiencing the following crash on Lollipop device when trying to use tab steps.

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.twentydeka.itrash.android, PID: 32743
                  java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
                      at android.graphics.drawable.AnimatedVectorDrawable.isStarted(AnimatedVectorDrawable.java:427)
                      at android.graphics.drawable.AnimatedVectorDrawable.draw(AnimatedVectorDrawable.java:179)
                      at android.widget.ImageView.onDraw(ImageView.java:1158)
                      at android.view.View.draw(View.java:15231)
                      at android.view.View.updateDisplayListIfDirty(View.java:14167)
                      at android.view.View.getDisplayList(View.java:14189)
                      at android.view.View.draw(View.java:14959)
                      at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
                      at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
                      at android.view.View.updateDisplayListIfDirty(View.java:14162)
                      at android.view.View.getDisplayList(View.java:14189)
                      at android.view.View.draw(View.java:14959)

[snip]

Here is my layout containing StepperLayout

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white">
        <com.stepstone.stepper.StepperLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                             xmlns:app="http://schemas.android.com/apk/res-auto"
                                             android:id="@+id/stepper_layout"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent"
                                             app:ms_stepperType="tabs"
                                             app:ms_activeStepColor="?attr/colorAccent"
                                             app:ms_inactiveStepColor="#cccccc"
                                             app:ms_backButtonColor="#FFFFFF"
                                             app:ms_nextButtonColor="#FFFFFF"
                                             app:ms_completeButtonColor="#FFFFFF"
                                             app:ms_tabStepDividerWidth="138dp"
                                             app:ms_bottomNavigationBackground="?attr/colorAccent" />
    </FrameLayout>
    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="270dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@android:color/darker_gray"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>

Here is my stepper adapter

public class SellerEshopRegistrationAdapter extends AbstractFragmentStepAdapter {

    public SellerEshopRegistrationAdapter(FragmentManager fm, Context context) {
        super(fm, context);
    }

    @Override
    public Step createStep(int position) {
        Step step = null;

        switch (position) {
            case 0:
                step = new UserCredentialsFragment();
                break;
            case 1:
                step = new DeliveryAddressFragment();
                break;
            case 2:
                step = new PersonalDetailsFragment();
                break;
            default:
                throw new IllegalArgumentException("unsupported position: " + position);
        }

        return step;
    }

    @Override
    public int getCount() {
        return 3;
    }

    @NonNull
    @Override
    public StepViewModel getViewModel(@IntRange(from = 0) int position) {
        StepViewModel.Builder builder = new StepViewModel.Builder(context);

        switch (position) {
            case 0:
                builder
                        .setTitle(R.string.user_credentials_title)
                        .setNextButtonLabel(R.string.next_button_label);
                break;
            case 1:
                builder
                        .setTitle(R.string.delivery_address_label)
                        .setNextButtonLabel(R.string.next_button_label)
                        .setBackButtonLabel(R.string.back_button_label);
                break;
            case 2:
                builder
                        .setTitle(R.string.personal_details_label)
                        .setNextButtonLabel(R.string.complete_button_label)
                        .setBackButtonLabel(R.string.back_button_label);
                break;
            default:
                throw new IllegalArgumentException("Unsupported position: " + position);
        }

        return builder.create();
    }
}

And finally here is relevant excerpt from acitivity hosting the stepper

public class SellerEshopRegistrationActivity extends ItrashActivity {
    public static final String                      TAG = "SellerEshopRegistrationActivity";
    public static final String                      SELLER_PARAM = "seller";

    public static final int                         DATA_VALIDATION_SUCCESS = 0;
    public static final int                         EMAIL_ALREADY_REGISTERED = 1;
    public static final int                         PASSWORD_RULES_BROKEN = 2;
    public static final int                         ADDRESS_OUT_OF_DELIVERY_RANGE = 3;
    public static final int                         INVALID_LOYALTY_CARD = 4;

    private Seller                                  mSeller;
    private String                                  mUserEmail;
    private String                                  mLoyaltyCardPrefix;
    private PersonalDetailsFragment                 mPersonalDetailsFragment;

    @BindView(R.id.stepper_layout) StepperLayout    mStepperLayout;

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

        setTitle(getString(R.string.user_registration_title));

        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        if (savedInstanceState != null) {
            mSeller = savedInstanceState.getParcelable(SELLER_PARAM);
        } else {
            mSeller = getIntent().getParcelableExtra(SELLER_PARAM);
        }

        mStepperLayout.setAdapter(new SellerEshopRegistrationAdapter(getSupportFragmentManager(), this));
        mStepperLayout.setShowErrorStateEnabled(true);
    }

Digging further inside AnimatedVectorDrawable.java

private boolean isStarted() {
        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
        final int size = animators.size();
        for (int i = 0; i < size; i++) {
            final Animator animator = animators.get(i);
            if (animator.isStarted()) {
                return true;
            }
        }
        return false;
    }

For a reason unknown to me the animators list is null. Do you have any idea what could cause it and how to prevent the crash?

Cheers

zawadz88 commented 7 years ago

Hi @quirkfly, Which version of the library are you using? Also on what devices do you see this crash? What's your support library version?

quirkfly commented 7 years ago

I am using material-stepper 3.3.0. The crash is happening on Android 5.1.1. As for the support library I am using the following

    compile 'com.android.support:support-annotations:23.4.0'
    compile 'com.android.support:appcompat-v7:24.2.0'
    compile 'com.android.support:design:24.2.0'
    compile 'com.android.support:recyclerview-v7:23.2.1'
    compile 'com.android.support:cardview-v7:24.2.0'
zawadz88 commented 7 years ago

3.3.0 depends on Android Support library 25.3.1 so there might be some issues there if you're using different versions in your app. I'd recommend using the same version for all support libraries in general. You can check the resolved library versions by running: ./gradlew :app:dependencies --configuration compile assuming you module's name is app.

Can you update all of them to 25.3.1?

quirkfly commented 7 years ago

I see. That would make sense. The update to 25.3.1 is unfortunately not an option as I am running on 32bit arch. I guess will have to live with progress_bar type, which is working fine, than. Nevertheless thanks for clarification.

zawadz88 commented 7 years ago

You can also check with an older version of the stepper library, e.g. 2.0.0?

quirkfly commented 7 years ago

Actually did the update of support library to 25.4.0 as suggested (32bit arch is ok with that, it is the build tools I can not go above version 23) however the issue is still around. Tried even to downgrade the stepper library to 2.0.0 however encountered compilation errors as the step fragments are implementing the callbacks introduced in a later version.

zawadz88 commented 7 years ago

Hmmm it might be build tools related, some people were reporting some issues when using older build tools than in this lib. Regarding the compilation errors you might try using callbacks described here: https://github.com/stepstone-tech/android-material-stepper/tree/v2.0.0 although if it's build tools related this might not work as well :/

quirkfly commented 7 years ago

3.2.0 is the lowest I can go with without touching the code, still crashing though. Will try on Android 6.0 later on and report my findings.

quirkfly commented 7 years ago

Eventually did try running the code on Android 7.0, went fine no crash occurred. Hence It appears as the issue is pertinent to Android 5.1 (and possibly below).

zawadz88 commented 7 years ago

This is probably due to animated vector drawable compat support library which is used in the library and is incompatible with the build tools you're using. The only solution I see here is to either update the build tools or use an older library version which didn't use animated vector drawables e.g. 2.0.0. Although the latter will require changing some code probably in your app and you won't be able to use the latest features.