Context

基础

        当应用的进程启动时,会得到一个整个应用的context(通过getApplicationContext()得到)。Activity,Service都是Context的子类,所以每一个Activity,Service都是一个Context
        在一般情况下,两者是可以通用的,如toast中需要的context传入两者中的任何一个都行。但在有些时候只能用后者,不能用前者。如上面说的弹出dialog时(因为dialog是activity的一部分)。所以,在以后需要context的时候,尽量使用activity.this,而不使用getApplicationContext()。但是,当打开数据库的时候,如果传入的context是activity.this,那么这个打开的数据库,会随着activity的销毁而关闭;如果传入的是getApplicationContext,就不会有这种情况 。
        另外还有在测试单元中,也可以得到一个context,这个context是虚拟的。
        Context的子类为ContextImpl。

setOuterContext

        该方法是在ActivityThread#createBaseContextForActivity()——它是startActivity()执行的必经一步——中进行调用的,其传入的为一个Activity实例。
        因此,Context中可以通过mOuterContext访问到它所关联的Activity实例。同样,在Activity实例中可通过mBase访问到它所关联的Context对象。

getSystemService

        经常使用它来获取一些管理类。 对于Context而言,它的实现子类是ContextImpl。ContextImpl中的方法如下:
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }
        SystemServiceRegistry,该类其内部八、九成的代码都在一个静态代码块中,而在ContextImpl有一个成员变量定义如下:
    final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();//后者只是返回了一个Object[]
        因此,在ContextImpl初始化时SystemServiceRegistry就已经加载成功了,静态代码块中的代码也早就执行完毕了。
        在静态代码块中,全部是调用registerService(),截取其中一部分如下:

	    registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
                new CachedServiceFetcher<LayoutInflater>() {
            @Override
            public LayoutInflater createService(ContextImpl ctx) {
                return new PhoneLayoutInflater(ctx.getOuterContext());
            }});
            registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
                new CachedServiceFetcher<ActivityManager>() {
            @Override
            public ActivityManager createService(ContextImpl ctx) {
                return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
            }});
        可以看出,该代码块就是注册一堆的Fetcher。看一下registerService()以及相对的get方法如下:
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

    public static String getSystemServiceName(Class<?> serviceClass) {
        return SYSTEM_SERVICE_NAMES.get(serviceClass);
    }

    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }
        涉及到的两个变量的定义如下:
    private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();
        因此,registerService()只是将简单地将往两个Map中添加数据。而get也只是简单地从两个map中取数据。
        从上面的分析可以得出:
Context#getSystemService->SystemServiceRegistry#getSystemService()->CachedServiceFetcher#getService.
        CachedServiceFetcher如下:
    static abstract interface ServiceFetcher<T> {
        T getService(android.app.ContextImpl ctx);
    }
    static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
        private final int mCacheIndex;

        public CachedServiceFetcher() {
            mCacheIndex = sServiceCacheSize++;
            //sServiceCacheSize为静态的全局变量,每new一个CachedServiceFetcher对象时,自动+1,这样就保证了不同的CachedServiceFetcher对象中mCacheIndex是不同的。
        }

        @Override
        @SuppressWarnings("unchecked")
        public final T getService(android.app.ContextImpl ctx) {
            final Object[] cache = ctx.mServiceCache;
            synchronized (cache) {
                Object service = cache[mCacheIndex];
                if (service == null) {//第一次调用,该判断肯定成立。
                    service = createService(ctx);
                    cache[mCacheIndex] = service;//缓存,下次就不用走createService()了。也就是实现了各种Context#getSystemService()返回值的单例模式。
                }
                return (T)service;
            }
        }

        public abstract T createService(android.app.ContextImpl ctx);//这个方法,在静态代码中registerService时都实现了
    }
        因此,可以将上面的调用过程补充完整
Context#getSystemService->SystemServiceRegistry#getSystemService()->CachedServiceFetcher#getService()->CachedServiceFetcher#createService
        故Context#getSystemService的返回值就是CachedServiceFetcher#createService的返回值。根据自己传入到getSystemService中的值就可以得到对应的Service的实例,而且getSystemService返回的实例都是单例的。例如LayoutInflater的具体实现子类就是PhoneLayoutInflater,WindowManager的具体实现子类为WindowManagerImpl。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值