Android源码——Configuration源码解析

继承结构

Configuration维护了所有影响系统资源的信息,如地区、缩放、屏幕大小、 方向等

public final class Configuration implements Parcelable, Comparable<Configuration> {

}

  • 静态空的Configuration,hide
  • 字体缩放比例
  • Mobile Country Code
  • Mobile Network Code
  • 国家/区域
  • 用户设置国家,hide
public static final Configuration EMPTY = new Configuration();
public float fontScale;
public int mcc;
public int mnc;
public Locale locale;
public boolean userSetLocale;

常量

ScreenLayout相关

屏幕大小掩码、未设置、大于320x426、大于320x470、大于480x640、大于720x960

public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
public static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;

横纵比掩码、未设置、不拉长、拉长

public static final int SCREENLAYOUT_LONG_MASK = 0x30;
public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
public static final int SCREENLAYOUT_LONG_NO = 0x10;
public static final int SCREENLAYOUT_LONG_YES = 0x20;

方向掩码、偏移量、未设置、从左到右、从右到左

public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6;
public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00;
public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;

屏幕大小-横纵比-方向都未设置、兼容模式用于特殊应用、实际值

public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED;
public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
public int screenLayout;

TouchScreen相关

未设置、不支持触屏、触控笔、手指触屏、实际值

public static final int TOUCHSCREEN_UNDEFINED = 0;
public static final int TOUCHSCREEN_NOTOUCH = 1;
@Deprecated public static final int TOUCHSCREEN_STYLUS = 2;
public static final int TOUCHSCREEN_FINGER = 3;
public int touchscreen;

Keyboard相关

未设置、无键盘、字母键盘、数字键盘、实际值

public static final int KEYBOARD_UNDEFINED = 0;
public static final int KEYBOARD_NOKEYS = 1;
public static final int KEYBOARD_QWERTY = 2;
public static final int KEYBOARD_12KEY = 3;
public int keyboard;

KeyboardHidden相关

未设置、显示键盘、隐藏键盘、隐藏软键盘、实际值

public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;

public static final int KEYBOARDHIDDEN_NO = 1;
public static final int HARDKEYBOARDHIDDEN_NO = 1;

public static final int KEYBOARDHIDDEN_YES = 2;
public static final int HARDKEYBOARDHIDDEN_YES = 2;

public static final int KEYBOARDHIDDEN_SOFT = 3;

public int keyboardHidden;
public int hardKeyboardHidden;

Navigation相关

未设置、无导航栏、键盘布局、轨迹球布局、车轮布局、实际值

public static final int NAVIGATION_UNDEFINED = 0;
public static final int NAVIGATION_NONAV = 1;
public static final int NAVIGATION_DPAD = 2;
public static final int NAVIGATION_TRACKBALL = 3;
public static final int NAVIGATION_WHEEL = 4;
public int navigation;

NavigationHidden相关

未设置、显示、隐藏、实际值

public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
public static final int NAVIGATIONHIDDEN_NO = 1;
public static final int NAVIGATIONHIDDEN_YES = 2;
public int navigationHidden;

Orientation相关

未设置、水平、垂直、正方形、实际值

public static final int ORIENTATION_UNDEFINED = 0;
public static final int ORIENTATION_PORTRAIT = 1;
public static final int ORIENTATION_LANDSCAPE = 2;
@Deprecated public static final int ORIENTATION_SQUARE = 3;
public int orientation;

UIMode相关

类型掩码、未设置、标准模式、桌面模式、车载模式、tv模式、应用模式

public static final int UI_MODE_TYPE_MASK = 0x0f;
public static final int UI_MODE_TYPE_UNDEFINED = 0x00;
public static final int UI_MODE_TYPE_NORMAL = 0x01;
public static final int UI_MODE_TYPE_DESK = 0x02;
public static final int UI_MODE_TYPE_CAR = 0x03;
public static final int UI_MODE_TYPE_TELEVISION = 0x04;
public static final int UI_MODE_TYPE_APPLIANCE = 0x05;

