1

I have inherited this Android app. When I attempt to build a signed APK, I get an error that says Error:(31) Error: Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead [ValidFragment]

It points to this bit of code:

public class BasicInfoFragment extends BasePassportFragment implements LocationEditText.LocationEditTextListener {

    private User user;
    private Templates templates;

    public BasicInfoFragment() {
        super(false);
    }

    public BasicInfoFragment(User user) {
        super(false);
        this.user = user;
    }

    public BasicInfoFragment(User user, Templates templates) {
        super(false);
        this.user = user;
        this.templates = templates;
    }

   ...

}

The error points to the 2nd and 3rd methods, public BasicInfoFragment(User user) and public BasicInfoFragment(User user, Templates templates) so I am confused why public BasicInfoFragment() is okay but the other two are not?

Chris
  • 5,485
  • 15
  • 68
  • 130
  • Why are you setting super(false)? Would you also please show the other fragments? Like the BasePassportFragment()? – Eenvincible Aug 18 '14 at 19:34
  • it is because the constructor that will be called to re-instanciate your fragment will be the empty one. which means that the user and the templates will be null. – njzk2 Aug 18 '14 at 19:46
  • Possible duplicated: http://stackoverflow.com/questions/17420637/error-non-default-constructors-in-fragments – Jose Rodriguez Aug 18 '14 at 19:46

1 Answers1

6

I am confused why public BasicInfoFragment() is okay but the other two are not?

When an activity is destroyed and recreated as part of a configuration change (e.g., screen rotation), Android automatically destroys and recreates the fragments that were managed by the old activity instance. To do that, it will use the default constructor, not either of the other two constructors.

Also, when your app's process is terminated while you are in the background, and the user returns to your app (e.g., recent-tasks list), Android will create a brand-new instance of your activity... and all of its fragments. Once again, it will use the default constructor.

The risk of using the other constructors is that any objects passed in to those constructors is prone to being lost during either of the above events. Lint is steering you towards getting rid of those constructors and using the factory pattern (e.g., a static newInstance() method), where data is supplied to the fragment via the setArguments() method. This attaches a Bundle, retrievable by the fragment instance via getArguments(). That Bundle is automatically part of the saved instance state, which will be held onto through either of the above events.

TL;DR: the other public constructors represent a strong enough "code smell" that Lint nowadays yells at you

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491