| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Jetpack学习之 App Startup,android视频开发面试问题 -> 正文阅读 |
|
[移动开发]Jetpack学习之 App Startup,android视频开发面试问题 |
因为 dependencies { def work_version = “2.4.0” implementation “androidx.work:work-runtime:$work_version” implementation “androidx.work:work-runtime-ktx:$work_version” } 然后我们可以在 WorkManager 的jar包中找到他的 可以看下
public class WorkManagerInitializer extends ContentProvider { @Override public boolean onCreate() { // 初始化操作 WorkManager.initialize(getContext(), new Configuration.Builder().build()); return true; } … } 也就是说 我们先来配置 App Startup,首先导入: implementation “androidx.startup:startup-runtime:1.0.0” App Startup提供了一个接口 public interface Initializer { @NonNull T create(@NonNull Context context); @NonNull List<Class<? extends Initializer<?>>> dependencies(); } 该接口有两个方法:
该方法用来做初始化的工作,就是我们做
该组件在初始化时,需要依赖哪些组件的初始化,返回一个列表,这个列表里的组件都实现 也就是说,这个方法可以用来决定初始化顺序 假如我们要将 WorkManager 写入到我们 App Startup 的启动优化项里,那我们需要给其实现这个接口: class WorkManagerInitializer : Initializer { override fun create(context: Context) { // 照搬 WorkManagerInitializer 的 onCreate 代码 WorkManager.initialize(context, Configuration.Builder().build()) } override fun dependencies(): MutableList<Class<out Initializer<*>>> { return mutableListOf() } } 我学着 WorkManager 在这里做了初始化,因为大部分的组件都是不依赖别的组件初始化的,所以 就和注解一样,在给所有需要 ContentProvider 初始化的组件实现了 <provider android:name=“androidx.startup.InitializationProvider” android:authorities="${applicationId}.androidx-startup" android:exported=“false” tools:node=“merge”> <meta-data android:name=“com.example.app_startup_demo.WorkManagerInitializer” android:value=“androidx.startup”/> 上面只有 这样就完成了一次启动优化啦~ 有些库可能不会在 App 初始化的时候就去初始化,而是要等使用的时候再去,即 延迟初始化,和kotlin的 而 App Startup 也考虑到了这一点,只需 AndroidManifest 中加入这个: <provider android:name=“androidx.startup.InitializationProvider” …> <meta-data android:name=“com.example.app_startup_demo.WorkManagerInitializer” tools:node=“remove”/>
如果想要使用,则要在代码中手动使用下面代码延迟初始化: AppInitializer.getInstance(this).initializeComponent(WorkManagerInitializer::class.java) ========================================================================= 上面我们可以总结出让一个使用 ContentProvider 初始化的库,来用
为什么这样做就可以降低启动耗时呢? 这边来简单的解析一下它做了什么。 其实最关键的地方还是在于它在 <provider android:name=“androidx.startup.InitializationProvider” android:authorities="${applicationId}.androidx-startup" android:exported=“false” tools:node=“merge”>
指向
授权方列表,没有默认值且该值必须是整个手机唯一的,所以一般会在前面加 applicationId 的前缀
其他应用程序是否可以使用这个内容提供器,这里设置为false,表示不可以
这个是XML文件的属性,它标志着该节点(即标签)的行为 可以看到 举个例子,我们的项目有主项目和引用的jar包,它们都会使用用一个 name 为 ActivityOne 的 这样就会出现一个问题,你两个清单文件都使用到了含有同一个 name 的标签,那么打包编译时肯定会出现问题,因为最终编译出来的 activity 的标签要是唯一的,这个地方就不知道使用哪一个。 Android提供的一种解决方式就是使用 下面是两个清单文件: // 第三方jar包----低优先级清单文件 <activity android:name=“com.example.ActivityOne” android:windowSoftInputMode=“stateUnchanged”> // 主项目----高优先级清单文件 <activity android:name=“com.example.ActivityOne” android:screenOrientation=“portrait” tools:node=“merge”> // 这里进行节点merge,合并所有name为 com.example.ActivityOne 的 activity标签 打包后,形成的新的标签为: <activity android:name=“com.example.ActivityOne” android:screenOrientation=“portrait” android:windowSoftInputMode=“stateUnchanged”> 所以 通过 那么在打包之后,一个应用只有一个 ContentProvider,然后执行它的 点进 public final class InitializationProvider extends ContentProvider { @Override public boolean onCreate() { Context context = getContext(); if (context != null) { // 1 AppInitializer.getInstance(context).discoverAndInitialize(); } else { throw new StartupException(“Context cannot be null”); } return true; } } 注释1处,执行 // AppInitializer.java void discoverAndInitialize() { try { Trace.beginSection(SECTION_NAME); ComponentName provider = new ComponentName(mContext.getPackageName(), InitializationProvider.class.getName()); // 1 ProviderInfo providerInfo = mContext.getPackageManager() .getProviderInfo(provider, GET_META_DATA); // 2 Bundle metadata = providerInfo.metaData; String startup = mContext.getString(R.string.androidx_startup); if (metadata != null) { Set<Class<?>> initializing = new HashSet<>(); Set keys = metadata.keySet(); // 3 for (String key : keys) { String value = metadata.getString(key, null); if (startup.equals(value)) { Class<?> clazz = Class.forName(key); if (Initializer.class.isAssignableFrom(clazz)) { Class<? extends Initializer<?>> component = (Class<? extends Initializer<?>>) clazz; // 4 mDiscovered.add(component); if (StartupLogger.DEBUG) { StartupLogger.i(String.format(“Discovered %s”, key)); } // 5 doInitialize(component, initializing); } } } } } catch (PackageManager.NameNotFoundException | ClassNotFoundException exception) { throw new StartupException(exception); } finally { Trace.endSection(); } } 这段代码不是很难,来分析一下: 注释1: 打包后,清单文件里面只有一个 InitializationProvider 的 注释2: 根据注释处的对象,获取到该标签下的 注释3:遍历 注释4:一直筛选,符合实现 注释5:执行 这个方法就是遍历 接下来看下 // AppInitializer.java T doInitialize( @NonNull Class<? extends Initializer<?>> component, @NonNull Set<Class<?>> initializing) { synchronized (sLock) { boolean isTracingEnabled = Trace.isEnabled(); try { if (isTracingEnabled) { Trace.beginSection(component.getSimpleName()); } if (initializing.contains(component)) { String message = String.format( “Cannot initialize %s. Cycle detected.”, component.getName() ); throw new IllegalStateException(message); } Object result; // 1 if (!mInitialized.containsKey(component)) { initializing.add(component); try { // 2 Object instance = component.getDeclaredConstructor().newInstance(); // 3 Initializer<?> initializer = (Initializer<?>) instance; // 4 List<Class<? extends Initializer<?>>> dependencies = initializer.dependencies(); if (!dependencies.isEmpty()) { // 5 for (Class<? extends Initializer<?>> clazz : dependencies) { if (!mInitialized.containsKey(clazz)) { doInitialize(clazz, initializing); } } } if (StartupLogger.DEBUG) { StartupLogger.i(String.format(“Initializing %s”, component.getName())); } // 6 result = initializer.create(mContext); if (StartupLogger.DEBUG) { StartupLogger.i(String.format(“Initialized %s”, component.getName())); |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 7:15:16- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |