Challenge - evokes a question about newInstance()


#1

The DatePickerFragment and TimePickerFragment share a lot of code. So, I was thinking that one should create a base abstract class that both would inherit from. However, in java you can’t make a method both static and abstract, to force the super classes to implement it.

I then realized that I don’t understand why we are using a static method to create an instance of the class instead of just using a constructor that takes the Date. Is there a reason for this?

Thank you!


#2

Logic tells me that it makes no difference where you do the “new DatePickerFragment” command, and these are identical:

DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate()); //(new done in the newInstance() method) and DatePickerFragment dialog = new DatePickerFragment(mCrime.getDate());
Even though dialog goes out of scope, the [color=#800000]dialog.show(fm, DIALOG_DATE);[/color] command tells Android to control this instance, so it doesn’t get garbage collected.

And you are not answering the question because you are just shrugging and thinking “Pffft, I don’t know”?


#3

This question actually comes up a lot in class. You’re right that the two approaches are exactly equivalent.

We use newInstance mainly because this is the standard convention in Android code. There is no huge upside to using constructors instead, and we think there’s a lot of value in recommending practices that are similar to those in the larger Android community.

I can think of one advantage to not using constructors, though, and that has to do with the default constructor. Fragment instances are often created dynamically by the FragmentManager, which means that every fragment must have a default parameterless constructor.

Default constructors are strange, though. It is easy to destroy them by adding code. For example, let’s say I create a really simple ListFragment like so:

public class MySimpleListFragment extends ListFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("MySimpleListFragment", "Hi!");
    }
}

This fragment will work perfectly fine in all circumstances.

If you add a constructor with parameters, however:

public class LoggingListFragment extends ListFragment {
    String mLogString;

    public LoggingListFragment(String logString) {
        mLogString = logString;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("LoggingListFragment", mLogString);
    }
}

…the default constructor no longer exists. So LoggingListFragment will cause an exception to be thrown on rotation at runtime. If you use newInstance, this problem can’t happen.

Of course, that doesn’t solve your problem. One possible solution would be to refactor your setup code into an instance method, so that your newInstance looks something like this:

public MyFragment newInstance(String myArgument) {
    MyFragment instance = new MyFragment();
    instance.initialize(myArgument);
    return instance;
}

#4

[quote=“phillips”]This question actually comes up a lot in class. You’re right that the two approaches are exactly equivalent.

We use newInstance mainly because this is the standard convention in Android code. There is no huge upside to using constructors instead, and we think there’s a lot of value in recommending practices that are similar to those in the larger Android community.
[/quote]

Thanks! That is what I thought. And yes, you would need to be sure to code a default constructor.