Android源码中单例模式分析

前言

Android系统中,我们经常会通过Context获取系统级别的服务,如WindowManagerServiceActivityManagerService等,更长用的是一个LayoutInflater的类,这些服务会在合适的时候以单例的形式注册在系统中,在我们需要的时候就通过ContextgetSystemService(String name)获取。我们以常用的LayoutInflater为例来说明。

ListView的getView方法

平时我们使用LayoutInflater较为常见的地方是在ListView适配器的getView()中。代码

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(mLayoutId, parent, false);
            convertView.setTag(holder);
        }else{
           convertView = (ViewHolder)paramView.getTag();
        }
        return convertView;
    }

通常我们使用LayoutInflater.from(Context)来获取LayoutInflater服务,下面看看LayoutInflater.from(Context)的实现。

    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)方法内部调用的是ContextgetSystemService(String key)方法,我们跟踪到Context类看到,该类是抽象类。

   public abstract class Context{

   }

其实在ApplicationActivityService中都会存在一个Context对象,即Context的总数为Activity个数+Service个数+1。而ListView通常显示在Activity中,那我们就以Activity中的Context分析。

ActivityThread的main方法

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

    public static void main(String[] args) {
        ...
        //主线程消息循环
        Looper.prepareMainLooper();
        //创建ActivityThread对象
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        ...
        Looper.loop();
    }


    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 {
                //关联appThread
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ...
        } else {
            ...
            try {
                mInstrumentation = new Instrumentation();
                //创建application的Context
                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);
            }
        }
    }

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

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        ...
        Activity a = performLaunchActivity(r, customIntent);
        ...
        //Activity的OnResume生命周期
        handleResumeActivity();
    }

    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);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } 
        ...

        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.referrer, r.voiceInteractor, window);
                ...
                activity.mCalled = false;
                if (r.isPersistable()) {
                    //Activity的OnCreate生命周期
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ...
                //Activity的onStart生命周期
                activity.performStart();
                ...
            }
            ...
        } 

        return activity;
    }


    private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
        ...
        //创建Activity的Context
        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.token, displayId, r.overrideConfig);
        appContext.setOuterContext(activity);
        Context baseContext = appContext;
        ...
        return baseContext;
    }

通过以上代码的分析,我们找到Context的实现类就是ContextImpl ,我们继续跟踪ContextImpl 类的getSystemService(String key),代码如下:

    @Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

SystemServiceRegistry分析

从这个类的名字我们可以发现,这个类貌似就是注册服务的,实际上这个类中一个静态代码块,来注册各种服务,代码如下:

    static {
        ...
        //蓝牙服务
        registerService(Context.BLUETOOTH_SERVICE, BluetoothManager.class,
                new CachedServiceFetcher<BluetoothManager>() {
            @Override
            public BluetoothManager createService(ContextImpl ctx) {
                return new BluetoothManager(ctx);
            }});
        //剪切板服务
        registerService(Context.CLIPBOARD_SERVICE, ClipboardManager.class,
                new CachedServiceFetcher<ClipboardManager>() {
            @Override
            public ClipboardManager createService(ContextImpl ctx) {
                return new ClipboardManager(ctx.getOuterContext(),
                        ctx.mMainThread.getHandler());
            }});
        //电池服务
        registerService(Context.BATTERY_SERVICE, BatteryManager.class,
                new StaticServiceFetcher<BatteryManager>() {
            @Override
            public BatteryManager createService() {
                return new BatteryManager();
            }});
        //NFC服务
        registerService(Context.NFC_SERVICE, NfcManager.class,
                new CachedServiceFetcher<NfcManager>() {
            @Override
            public NfcManager createService(ContextImpl ctx) {
                return new NfcManager(ctx);
            }});
        //布局填充LayoutInflater服务
        registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
                new CachedServiceFetcher<LayoutInflater>() {
            @Override
            public LayoutInflater createService(ContextImpl ctx) {
                return new PhoneLayoutInflater(ctx.getOuterContext());
            }});
        //WIFI服务
        registerService(Context.WIFI_SERVICE, WifiManager.class,
                new CachedServiceFetcher<WifiManager>() {
            @Override
            public WifiManager createService(ContextImpl ctx) {
                IBinder b = ServiceManager.getService(Context.WIFI_SERVICE);
                IWifiManager service = IWifiManager.Stub.asInterface(b);
                return new WifiManager(ctx.getOuterContext(), service,
                        ConnectivityThread.getInstanceLooper());
            }});
        //窗口服务
        registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
            @Override
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx);
            }});

        //相机服务
        registerService(Context.CAMERA_SERVICE, CameraManager.class,
                new CachedServiceFetcher<CameraManager>() {
            @Override
            public CameraManager createService(ContextImpl ctx) {
                return new CameraManager(ctx);
            }});
        //网络状态服务
        registerService(Context.NETWORK_STATS_SERVICE, NetworkStatsManager.class,
                new CachedServiceFetcher<NetworkStatsManager>() {
            @Override
            public NetworkStatsManager createService(ContextImpl ctx) {
                return new NetworkStatsManager(ctx.getOuterContext());
            }});
        ...等等
    }

以上静态代码块在该类第一次加载时执行,且只执行一次,保证实例唯一性。以上服务就包含了布局填充器服务LayoutInflater Service 。看下如何获取

    private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
    
    //Service缓存容器
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();
    
    //注册服务器
    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);
    }
    
    //获取Service
    @Override
    public final T getService(ContextImpl ctx) {
       final Object[] cache = ctx.mServiceCache;
       synchronized (cache) {
        // Fetch or create the service.
       //从缓存中获取
       Object service = cache[mCacheIndex];
       if (service == null) {
           service = createService(ctx);
           cache[mCacheIndex] = service;
        }
       return (T)service;
     }

通过ContextImpl类的分析,我们知道将服务以键值对的形式存储在一个hashMap中,用户使用时只需要根据key来获取到对应的ServiceFetcher,然后通过调用ServiceFetchergetService方法来获取具体的的服务对象。以上便达到了单例的效果。

推荐阅读更多精彩内容