5

When a user opens preferences on my app he may make changes for example changing the app theme.

The documentation for ContextThemeWrapper.setTheme(int) says:

Set the base theme for this context. Note that this should be called before any views are instantiated in the Context (for example before calling setContentView(View) or inflate(int, ViewGroup)).

So my first thought was restarting the app onResume() when the user changed the preferences. However I noticed that sometimes the process of restarting the activity is seamless while other times the activity is closed, the home screen is seen and only after some seconds the app opens again.

I'm wondering if there is a way to change handle the preferences changes. Like for instance changing the theme after onResume without restarting the activity or restarting the activity on the background while the user is on preferences.

What's the right way to handle this?

Jason Capriotti
  • 1,836
  • 2
  • 17
  • 33
lisovaccaro
  • 32,502
  • 98
  • 258
  • 410
  • 1
    Why do you think that you have to *restart* your activity? After all, the only thing that "starting" an activity dictates is what `Intent` was used to start it in the first place. Any other change to an existing running activity can be made in the existing running activity (e.g., loading a new UI). – CommonsWare Jan 03 '15 at 23:37
  • http://stackoverflow.com/questions/2482848/how-to-change-current-theme-at-runtime-in-android – Dave S Jan 13 '15 at 22:19

4 Answers4

5

Assuming that your Preference screen is an Activity, when the user navigated to it, MainActivity was placed on a paused state (and then probably on a stopped state). When the user navigates back to MainActivity onResume() will be called; here you can change the sate of MainActivity accordingly to reflect the preferences that were changed.

Emmanuel
  • 13,083
  • 4
  • 39
  • 53
  • but what if I want to restart/create a new instance of MainActivity to reflect the user preferences? How can I do it without the user noticing? – lisovaccaro Jan 04 '15 at 02:34
  • Why would you want to do that? The framework gives you a way to updated anything you need on `MainActivity` after a change on your preferences screen. – Emmanuel Jan 04 '15 at 02:45
  • hi @Emmanuel my current doubt with this method is that setTheme doesn't work onResume() please look at the edited question. – lisovaccaro Jan 13 '15 at 21:02
  • You have the solution right there on your question. It will not work if called after the `View` in question is inflated. – Emmanuel Jan 13 '15 at 22:12
  • but I don't understand, when I return from preferences the `View` will be inflated. So how could I change the theme without restarting it? It's simply not possible. In such case I want to know how to restart the activity seamlessly because I haven't managed to get a consistent behavior – lisovaccaro Jan 14 '15 at 13:41
3

I'm assuming you are storing user's selected theme in App Preferences. So in your Activity's onCreate(), add setTheme().

public void onCreate(Bundle savedInstanceState) {
    setTheme(android.R.style.Theme); // or whatever theme you're using

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
}

But changes don't take effect until the activity is restarted. So if you need to immediately apply theme changes, call recreate() afterwards applying theme:

// Might need to call them on getApplication() depending on Context
setTheme(userSelectedTheme);
recreate();

Also, as Attiq mentioned, re-creating an activity might result in loss of data fetched from network using Threads/AsyncTasks so you need to take that in to account as well.

Community
  • 1
  • 1
  • And if you need to be able to switch between multiple themes, you can [select the theme like this](http://stackoverflow.com/questions/2482848/how-to-change-current-theme-at-runtime-in-android) and call `recreate()` afterwards. –  Jan 14 '15 at 16:03
2
When a user opens preferences on my app he may make changes that mean I have to restart my MainActivity however I don't want to user to notice anything happened.

User will not notice anything because, the activity life cycle will take care.

Tasks - EVENT 1 Main Activity (MA) TO Preference Activity (PA)

EVENT 2 Preference Activity (PA)TO Main Activity

Activity Life Cycle - MA onPause() TO PA onResume() ... PA onPause() TO MA onResume()

 nor remove it from the back stack.

If you want the same activity from backstack to resume and not a new MainActivity to be created, this can be done using launchmodes

Code sample

intent = new Intent(this, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
        startActivity(intent);
Prem
  • 4,823
  • 4
  • 31
  • 63
1

Our application is offering multiple themes and we have already tried methods like updating themes from onResume or onStart[restart activity case] but it's requires onCreate() method calls to update the themes, you need to finish the activity and recreate it using selected themes.

Important point: Re-creating new activity might result in lose of data fetched from network using threads or asynctask in the activity so you need to take this issue as well.

In our application, we are saving the number of selected theme in the sharedpreferences and loading it during the creation of new activity.

To finish and restart the activity

public static void changeToTheme(Activity activity, int theme) {
    sTheme = theme;
    activity.finish();

    activity.startActivity(new Intent(activity, activity.getClass()));
}
Attiq ur Rehman
  • 475
  • 1
  • 6
  • 21
  • how should I restart the activity so it's as seamless as possible? I tried finishing it onResume and starting it again. But sometimes it closes to the home screen and opens back again. Is it possible to make it seamless? Maybe finish it when preferences open and starting it when the user presses back. – lisovaccaro Jan 14 '15 at 13:42