单例模式-LayoutInflater
前言
在Android系统中,我们通常会通过上下文对象Context获取一些系统级别的服务。而这些服务会在适当的时候以单例的形式注册在系统中,那么我们就可以通过Context的getSystemService(String name)获取。
以下的源码是Android8.0 API 26。
LayoutInflater
今天我们来看一下Android源码中的设计模式之单例模式。我们来讲一讲我们经常用到的单例类LayoutInflater。在我们使用RecylerView时,经常会用到,我们写RecyclerView的适配器时就会用到,如:
public class RvAdapter extends RecyclerView.Adapter<RvViewHolder> { ... @NonNull @Override public RvViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_item,parent,false); return new RvViewHolder(itemView); } ...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
我们使用LayoutInflater.from(parent.getContext())来获取我们的LayoutInflater服务。我们来看看LayoutInflater的from方法:
/**
* Obtains the LayoutInflater from the given 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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
从上面的代码,结合我们在前言中提到的,可知,LayoutInflater已在某个时刻以单例的形式注册在系统中了。我们现在通过上下文对象Context去获取这个对象。那么我们去看看Context对象的getSystemService方法是如何获取系统服务的:
/**
* Interface to global information about an application environment. This is
* an abstract class whose implementation is provided by
* the Android system. It
* allows access to application-specific resources and classes, as well as
* up-calls for application-level operations such as launching activities,
* broadcasting and receiving intents, etc.
*/
public abstract class Context {
public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name); /** * Return the handle to a system-level service by class. * <p> * Currently available classes are: * {@link android.view.LayoutInflater} * ... */
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
从上面的信息,我们可以知道Context是一个抽象类,它的实现是由Android系统提供的。Context提供了关于应用环境的全局信息的接口,即我们可以通过Context提供的接口获取关于应用的全局信息。我们看看Android系统对Context的实现,如果想知道Context的实现类,我们就要找到Context在哪里被初始化,我们可以从Activity的初始化开始查找,一个Activity的入口是ActivityThread的main函数:
ActivityThread对象管理应用进程的主线程的执行,如计划和执行activity、广播和其他activity管理者请求的操作。
/**
* This manages the execution of the main thread in an
* application process, scheduling and executing activities,
* broadcasts, and other operations on it as the activity
* manager requests.
*
* {@hide}
*/
public final class ActivityThread extends ClientTransactionHandler {
public static void main(String[] args) { ... /** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. * 将当前线程初始化为一个循环,作为应用程序的主循环,这个主循环是Android环境创建,我 * 们不能亲自去调用这个prepareMainLooper方法 */ Looper.prepareMainLooper(); ... /** * 创建ActivityThread对象 */ ActivityThread thread = new ActivityThread(); thread.attach(false); ... /**
* 初始化主线程的Handler
*/ if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } ... /** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. * 在这个线程运行消息队列 */ Looper.loop(); ... }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
我再来看看thread.attach()这个方法:
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 = ActivityManager.getService(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } // 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) { throw e.rethrowFromSystemServer(); } } } }); } 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.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> { 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(globalConfig, null /* compat */)) { updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(), mResourcesManager.getConfiguration().getLocales()); // This actually changed the resources! Tell everyone about it. if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(globalConfig)) { mPendingConfiguration = globalConfig; sendMessage(H.CONFIGURATION_CHANGED, globalConfig); } } } }; ViewRootImpl.addConfigCallback(configChangedCallback); }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
从上面的代码我们看到Context的实现类,可能是ContextImpl,我们来看看ContextImpl.java:
ContextImpl为Context API的一般实现,它为Activity和其他应用组件提供了基本的上下文对象。
/**
* Common implementation of Context API, which provides the base
* context object for Activity and other application components.
*/
class ContextImpl extends Context {
... @Override public Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name); } ...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
SystemServiceRegistry类管理所有系统服务,可以通过Context对象的getSystemService方法获得服务。
/**
* Manages all of the system services that can be returned by {@link Context#getSystemService}.
* Used by {@link ContextImpl}.
*/
final class SystemServiceRegistry {
... /** * Gets a system service from a given context. */ public static Object getSystemService(ContextImpl ctx, String name) { ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name); return fetcher != null ? fetcher.getService(ctx) : null; } ...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
SYSTEM_SERVICE_FETCHERS是一个HashMap:
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap<String, ServiceFetcher<?>>();
- 1
- 2
SystemServiceRegistry还有一段这样的代码:
/** * Base interface for classes that fetch services. * These objects must only be created during static initialization. */ static abstract interface ServiceFetcher<T> { T getService(ContextImpl ctx); } /** * Override this class when the system service constructor needs a * ContextImpl and should be cached and retained by that context. */ static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> { private final int mCacheIndex; public CachedServiceFetcher() { mCacheIndex = sServiceCacheSize++; } @Override @SuppressWarnings("unchecked") 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) { try { service = createService(ctx); cache[mCacheIndex] = service; } catch (ServiceNotFoundException e) { onServiceNotFound(e); } } return (T)service; } } public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
CachedServiceFetcher的mCacheIndex会保存单例在数组中的位置,数组的初始化也就是单例的初始化是在下面这个静态代码块里完成。
SystemServiceRegistry有一个静态块:
static { // 注册各种各样的服务,都是单例 ... registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class, new CachedServiceFetcher<LayoutInflater>() { @Override public LayoutInflater createService(ContextImpl ctx) { return new PhoneLayoutInflater(ctx.getOuterContext()); }}); ... } /** * Statically registers a system service with the context. * This method must be called during static initialization only. */ 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); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
至此,我们终于从SystemServiceRegistry对象中把LayoutInflater单例取回来了。
核心服务以单例形式存在,减少了资源的消耗。
谢谢
文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_40763897/article/details/103841322
- 点赞
- 收藏
- 关注作者
评论(0)