黑夜模式掩码、未设置、不启动黑夜模式、启动黑夜模式

public static final int UI_MODE_NIGHT_MASK = 0x30;
public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
public static final int UI_MODE_NIGHT_NO = 0x10;
public static final int UI_MODE_NIGHT_YES = 0x20;
public int uiMode;

Dp相关

未设置、可使用(最小)屏幕宽度/高度/密度实际值

public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
public int screenWidthDp;

public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
public int screenHeightDp;

public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
public int smallestScreenWidthDp;

public static final int DENSITY_DPI_UNDEFINED = 0;
public int densityDpi;

compat相关

兼容模式下的宽度、高度、最小宽度、内部记录

public int compatScreenWidthDp;
public int compatScreenHeightDp;
public int compatSmallestScreenWidthDp;
public int seq;

方法

构造函数

public Configuration() {
    setToDefaults();
}

public Configuration(Configuration o) {
    setTo(o);
}

set方法

  • 深拷贝传进来的参数
  • 所有参数设为默认值
public void setTo(Configuration o) {
    fontScale = o.fontScale;
    mcc = o.mcc;
    mnc = o.mnc;
    if (o.locale != null) {
        locale = (Locale) o.locale.clone();
    }
    userSetLocale = o.userSetLocale;
    touchscreen = o.touchscreen;
    keyboard = o.keyboard;
    keyboardHidden = o.keyboardHidden;
    hardKeyboardHidden = o.hardKeyboardHidden;
    navigation = o.navigation;
    navigationHidden = o.navigationHidden;
    orientation = o.orientation;
    screenLayout = o.screenLayout;
    uiMode = o.uiMode;
    screenWidthDp = o.screenWidthDp;
    screenHeightDp = o.screenHeightDp;
    smallestScreenWidthDp = o.smallestScreenWidthDp;
    densityDpi = o.densityDpi;
    compatScreenWidthDp = o.compatScreenWidthDp;
    compatScreenHeightDp = o.compatScreenHeightDp;
    compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
    seq = o.seq;
}

public void setToDefaults() {
    fontScale = 1;
    mcc = mnc = 0;
    locale = null;
    userSetLocale = false;
    touchscreen = TOUCHSCREEN_UNDEFINED;
    keyboard = KEYBOARD_UNDEFINED;
    keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
    hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
    navigation = NAVIGATION_UNDEFINED;
    navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
    orientation = ORIENTATION_UNDEFINED;
    screenLayout = SCREENLAYOUT_UNDEFINED;
    uiMode = UI_MODE_TYPE_UNDEFINED;
    screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
    screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
    smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
    densityDpi = DENSITY_DPI_UNDEFINED;
    seq = 0;
}

@Deprecated public void makeDefault() {
    setToDefaults();
}

设置国家、设置方向

public void setLocale(Locale loc) {
    locale = loc;
    userSetLocale = true;
    setLayoutDirection(locale);
}

public void setLayoutDirection(Locale locale) {
    final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(locale);
    screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)| (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT);
}

get方法

获取方向、根据当前参数获取方向

public int getLayoutDirection() {
    return ((screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) >> SCREENLAYOUT_LAYOUTDIR_SHIFT) - 1;
}

private static int getScreenLayoutNoDirection(int screenLayout) {
    return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
}

update方法

根据参数更新Configuration、判断是否需要更新资源

