您的位置:首页 > 移动开发 > Android开发

Android源码中的单例模式

2016-01-27 10:57 369 查看

LayoutInflater 源码浅析

在Android中,我么常用LayoutInflater来加载一个布局,通常我们使用LayoutInflater.from(Context)来获取LayoutInflater服务。在Android系统中我们经常会通过Context获取系统级别的服务,如WindowManagerService、ActivityManagerService等,LayoutInflater也是其中之一,这些服务会在合适的时候以单例的形式注册在系统中,在我们需要的时候通过Context的getSystemService(String name)获取。我们以LayoutInflater为例说明,接下来我们看看LayoutInflater.from(Context)的实现:

[code]public static LayoutInflater from(Context context) {
    LayoutInflater LayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         if (LayoutInflater == null) {
             throw new AssertionError("LayoutInflater not found.");
         }
         return LayoutInflater;
}


可以看到from方法中是调用Context的getSystemService(String name)方法,我们知道Context是一个抽象类,我们要看具体的实现还要找出Context的实现类。那么这个Context对象的具体实现类是什么呢?

其实在Application、Activity、Service都会存在一个Context对象,即Context的总个数为Activity个数 + Service个数 + 1.而我们使用LayoutInflater一般在Activity中使用,所以这个Context一定是Activity的Context。接下来我们从Activity的Context入手进行分析。

我们知道,一个Activity的入口是ActivityThread的main函数,在main函数中创建一个新的ActivityThread对象,并且启动消息循环(UI线程),创建新的Activity、新的Context对象,然后将该Context对象传递给Activity。下面看看ActivityThread源代码:

[code] public static void main(String[] args) {
        // 省略代码

        Process.setArgV0("<pre-initialized>");
        // 主线程消息循环
        Looper.prepareMainLooper();
        // 创建ActivityThread对象
        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        AsyncTask.init();

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        // 不是系统应用的情况
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            // Watch for getting close to heap limit.
            BinderInternal.addGcWatcher(new Runnable() {
                @Override public void run() {
                    if (!mSomeActivitiesChanged) {
                        return;
                    }
                    Runtime runtime = Runtime.getRuntime();
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                    if (dalvikUsed > ((3*dalvikMax)/4)) {
                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                + " total=" + (runtime.totalMemory()/1024)
                                + " used=" + (dalvikUsed/1024));
                        mSomeActivitiesChanged = false;
                        try {
                            mgr.releaseSomeActivities(mAppThread);
                        } catch (RemoteException e) {
                        }
                    }
                }
            });
        } else {
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            try {
                mInstrumentation = new Instrumentation();
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        // add dropbox logging to libcore
        DropBox.setReporter(new DropBoxReporter());

        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
            @Override
            public void onConfigurationChanged(Configuration newConfig) {
                synchronized (mResourcesManager) {
                    // We need to apply this change to the resources
                    // immediately, because upon returning the view
                    // hierarchy will be informed about it.
                    if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                        // This actually changed the resources!  Tell
                        // everyone about it.
                        if (mPendingConfiguration == null ||
                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                            mPendingConfiguration = newConfig;

                            sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                        }
                    }
                }
            }
            @Override
            public void onLowMemory() {
            }
            @Override
            public void onTrimMemory(int level) {
            }
        });
    }


在main方法中,我们创建一个ActivityThread对象后,调用了其attach函数,并且参数为false。在attach函数中,参数为false的情况下(即非系统应用),会通过Binder机制与ActivityManagerService通信,并且最终调用handleLaunchActivity函数,我们看看该函数的实现:

[code]private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 代码省略
    Activity a = performLaunchActivity(r, customIntent);
    // 代码省略
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // 代码省略
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            // 创建Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            // 代码省略
        } catch (Exception e) {
            // 代码省略
        }

        try {
            // 创建Application对象
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            // 省略代码
            if (activity != null) {
                // 获取Context对象
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title =             r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                // 省略代码
                // 将appContext对等对象attach到activity中
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.voiceInteractor);

                // 省略代码
                // 调用Activity的onCreate方法
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
               // 代码省略
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            // 代码省略
        }

        return activity;
    }

 private Context createBaseContextForActivity(ActivityClientRecord r,
            final Activity activity) {
        // 创建Context对象,可以看到实现类是ContextImpl
        ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
        appContext.setOuterContext(activity);
        Context baseContext = appContext;
        // 省略代码
        return baseContext;
    }


同过上面代码分析可以知道,Context的实现类为ContextImpl。我们继续跟踪ContextImpl类:

[code]class ContextImpl extends Context {
    // 代码省略
    static class More ...ServiceFetcher {
         int mContextCacheIndex = -1;

        public Object getService(ContextImpl ctx) {
            ArrayList<Object> cache = ctx.mServiceCache;
            Object service;
            synchronized (cache) {
                if (cache.size() == 0) {
                    // Initialize the cache vector on first access.
                    // At this point sNextPerContextServiceCacheIndex
                    // is the number of potential services that are
                    // cached per-Context.
                    for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {
                        cache.add(null);
                    }
                } else {
                    service = cache.get(mContextCacheIndex);
                    if (service != null) {
                        return service;
                    }
                }
                service = createService(ctx);
                cache.set(mContextCacheIndex, service);
                return service;
            }
        }

        /**
         * 子类覆写该方法用以创建服务对象
         */
        public Object createService(ContextImpl ctx) {
            throw new RuntimeException("Not implemented");
        }
    }

    // 1.Service容器
    private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =
            new HashMap<String, ServiceFetcher>();

    private static int sNextPerContextServiceCacheIndex = 0;
    // 2.注册服务
    private static void registerService(String serviceName, ServiceFetcher fetcher) {
        if (!(fetcher instanceof StaticServiceFetcher)) {
            fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
        }
        SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
    }

    // 3.静态语句块,第一次加载该类时执行(只执行一次,保证实例的唯一性)
    static {
        // 代码省略
        // 注册LayoutInflater service
        registerService(LAYOUT_INFLATER_SERVICE, new ServiceFetcher() {
                public Object createService(ContextImpl ctx) {
                    return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
                }});
        //代码省略
    }

    // 4.根据key获取对应的服务
     @Override
    public Object getSystemService(String name) {
        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
        return fetcher == null ? null : fetcher.getService(this);
    }
    // 代码省略
}


从ContextImpl类的部分代码可以看到,在虚拟机第一次加载该类时会注册各种ServiceFetcher,其中就包含了LayoutInflater Service。将这些服务以键值对的形式存储在一个HashMap中,用户使用时只需要根据key来获取到对应的ServiceFetcher,然后通过ServiceFetcher对象的getService函数来获取具体的服务对象。当第一次获取时,会调用ServiceFetcher的createService函数创建服务对象,然后将该对象存到一个列表中,下次再取时从缓存中获取,避免重复创建对象,从而达到单例的效果。关于LayoutInflater的原理可以参考《 LayoutInflater源码深度分析笔记》这种方式我们在《确保对象的唯一性——单例模式》一文中有所介绍,大家有兴趣可以看一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: