use of org.robolectric.shadows.ShadowContextThemeWrapper in project robolectric by robolectric.
the class ActivityController method configurationChange.
/**
* Performs a configuration change on the Activity.
*
* <p>If the activity is configured to handle changes without being recreated, {@link
* Activity#onConfigurationChanged(Configuration)} will be called. Otherwise, the activity is
* recreated as described <a
* href="https://developer.android.com/guide/topics/resources/runtime-changes.html">here</a>.
*
* @param newConfiguration The new configuration to be set.
* @return ActivityController instance
*/
public ActivityController<T> configurationChange(final Configuration newConfiguration) {
final Configuration currentConfig = component.getResources().getConfiguration();
final int changedBits = currentConfig.diff(newConfiguration);
currentConfig.setTo(newConfiguration);
// Can the activity handle itself ALL configuration changes?
if ((getActivityInfo(component.getApplication()).configChanges & changedBits) == changedBits) {
shadowMainLooper.runPaused(() -> {
component.onConfigurationChanged(newConfiguration);
ViewRootImpl root = getViewRoot();
if (root != null) {
if (RuntimeEnvironment.getApiLevel() <= N_MR1) {
ReflectionHelpers.callInstanceMethod(root, "updateConfiguration", ClassParameter.from(Configuration.class, newConfiguration), ClassParameter.from(boolean.class, false));
} else {
root.updateConfiguration(Display.INVALID_DISPLAY);
}
}
});
return this;
} else {
@SuppressWarnings("unchecked") final T recreatedActivity = (T) ReflectionHelpers.callConstructor(component.getClass());
final _Activity_ _recreatedActivity_ = reflector(_Activity_.class, recreatedActivity);
shadowMainLooper.runPaused(() -> {
// Set flags
_component_.setChangingConfigurations(true);
_component_.setConfigChangeFlags(changedBits);
// Perform activity destruction
final Bundle outState = new Bundle();
// The order of onPause/onStop/onSaveInstanceState is undefined, but is usually:
// onPause -> onSaveInstanceState -> onStop before API P, and onPause -> onStop ->
// onSaveInstanceState from API P.
// See
// https://developer.android.com/reference/android/app/Activity#onSaveInstanceState(android.os.Bundle) for documentation explained.
// And see ActivityThread#callActivityOnStop for related code.
_component_.performPause();
if (RuntimeEnvironment.getApiLevel() < P) {
_component_.performSaveInstanceState(outState);
if (RuntimeEnvironment.getApiLevel() <= M) {
_component_.performStop();
} else {
// API from N to O_MR1(both including)
_component_.performStop(true);
}
} else {
_component_.performStop(true, "configurationChange");
_component_.performSaveInstanceState(outState);
}
// This is the true and complete retained state, including loaders and retained
// fragments.
final Object nonConfigInstance = _component_.retainNonConfigurationInstances();
// This is the activity's "user" state
final Object activityConfigInstance = nonConfigInstance == null ? // No framework or user state.
null : reflector(_NonConfigurationInstances_.class, nonConfigInstance).getActivity();
_component_.performDestroy();
makeActivityEligibleForGc();
// Restore theme in case it was set in the test manually.
// This is not technically what happens but is purely to make this easier to use in
// Robolectric.
ShadowContextThemeWrapper shadowContextThemeWrapper = Shadow.extract(component);
int theme = shadowContextThemeWrapper.callGetThemeResId();
// Setup controller for the new activity
attached = false;
component = recreatedActivity;
_component_ = _recreatedActivity_;
// TODO: Pass nonConfigurationInstance here instead of setting
// mLastNonConfigurationInstances directly below. This field must be set before
// attach. Since current implementation sets it after attach(), initialization is not
// done correctly. For instance, fragment marked as retained is not retained.
attach(/* activityOptions= */
null, /* lastNonConfigurationInstances= */
null);
if (theme != 0) {
recreatedActivity.setTheme(theme);
}
// Set saved non config instance
_recreatedActivity_.setLastNonConfigurationInstances(nonConfigInstance);
ShadowActivity shadowActivity = Shadow.extract(recreatedActivity);
shadowActivity.setLastNonConfigurationInstance(activityConfigInstance);
// Create lifecycle
_recreatedActivity_.performCreate(outState);
if (RuntimeEnvironment.getApiLevel() <= O_MR1) {
_recreatedActivity_.performStart();
} else {
_recreatedActivity_.performStart("configurationChange");
}
_recreatedActivity_.performRestoreInstanceState(outState);
_recreatedActivity_.onPostCreate(outState);
if (RuntimeEnvironment.getApiLevel() <= O_MR1) {
_recreatedActivity_.performResume();
} else {
_recreatedActivity_.performResume(true, "configurationChange");
}
_recreatedActivity_.onPostResume();
// TODO: Call visible() too.
});
}
return this;
}
Aggregations