1

For example, suppose I have an android application, in simple, there are 3 activities :

MainActivity -> Main2Activity -> Main3Activity

,which user can visit them in sequence (eg: by button click), also there is some global data to show:

public class GlobalData{
    public static String userId;
}

public class MainActivity extends AppCompatActivity {
    //button click listener
    public void toMain2Activity(View view){
        Intent i = new Intent(this, Main2Activity.class);
        this.startActivity(i);
    }
}

public class Main2Activity extends AppCompatActivity {
    //button click listener
    public void toMain3Activity(View view){
        Intent i = new Intent(this,Main3Activity.class);
        this.startActivity(i);
    }
}

public class Main3Activity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
    }
}

One day, Main3Activity needs to display userId in GlobalData, so I modify Main3Activity:

public class Main3Activity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);

        Toast.makeText(this,GlobalData.userId, Toast.LENGTH_LONG).show();
    }
}

But according to Why is Global State so Evil?, I should avoid global state, so I try to pass the original data object instead of allowing global state, so I try to pass the global object to Main3Activity instead of share it everywhere:

public class GlobalData implements Serializable {
    public String userId="user_67890";
}

public class MainActivity extends AppCompatActivity {
    private GlobalData globalData=new GlobalData();

    public void toMain2Activity(View view){
        Intent i = new Intent(this, Main2Activity.class);
        i.putExtra("global",this.globalData);
        this.startActivity(i);
    }
}

public class Main2Activity extends AppCompatActivity {
    private GlobalData globalData;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        this.globalData=(GlobalData)this.getIntent().getSerializableExtra("global");
    }

    public void toMain3Activity(View view){
        Intent i = new Intent(this, Main3Activity.class);
        i.putExtra("global",this.globalData);
        this.startActivity(i);
    }
}

public class Main3Activity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        GlobalData globalData=(GlobalData) this.getIntent().getSerializableExtra("global");
        Toast.makeText(this,globalData.userId, Toast.LENGTH_LONG).show();
    }
}

But I think avoiding global state is less maintainable and more unpredictable in my case because:

  1. With global state, I don't need to modify Main2Activity, which seems more fit the open closed principle, but if I want to avoid global state, I need to modify all intermediate (eg:Main2Activity) UI from start(source of GlobalData) to terminal (UI that uses GlobalData), which my android application is usually one UI component is included by another UI in depth.

  2. If I pass the GlobalData only when I need it, it means I may have many functions need to add something like "GlobalData globaldata=this.getIntent().getSerializableExtra..." and "Intent i=..." everywhere, which I think it is less readable

  3. In the modified version, it is possible that the this.getIntent().getSerializableExtra is failed because I may forget to put the object into the intent, and I need to handle if I get GlobalData failed, which I think it is less maintainable

  4. Usually the GlobalData is not involved in Unit Test because the GlobalData is usually displayed directly, so I think sharing GlobalData doesn't make the app harder to test

  5. Using intent let me need to think how to write additional codes to pass data between same level UI components (eg:same Activity, from EditText to error message detail label)

As above, I think avoid global state is more evil than having global state in my case. So my question is, are "I'm writing android applications" and "follow open-closed principles" reasons to allow global state?

  • Android-specific considerations aside, aren't you really just asking whether the open-closed principle is more important than the avoid-global-state principle? There is no answer to that question. – Christian Hackl Mar 15 at 6:44
2

Global state is a really bad idea in android unless you package it up into an application database or something like that.

The android runtime will periodically close and reopen activities, and can even close your entire activity and unload it.

If you rely on your global state, when the activity reopens, it won't necessarily instantiate your global data properly, and you can get some really bizzare effects when that happens. In order to solve that, you have to use the proper android APIs to store your global state, ie onSaveInstanceState(), and at that point you may as well manage your state's lifecycle properly instead of just declaring a static variable and hoping that does the job.

  • "Global state is a really bad idea, especially in android" – Caleth Mar 15 at 9:35

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.