1

So I am trying to make an app in which you can change the language (in a preference activity) to system default or a specific language. Whenever you change the language the app is restarted and the new locale is selected. When the first activity starts, it saves the Locale which has to be used into a static variable in an Utils class. In every activity onCreate method I load that locale.

Now, for clarification, here's the Locale part of the Utils class:

private static Locale locale = null;
public static boolean isLocaleNull() {
    return locale == null;
}
public static void setLocale(Locale locale) {
    Utils.locale = locale;
}
public static void loadLocale(Context baseContext) {
    if (locale == null) return;
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    baseContext.getResources().updateConfiguration(config, baseContext.getResources().getDisplayMetrics());
}

Here's my onCreate on my first activity (only locale part):

if (!Utils.isLocaleNull()) {
    String locale = PreferenceManager.getDefaultSharedPreferences(getBaseContext())
            .getString(getResources().getString(R.string.prefsKeyLanguage), "default");
    if (locale != null && !locale.equals("default"))
        Utils.setLocale(new Locale(locale));
}

And here's how I load the locale in all activities:

Utils.loadLocale(getBaseContext());

Finally, in the loadLocale we have if (locale == null) return; and in the locale loader we have if (... && !locale.equals("default")) which means the locale will be null if System Default is selected which means the locale won't be change if System Default is selected.

Everything's perfect! I mean, it works as expected. But can it fail in some cases? Is it a good idea? I know that holding static references to instances is a bad idea in some cases. Is this one of those some cases? If yes, what should I do?

Thanks!

Chaoz
  • 2,119
  • 1
  • 20
  • 39
  • not sure if thread safety matters and if you have to worry about race conditions on the setLocal calls (common issue on UI code) – Vincent De Smet May 31 '15 at 14:05

1 Answers1

1

You are right, it is not a good idea because Android will get rid of that static variable as soon as it will need memory (and it happens quite often).

You should set and retrieve your Locale using SharedPreferences.

To deal with Objects in the SharedPreferences use Gson:

To Save

 Editor prefsEditor = mPrefs.edit();
 Gson gson = new Gson();
 String json = gson.toJson(MyObject);
 prefsEditor.putString("MyObject", json);
 prefsEditor.commit();

To Retreive

Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);
Luca Fagioli
  • 12,722
  • 5
  • 59
  • 57
  • 1
    I accepted this answer but I found a better solution - send the locale language over the intent using setExtra(String) and then creating the locale and using it on the other side. Thanks anyway! – Chaoz May 31 '15 at 14:38
  • If you just need the language (`String`), why don't you just save the language (as a `String`) in your `SharedPreferences`? This way you can create the `Locale` when you need it, and also show the current language in the Options panel for example :) – Luca Fagioli May 31 '15 at 14:45
  • I do. Look at my code at the onCreate from my first activity. The thing is that I don't want to open and read the preference file every time. – Chaoz May 31 '15 at 14:53
  • Do not worry about that. SharedPreferences are cached in memory after the first reference, so it open really only the first time. – Luca Fagioli May 31 '15 at 15:04
  • OK, thanks! But there are problems with this caching... for example if you read some preferences and then edit them it won't save them to the file. So if you force-stop your program before it closes (i.e. take out the phone battery) all preferences are lost... – Chaoz May 31 '15 at 15:08
  • With `.apply()` I see your point, although the documentation states that you shouldn't worry (but I guess in a case such one you mentioned, there's nothing the framework can do). But with `.commit()` you are safe from that, because is a synchronous operation. Check [this part of the documentation](http://stackoverflow.com/a/5960743/636561) – Luca Fagioli May 31 '15 at 15:20
  • Thanks! Wasn't really sure about apply and commit. – Chaoz May 31 '15 at 15:35