獲取屏幕高度的代碼
int getScreenHeight(Activity context) {
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
return metrics.heightPixels;
}
問題現(xiàn)象
在Android N 7.0(SDK 24)上當(dāng),Activity進(jìn)入過分屏模式再退出后,使用上面的代碼去獲取屏幕高度,得到的值是真正的屏幕高度減去狀態(tài)欄的高度。然而在Android 7.1(SDK 25) 上,確沒有這個(gè)問題,猜測是谷歌的BUG,在7.1上已經(jīng)得到了修正。同時(shí)出問題的時(shí)候,傳入的context是Activity,但是當(dāng)我傳入的是ApplicationContext時(shí),返回的屏幕高度又是正確的,這就無語了。
問題原因
通過調(diào)試Android SDK 24和25的框架代碼,發(fā)現(xiàn)出現(xiàn)問題的原因是,SDK 24的ActivityThread的performConfigurationChanged方法configuration沒有正確地更新,但是SDK25做了修正。下面直接給出導(dǎo)致這個(gè)問題的框架代碼:
Android 7.0
public final class ActivityThread {
...
private void performConfigurationChanged(...) {
...
boolean shouldChangeConfig = false;
if ((activity == null) || (activity.mCurrentConfig == null)) {
shouldChangeConfig = true;
} else {
// If the new config is the same as the config this Activity
// is already running with then don't bother calling
// onConfigurationChanged
int diff = activity.mCurrentConfig.diff(newConfig);
if (diff != 0) {
shouldChangeConfig = true;
}
}
...
}
Android 7.1
public final class ActivityThread {
...
private void performConfigurationChanged(...) {
...
boolean shouldChangeConfig = false;
if ((activity == null) || (activity.mCurrentConfig == null)) {
shouldChangeConfig = true;
} else {
// If the new config is the same as the config this Activity is already
// running with and the override config also didn't change, then don't
// bother calling onConfigurationChanged.
int diff = activity.mCurrentConfig.diff(newConfig);
if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken, amOverrideConfig)) {
// Always send the task-level config changes. For system-level configuration, if
// this activity doesn't handle any of the config changes, then don't bother
// calling onConfigurationChanged as we're going to destroy it.
if (!mUpdatingSystemConfig
|| (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
|| !reportToActivity) {
shouldChangeConfig = true;
}
}
}
...
}
比較這兩塊代碼,可以發(fā)現(xiàn) SDK25增加了!mResourcesManager.isSameResourcesOverrideConfig(activityToken, amOverrideConfig)這個(gè)條件來設(shè)置shouldChangeConfig的值。如果shouldChangeConfig那么Activity的configuration在退出分屏后會(huì)更新為未分屏之前的值。
解決方案
為了解決這個(gè)問題,只需要將context更換為ApplicationContext即可。