public int updateFrom(Configuration delta) {
    int changed = 0;
    if (delta.fontScale > 0 && fontScale != delta.fontScale) {
        changed |= ActivityInfo.CONFIG_FONT_SCALE;
        fontScale = delta.fontScale;
    }
    if (delta.mcc != 0 && mcc != delta.mcc) {
        changed |= ActivityInfo.CONFIG_MCC;
        mcc = delta.mcc;
    }
    if (delta.mnc != 0 && mnc != delta.mnc) {
        changed |= ActivityInfo.CONFIG_MNC;
        mnc = delta.mnc;
    }
    if (delta.locale != null && (locale == null || !locale.equals(delta.locale))) {
        changed |= ActivityInfo.CONFIG_LOCALE;
        locale = delta.locale != null? (Locale) delta.locale.clone() : null;
        changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
        setLayoutDirection(locale);
    }
    if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0))){
        userSetLocale = true;
        changed |= ActivityInfo.CONFIG_LOCALE;
    }
    if (delta.touchscreen != TOUCHSCREEN_UNDEFINED && touchscreen != delta.touchscreen) {
        changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
        touchscreen = delta.touchscreen;
    }
    if (delta.keyboard != KEYBOARD_UNDEFINED && keyboard != delta.keyboard) {
        changed |= ActivityInfo.CONFIG_KEYBOARD;
        keyboard = delta.keyboard;
    }
    if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED && keyboardHidden != delta.keyboardHidden) {
        changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
        keyboardHidden = delta.keyboardHidden;
    }
    if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED && hardKeyboardHidden != delta.hardKeyboardHidden) {
        changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
        hardKeyboardHidden = delta.hardKeyboardHidden;
    }
    if (delta.navigation != NAVIGATION_UNDEFINED && navigation != delta.navigation) {
        changed |= ActivityInfo.CONFIG_NAVIGATION;
        navigation = delta.navigation;
    }
    if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED && navigationHidden != delta.navigationHidden) {
        changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
        navigationHidden = delta.navigationHidden;
    }
    if (delta.orientation != ORIENTATION_UNDEFINED
            && orientation != delta.orientation) {
        changed |= ActivityInfo.CONFIG_ORIENTATION;
        orientation = delta.orientation;
    }
    if (getScreenLayoutNoDirection(delta.screenLayout) != (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED) && (getScreenLayoutNoDirection(screenLayout) != getScreenLayoutNoDirection(delta.screenLayout))) {
        changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
        if ((delta.screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == 0) {
            screenLayout = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK)|delta.screenLayout;
        } else {
            screenLayout = delta.screenLayout;
        }
    }
    if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED) && uiMode != delta.uiMode) {
        changed |= ActivityInfo.CONFIG_UI_MODE;
        if ((delta.uiMode&UI_MODE_TYPE_MASK) != UI_MODE_TYPE_UNDEFINED) {
            uiMode = (uiMode&~UI_MODE_TYPE_MASK) | (delta.uiMode&UI_MODE_TYPE_MASK);
        }
        if ((delta.uiMode&UI_MODE_NIGHT_MASK) != UI_MODE_NIGHT_UNDEFINED) {
            uiMode = (uiMode&~UI_MODE_NIGHT_MASK) | (delta.uiMode&UI_MODE_NIGHT_MASK);
        }
    }
    if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED && screenWidthDp != delta.screenWidthDp) {
        changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
        screenWidthDp = delta.screenWidthDp;
    }
    if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED && screenHeightDp != delta.screenHeightDp) {
        changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
        screenHeightDp = delta.screenHeightDp;
    }
    if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
        changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
        smallestScreenWidthDp = delta.smallestScreenWidthDp;
    }
    if (delta.densityDpi != DENSITY_DPI_UNDEFINED) {
        changed |= ActivityInfo.CONFIG_DENSITY;
        densityDpi = delta.densityDpi;
    }
    if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
        compatScreenWidthDp = delta.compatScreenWidthDp;
    }
    if (delta.compatScreenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
        compatScreenHeightDp = delta.compatScreenHeightDp;
    }
    if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
        compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
    }
    if (delta.seq != 0) {
        seq = delta.seq;
    }
    
    return changed;
}

public static boolean needNewResources(int configChanges, int interestingChanges) {
    return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
}

diff方法

只对比Configuration差异,不修改

