下面列出了android.content.res.Configuration#diff() 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Set new display override config and return array of ids of stacks that were changed during
* update. If called for the default display, global configuration will also be updated. Stacks
* that are marked for deferred removal are excluded from the returned array.
*/
int[] setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration, int displayId) {
final DisplayContent displayContent = getDisplayContent(displayId);
if (displayContent == null) {
throw new IllegalArgumentException("Display not found for id: " + displayId);
}
final Configuration currentConfig = displayContent.getOverrideConfiguration();
final boolean configChanged = currentConfig.diff(newConfiguration) != 0;
if (!configChanged) {
return null;
}
displayContent.onOverrideConfigurationChanged(newConfiguration);
mTmpStackList.clear();
if (displayId == DEFAULT_DISPLAY) {
// Override configuration of the default display duplicates global config. In this case
// we also want to update the global config.
setGlobalConfigurationIfNeeded(newConfiguration, mTmpStackList);
} else {
updateStackBoundsAfterConfigChange(displayId, mTmpStackList);
}
mTmpStackIds.clear();
final int stackCount = mTmpStackList.size();
for (int i = 0; i < stackCount; ++i) {
final TaskStack stack = mTmpStackList.get(i);
// We only include stacks that are not marked for removal as they do not exist outside
// of WindowManager at this point.
if (!stack.mDeferRemoval) {
mTmpStackIds.add(stack.mStackId);
}
}
return mTmpStackIds.isEmpty() ? null : ArrayUtils.convertToIntArray(mTmpStackIds);
}
private int getConfigurationChanges(Configuration lastReportedConfig) {
// Determine what has changed. May be nothing, if this is a config that has come back from
// the app after going idle. In that case we just want to leave the official config object
// now in the activity and do nothing else.
final Configuration currentConfig = getConfiguration();
int changes = lastReportedConfig.diff(currentConfig);
// We don't want to use size changes if they don't cross boundaries that are important to
// the app.
if ((changes & CONFIG_SCREEN_SIZE) != 0) {
final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
currentConfig.screenWidthDp)
|| crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
currentConfig.screenHeightDp);
if (!crosses) {
changes &= ~CONFIG_SCREEN_SIZE;
}
}
if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
final int newSmallest = currentConfig.smallestScreenWidthDp;
if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
}
}
// We don't want window configuration to cause relaunches.
if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) {
changes &= ~CONFIG_WINDOW_CONFIGURATION;
}
return changes;
}
@Override
public void onConfigurationChanged(final Configuration newConfig) {
final Configuration oldConfig = getResources().getConfiguration();
final int diff = oldConfig.diff(newConfig);
final Configuration target = diff == 0 ? oldConfig : newConfig;
if (appLocale != null) {
setAppLocaleIntoConfiguration(target);
}
super.onConfigurationChanged(target);
}
private boolean relaunchActivityIfNeeded(Message msg) {
try {
Field f = sActivityThread.getClass().getDeclaredField("mActivities");
f.setAccessible(true);
Map mActivities = (Map) f.get(sActivityThread);
Object /*ActivityThread$ActivityConfigChangeData*/ data = msg.obj;
Object token;
if (data instanceof IBinder) {
token = data;
} else {
f = data.getClass().getDeclaredField("activityToken");
f.setAccessible(true);
token = f.get(data);
}
Object /*ActivityClientRecord*/ r = mActivities.get(token);
Intent intent = ReflectAccelerator.getIntent(r);
String bundleActivityName = unwrapIntent(intent);
if (bundleActivityName == null) {
return false;
}
f = r.getClass().getDeclaredField("activity");
f.setAccessible(true);
Activity activity = (Activity) f.get(r);
f = Activity.class.getDeclaredField("mCurrentConfig");
f.setAccessible(true);
Configuration activityConfig = (Configuration) f.get(activity);
if (mApplicationConfig == null) {
// The application config is not ready yet.
// This may be called on Android 7.0 multi-window-mode.
return false;
}
// Calculate the changes
int configDiff = activityConfig.diff(mApplicationConfig);
if (configDiff == 0) {
return false;
}
// Check if the activity can handle the changes
ActivityInfo bundleActivityInfo = sLoadedActivities.get(bundleActivityName);
if ((configDiff & (~bundleActivityInfo.configChanges)) == 0) {
return false;
}
// The activity isn't handling the change, relaunch it.
return ReflectAccelerator.relaunchActivity(activity, sActivityThread, token);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}