当前位置: 首页 > 科技观察

深入理解Android架构AppStartup原理

时间:2023-03-22 00:15:29 科技观察

前言AndroidStartup提供了一种更简单、更高效的方式来在应用程序启动时初始化组件。开发者可以使用AndroidStartup来简化启动顺序,明确设置组件间的初始化顺序和依赖关系;今天我们就来说说1.简单介绍一下使用AndroidXAppStartup来运行所有依赖的初始化。两种方式:自动初始化;手动初始化(也延迟初始化);1、自动初始化在build.gradle文件中添加依赖;implementation"androidx.startup:startup-runtime:1.0.0-alpha01"实现了Initializer接口并重新编写了两个方法来初始化组件;publicclassMvpInitializerimplementsInitializer{@NonNull@OverridepublicVoidcreate(@NonNullContextcontext){MvpManager.init(context);returnull;}@NonNull@OverridepublicList>>dependencies(){returnnewArrayList<>();}}......}create(Context):这里,进行组件初始化工作;dependencies():返回需要初始化的列表,同时设置App启动时依赖库的运行顺序;在AndroidManifest.xml文件中注册InitializationProvider;App启动时,AppStartup会读取AndroidManifest.xml文件中InitializationProvider下声明的组件进行初始化,完成后会自动进行初始化工作;2.手动初始化(也有延迟初始化)在build.gradle文件中添加依赖;创建类LibaryD实现Initializer接口,并重写两个初始化组件的方法;在AndroidManifest中注册InitializationProvider只需要在列表合并工具的tag中添加tools:node="remove"就会重新将其从列表文件中移出;在需要的地方初始化,调用下面的代码进行初始化;Initializer.getInstance(context).initializeComponent(Initializer::class.java);如果在组件初始化之后,再次调用AppInitializer.initializeComponent()方法不会再次初始化;手动初始化(也是惰性初始化)非常有用,App启动时组件不需要运行,只需要在需要的地方运行,可以减少App的启动时间,提高启动速度;二、源码分析1、AndroidManifest文件中配置的InitializationProvider的组件名称必须是androidx.startup.InitializationProvider。现在让我们看一下这个类的源代码;(context!=null){初始化AppInitializer.getInstance(context).discoverAndInitialize();}else{thrownewStartupException("Contextcannotbenull");}returntrue;}@OverridepublicCursorquery(...){thrownewIllegalStateException("Noallowed.");}@OverridepublicStringgetType(...){thrownewIllegalStateException("不允许。");}@Nullable@OverridepublicUriinsert(...){thrownewIllegalStateException("不允许。");}@Overridepublicintdelete(...){thrownewIllegalStateException("不允许。");}@Overridepublicintupdate(...){thrownewIllegalStateExceptionon("Notallowed.");}}InitializationProvider其实就是利用了ContentProvider的启动机制,在ContentProvider#onCreate(...);ContentProvider的其他方法没有意义,所以抛出IllegalStateException;2、自动初始化分析AppStartup调用ContentProvider中的AppInitializer#discoverAndInitialize()进行自动初始化;AppInitializer是AppStartup框架的核心类,整个AppStartup框架的代码其实很少,大部分核心代码都在AppInitializer类中;2.1.AppInitializer.javadiscoverAndInitializefinalSet>>mDiscovered;voiddiscoverAndInitialize(){获取androidx.startup.InitializationProvider组件信息ComponentNameprovider=newComponentName(mContext.getPackageName(),InitializationProvider.class.getName());ProviderInfoproviderInfo=mContext.getPackageManager().getProviderInfo(provider,GET_META_DATA);androidx.startupstringStringstartup=mContext.getString(R.string.androidx_startup);获取组件信息中的meta-data数据Bundlemetadata=providerInfo.metaData;遍历meta-data数据if(metadata!=null){Set>initializing=newHashSet<>();Setkeys=metadata.keySet();for(Stringkey:keys){Stringvalue=metadata.getString(key,null);判断meta-data数据中,value为androidx.startup的key值Forif(startup.equals(value)){Classclazz=Class.forName(key);检查指定类是否为Initializer接口的实现类mDiscoveredSetmDiscovered.add(component);初始化该组件doInitialize(component,initializing);}}}}}mDiscovered用于判断组件是否已经自动启动publicbooleanisEagerlyInitialized(@NonNullClass>component){returnmDiscovered.contains(component);}获取androidx.startup.InitializationProvider组件信息(每个Module中声明的组件信息,会在manifest合并工具androidx.startupstring中;获取组件信息中的meta-data数据;遍历meta-data数据;判断meta-data数据中,值为androidx.startup的键值对;检查指定类是否为Initializer接口的实现类;将Class添加到mDiscoveredSet,用于判断组件是否已经自动启动;初始化这个成分;2.2.AppInitializer.javaAppInitializer.javaprivatestaticfinalObjectsLock=newObject();缓存各个组件的初始化结果;finalMap,Object>mInitialized;初始化此组件TdoInitialize(Class>component,Set>initializing){locksLockObjectresult;判断有当前组件在初始化,说明存在循环依赖(message);}检查当前组件是否已经初始化if(!mInitialized.containsKey(component)){当前组件未初始化记录正在初始化initializing.add(component);通过反射实例化Initializer接口实现类Objectinstance=component.getDeclaredConstructor().newInstance();Initializerinitializer=(Initializer)instance;遍历依赖组件List>>dependencies=initializer.dependencies();if(!dependencies.isEmpty()){for(Class>clazz:dependencies){如果依赖组件未初始化,递归执行初始化if(!mIninitialized.containsKey(clazz)){doInitialize(clazz,initializing);注意:这里将initialize作为参数传入}}}初始化当前组件result=initializer.create(mContext);移除初始化记录initializing.remove(component);缓存初始化结果mInitialized.put(component,result);}else{当前组件已经初始化,直接returnresult=mInitialized.get(component);}return(T)result;}锁定sLock;组件,说明存在循环依赖(这是因为在递归初始化依赖组件的时候,initializing会作为参数传入,如果初始化中有当前组件,说明依赖关系形成循环,如果没有抛出异常,将形成无限递归);检查当前组件是否已经初始化;正在初始化记录;通过反射实例化实现Initializer接口的类;遍历依赖组件,如果依赖组件没有初始化,则递归调用doInitialize(...)进行初始化;初始化当前组件;删除正在初始化的记录;缓存初始化结果;3、手动初始化源码分析手动初始化(懒加载)源码分析:AppInitializer。..)方法:returndoInitialize(component,newHashSet>());}其实很简单,就是调用上一节的doInitialize(...)进行初始化需要注意的是,这个方法是允许在子线程中调用的。也就是说,自动初始化和手动初始化之间存在线程同步问题,那么AppStartup是如何解决的呢?sLock之前不是说了吗?其实就是用来保证线程同步的锁:TdoInitialize(Class>component,Set>initializing){locksLocksynchronized(sLock){...}}SummaryAppStartup是Jetpack的新成员。解决App启动时运行多个ContentProvider会增加App启动时间的问题;它使用InitializationProvider来管理多个依赖项,消除了为每个库单独使用ContentProvider的成本,并减少了初始化时间。;AppStartup允许你自定义组件的初始化顺序;AppStartup提供了一种延迟初始化组件的方法,以减少App初始化时间;

最新推荐
猜你喜欢