public int diff(Configuration delta) {
    int changed = 0;
    if (delta.fontScale > 0 && fontScale != delta.fontScale) {
        changed |= ActivityInfo.CONFIG_FONT_SCALE;
    }
    if (delta.mcc != 0 && mcc != delta.mcc) {
        changed |= ActivityInfo.CONFIG_MCC;
    }
    if (delta.mnc != 0 && mnc != delta.mnc) {
        changed |= ActivityInfo.CONFIG_MNC;
    }
    if (delta.locale != null
            && (locale == null || !locale.equals(delta.locale))) {
        changed |= ActivityInfo.CONFIG_LOCALE;
        changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
    }
    if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
            && touchscreen != delta.touchscreen) {
        changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
    }
    if (delta.keyboard != KEYBOARD_UNDEFINED
            && keyboard != delta.keyboard) {
        changed |= ActivityInfo.CONFIG_KEYBOARD;
    }
    if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
            && keyboardHidden != delta.keyboardHidden) {
        changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
    }
    if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
            && hardKeyboardHidden != delta.hardKeyboardHidden) {
        changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
    }
    if (delta.navigation != NAVIGATION_UNDEFINED
            && navigation != delta.navigation) {
        changed |= ActivityInfo.CONFIG_NAVIGATION;
    }
    if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
            && navigationHidden != delta.navigationHidden) {
        changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
    }
    if (delta.orientation != ORIENTATION_UNDEFINED
            && orientation != delta.orientation) {
        changed |= ActivityInfo.CONFIG_ORIENTATION;
    }
    if (getScreenLayoutNoDirection(delta.screenLayout) !=
                (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
            && getScreenLayoutNoDirection(screenLayout) !=
                getScreenLayoutNoDirection(delta.screenLayout)) {
        changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
    }
    if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
            && uiMode != delta.uiMode) {
        changed |= ActivityInfo.CONFIG_UI_MODE;
    }
    if (delta.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED
            && screenWidthDp != delta.screenWidthDp) {
        changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
    }
    if (delta.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED
            && screenHeightDp != delta.screenHeightDp) {
        changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
    }
    if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
            && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
        changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
    }
    if (delta.densityDpi != DENSITY_DPI_UNDEFINED
            && densityDpi != delta.densityDpi) {
        changed |= ActivityInfo.CONFIG_DENSITY;
    }
    return changed;
}

ScreenLayout相关

  • 根据传入数值设置屏幕,hide
  • 根据传入的参数缩减屏幕,hide
  • 检查当前屏幕是否达到指定大小
static public int resetScreenLayout(int curLayout) {
    return (curLayout & ~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK | SCREENLAYOUT_COMPAT_NEEDED)) | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE);
}

static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) {
    int screenLayoutSize;
    boolean screenLayoutLong;
    boolean screenLayoutCompatNeeded;
    
    if (longSizeDp < 470) {
        screenLayoutSize = SCREENLAYOUT_SIZE_SMALL;
        screenLayoutLong = false;
        screenLayoutCompatNeeded = false;
    } else {
        if (longSizeDp >= 960 && shortSizeDp >= 720) {
            screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE;
        } else if (longSizeDp >= 640 && shortSizeDp >= 480) {
            screenLayoutSize = SCREENLAYOUT_SIZE_LARGE;
        } else {
            screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL;
        }
        if (shortSizeDp > 321 || longSizeDp > 570) {
            screenLayoutCompatNeeded = true;
        } else {
            screenLayoutCompatNeeded = false;
        }
        if (((longSizeDp*3)/5) >= (shortSizeDp-1)) {
            screenLayoutLong = true;
        } else {
            screenLayoutLong = false;
        }
    }
    if (!screenLayoutLong) {
        curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO;
    }
    if (screenLayoutCompatNeeded) {
        curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
    }
    int curSize = curLayout&SCREENLAYOUT_SIZE_MASK;
    if (screenLayoutSize < curSize) {
        curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize;
    }
    return curLayout;
}

public boolean isLayoutSizeAtLeast(int size) {
    int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
    if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
    return cur >= size;
}

toString、Parcelable、compareTo、equals、hashCode方法

不赘述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值