1

We are encouraged to use static initializer (a.k.a. the newInstance() pattern) per Fragment when we are passing arguments. In case of Activity, there is no mentioning of such. And every time we are going to start an activity, we have to first create an Intent first, like below:

public class FirstActivity extends Activity {
    ...
    Intent intent = new Intent(this, SecondActivity.class);
    startActivity(intent);
    ...
}

And if there are some parameters we would like to pass, this gets even more complicated, since we need to give each parameter a name, like below:

public class FirstActivity extends Activity {
    ...
    int age = 10;
    int count = 20;
    String message = "hello";

    Intent intent = new Intent(this, SecondActivity.class);
    intent.putExtra("Age", age);
    intent.putExtra("Count", count);
    intent.putExtra("Message", message);
    startActivity(intent);
    ...
}

and in the SecondActivity we should retrieve these parameters with the same name:

public class SecondActivity extends Activity {
    ...
    int mAge;
    int mCount;
    String mMessage;

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

        mAge = getIntent().getIntExtra("Age", 0);
        mCount = getIntent().getIntExtra("Count", 0);
        mMessage = getIntent().getStringExtra("Message");
    }
    ...
}

Furthermore, these names we have used, "Age", "Count" and "Message" is hard-coded and error-prone. Most of the time we use a helper class, called something like IntentExtraKeys and use names from that class, like below:

public class IntentExtraKeys{

    public static final String AGE_KEY = "age_key";
    public static final String COUNT_KEY = "count_key";
    public static final String MESSAGE_KEY = "message_key";
}

and in the activities:

public class FirstActivity extends Activity{

    ...
    intent.putExtra(IntentExtraKeys.AGE_KEY, age);
    ...
}

and

public class SecondActivity extends Activity{

    ...
    mAge = getIntent().getIntExtra(IntentExtraKeys.AGE_KEY, 0);
    ...
}

Instead of this, we could have something like below:

public class FirstActivity extends Activity{

    ....
    SecondActivity.startActivity(this, age, count, message);
    ...
}

and

public class SecondActivity extends Activity{
    ...
    private static final String AGE_KEY = "age_key";
    private static final String COUNT_KEY = "count_key";
    private static final String MESSAGE_KEY = "message_key";

    public static void startActivity(Context context, int age, int count, String message){

    Intent intent = new Intent(context, SecondActivity.class);
    intent.putExtra(AGE_KEY, age);
    intent.putExtra(COUNT_KEY, count);
    intent.putExtra(MESSAGE_KEY, message);
    context.startActivity(intent); 
    }
    ...
}

This way, we save ourselves from writing code for creating an Intent every time we want to start the activity and if we are going to pass some parameters, we don't need to give them name. Only the activity we are starting knows their name, and it looks a lot cleaner, just like in fragments.

Is this bad design? Why is this uncommon?

Community
  • 1
  • 1
NecipAllef
  • 486
  • 1
  • 5
  • 18
  • I actually do this for quite a few activites, services, and especially intent services. I don't see anything wrong with this pattern for internal operations. Might not use it if using implicit intents, etc. – emerssso Nov 11 '15 at 02:04

2 Answers2

1

The static initializer pattern is used in fragments because even though you instantiate the fragment yourself for the first time the default constructor must exist so the platform can instantiate it again on it's own when the activity is rebuilt because of a configuration change.

Activities on the other hand are always instantiated by the system and they must not need any special factory method nor constructor in order to retain their ability to be exported as intents for use by other apps and the system itself; that's why static initializers don't make a whole lot of sense on Activities. They are quite valid though and you can use them if you want but they might complicate having custom initialization code for activities that perform the same function in various slightly-different ways and they create a false sense of coupling.

Machinarius
  • 3,637
  • 3
  • 30
  • 53
  • "perform the same function in various slightly-different ways and they create a false sense of coupling." Could you please elaborate? – NecipAllef Nov 11 '15 at 02:07
  • Sure. Imagine a picker or gallery activity with different operating modes and configuration options - you'd have to work out different overloads for the different operation modes (which is fine by itself) that you cannot share to other apps and cannot do anything else than just configuring and returning/launching an intent or else you risk coupling your activity construction to those methods, breaking the implicit contract with the platform that the only construction path must be the default constructor. – Machinarius Nov 11 '15 at 02:13
1

For fragment

There are some reasons to use static function to create Fragment

  1. Having single point to create Fragment instances. This makes sure the multi Fragment initializing having the same input arguments handling, etc.

  2. It helps developers avoid to create Non-static Nested fragment. Fragment & Activity must be de-coupling.

  3. The utility function can be invoked multi times. For example: The fragment is being used in TabLayout, ViewPager.

For Activity

You can create utility like you did. No problem. It is hard to say it is bad code or uncommon code.

If you will use the function More than one Or the Activity has input arguments. You can create the Utility function like you did.

LHA
  • 9,398
  • 8
  • 46
  • 85
  • I like how you highlight that it would not be an anti-pattern in any way and instead is quite the opposite by centralizing the initialization. It does have disadvantages though, as i'm discussing with OP in the comments on my answer. – Machinarius Nov 11 '15 at 02:15