Launcher中数据的加载流程

本文深入解析了Launcher应用的加载逻辑,包括数据加载、控件绑定及子线程处理过程。探讨了loadAndBindWorkspace和loadAndBindAllApps方法,解释了如何加载桌面数据和应用菜单列表,以及其背后的数据库交互和PackageManager使用。

承接上一篇文章Launcher的相关知识,当我们进入startLoader方法中,看到最后有这样一行代码

sWorker.post(mLoaderTask);

第一想法是开启了子线程,要执行耗时操作,想想也对加载数据当然是耗时操作要开启子线程。但是别急者去看runnable中的逻辑,先来看看sWorker这个Handler吧。

private static final Handler sWorker = new Handler(sWorkerThread.getLooper());

平时我们创建Handler对象就直接new一个了,为什么这个构造要传入一个参数呢,获取的是一个Looper,那这个Looper是哪个线程的Looper呢?再来看看sWorkerThread对象。

private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");

是一个HandlerThread的类,看HandlerThread的源码是一个Thread的子类,好先到这里,下一篇在具体说说Launcher中我们可以学习的一些设计方式,现在我们只要知道Handler执行了post方法,因为你对应Handler的Looper是在子线程中创建的,所以代码要在子线程中执行post方法参数中Runnable类中的run方法的逻辑。
进入的LoaderTask这个内部类中,直接找到run方法:这其中比较重要的两行代码如下

....
isUpgrade = loadAndBindWorkspace();
...
loadAndBindAllApps();

第一行代码是用来加载和显示手机Launcher桌面上的数据,第二行代码是用来加载Launcher中应用菜单列表中的所有的APP数据。这里说的的是原生的安卓应用(模拟器上的Android系统就是原生的),想小米改过的系统就只有一级桌面了,没有了中间的应用菜单列表按钮。先看第一个方法

private boolean loadAndBindWorkspace() {
        ...
        isUpgradePath = loadWorkspace();
        ....
       //第一个参数是负数,表示需要对所有的桌面页进行刷新。如果正数或者0,表示对指定页面进行刷新。
      //第二个参数表示是否需要清理桌面的重复数据。
       bindWorkspace(-1, isUpgradePath);
       ....
}

这个方法中最重要的是这两行代码,第一行,看方法名就知道它是用来加载数据的,第二行是用来讲数据绑定到控件上显示出来的。
loadWorkSpace()当中的逻辑比较多了,在这里就不贴代码了,它主要是从数据库中获取到对应的字段,通过集合传递到bindWorkspace方法中,然后bindWorkspace方法通过回调接口,将数据传递到Launcher中完成数据和控件的绑定来实现数据的展示。

private void loadAndBindAllApps() {
      ....
      loadAllApps();
      ....
      onlyBindAllApps();
}

同理对于加载应用菜单列表中的应用来说,也是先加载然后绑定这样的逻辑,但是和加载桌面数据不同的是在loadAllApps()方法中没有通过数据库来加载,使用的是PackageManager来获取手机中的所有应用(这里需要说明一下,我的讲解中使用的是Android4.4的Launcher源码来说,在Android5.0中加入了多账户的机制之后,这里就不是使用的PackageManager来实现获取所有应用了,5.0之后就是获取的登录账户的所有应用)。然后onlyBindAllApps()方法就和上面一样了,拿到数据调用回调接口,将数据传递到Launcher中,展示数据。

这就是基本的Launcher的加载逻辑,这里值得要提一下的是,如果想要屏蔽掉应用菜单列表,把所有的应用都加载到桌面上,Google在系统中提供了一个开关,在Hotseat.java这个类中的resetLayout()中有一个if判断,当这个if判断是true的时候就是显示应用菜单按钮,false就是显示应用菜单按钮。

具体的关于Launcher是怎么加载应用的,当有新应用安装、更新或者删除的时候具体的逻辑,之前的文章Launcher中APP的安装、更新和删除都有介绍,不清楚的可以移步那篇文章,有什么疑问欢迎给我留言。

<think>首先,用户的问题是:“我想了解Launcher3 workspace应用图标加载流程 请问Launcher3 workspace应用图标加载流程详解”。我需要基于提供的引用和之前的上下文来回答。 回顾系统级指令: - 所有行内数学表达式用 `$...$` 格式。 - 独立公式用 `$$...$$` 格式。 - LaTeX 语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如:[^1]。 用户的问题是中文的,所以我必须用中文回答。 现在,查看提供的引用: - 引用[1]:描述了Launcher3的工作区结构,包括Workspace、CellLayout等组件。 - 引用[2]:是一个转载的链接,提到Launcher3 workspace详解。 - 引用[3]:关于Activity启动流程,特别是从Launcher3点击图标开始的冷启动。 用户的问题是关于“Launcher3 workspace应用图标加载流程”的详细解释。所以,我需要聚焦在图标如何加载到工作区的流程上。 从引用[1]中,我提取到关键点: - Workspace 是主屏幕布局。 - CellLayout 是Workspace 中的每一页。 - ShortcutAndWidgetContainer 是装载图标的容器。 - BubbleTextView 是图标的实际载体。 引用[2]是一个外部链接,但内容摘要是关于Launcher3 workspace的解释,可能涉及加载流程。 引用[3]是关于Activity启动的,不是直接相关,但可能与点击图标后的行为有关。 我需要构建一个清晰的流程: 1. Launcher3 启动时加载应用图标。 2. 图标如何被创建并添加到工作区。 3. 涉及的关键类和步骤。 可能的流程: - Launcher3 启动时,它会查询系统应用列表。 - 对每个应用,创建快捷方式图标(BubbleTextView)。 - 将这些图标添加到CellLayout(通过ShortcutAndWidgetContainer)。 - 工作区(Workspace)管理多个CellLayout页面。 步骤细化: 1. LauncherApp 或类似类加载所有安装的应用。 2. 创建AppInfo对象来表示每个应用。 3. 使用ItemInfo创建图标视图。 4. 图标视图被添加到网格布局(CellLayout)。 5. Workspace处理图标的布局和排列。 在引用[1]中提到: - Workspace: 主屏幕布局。 - CellLayout: 页面。 - ShortcutAndWidgetContainer: 容器。 - BubbleTextView: 图标载体。 所以,加载流程可能: - LauncherModel 负责加载应用数据。 - 然后绑定到Workspace。 - Workspace为每个图标创建视图。 在Android Launcher中,典型流程: 1. LauncherModel 在后台加载应用列表。 2. 当数据准备好时,通知Launcher UI(如LauncherActivity)。 3. UI线程创建视图并添加到Workspace。 回答结构: - 以清晰的步骤解释流程。 - 使用中文。 - 引用提供的引用。 - 在结束时生成相关问题。 引用标识: - 当解释基于引用[1]时,添加[^1]。 - 类似地处理其他引用。 流程详解: 1. 初始化阶段:Launcher启动时,LauncherModel加载所有安装应用的列表。这包括查询PackageManager来获取应用信息[^1]。 2. 数据绑定:绑定数据到Workspace。Workspace包含多个CellLayout页面。每个CellLayout有一个ShortcutAndWidgetContainer,它是图标的父容器[^1]。 3. 图标创建:对于每个应用,创建一个BubbleTextView对象,它代表应用图标视图。这个视图包含应用的图标、标题等[^1]。 4. 添加到工作区:图标视图被添加到CellLayout中指定的位置。CellLayout处理图标的排列和布局,基于网格系统[^1]。 5. 显示:最后,Workspace管理页面切换,PageIndicator显示当前页面索引[^1]。 确保回答真实可靠:基于Android知识,但参考提供的引用。引用[1]是最相关的。 引用[3]不直接相关,但可以提到如果用户点击图标,会触发Activity启动流程。 用户问题专注于加载流程,不是点击事件。 生成相关问题: - 在回答结束时,添加相关问题部分。 最终回答结构: 1. 简介:简要解释整个流程。 2. 详细步骤:分步描述图标加载流程。 3. 关键类:提及涉及的类。 4. 结束语:总结。 5. 相关问题:生成2-3个相关问题。 </think>### Launcher3 workspace应用图标加载流程详解 在Android系统中,Launcher3是默认的启动器应用,它负责显示桌面工作区(Workspace)上的应用图标。应用图标加载流程涉及多个组件协同工作,包括数据加载、视图创建和布局管理。下面我将基于提供的引用内容,逐步解释整个流程。核心流程可概括为:**Launcher初始化时查询应用列表 → 创建应用数据模型 → 绑定数据到视图层 → 在CellLayout中动态排列图标**。具体步骤如下: #### 1. **应用数据加载阶段** - **查询系统应用列表**:Launcher启动时,后台服务(如`LauncherModel`)通过`PackageManager`查询系统所有安装的应用信息,包括包名、图标、标签等。这些信息被封装为`AppInfo`或`ItemInfo`对象,存储在内存中[^1]。 - 关键点:此步骤通常在异步线程执行,以避免阻塞UI线程。 - **数据处理**:`LauncherModel`过滤和排序应用数据(例如,按用户配置或默认规则),准备绑定到UI组件[^1]。 #### 2. **视图绑定与创建阶段** - **Workspace初始化**:UI层(`LauncherActivity`)加载布局文件(如`launcher.xml`),其中`Workspace`作为根容器,管理多个桌面页面(每个页面是一个`CellLayout`)[^1]。 - 关键类:`Workspace`继承自`ViewGroup`,负责处理页面滑动和布局协调。 - **CellLayout准备**:每个`CellLayout`代表一个桌面页面,包含一个`ShortcutAndWidgetContainer`作为图标容器。该容器以网格形式组织图标位置(例如,4×4或5×5布局),基于`DeviceProfile.java`定义的参数(如单元格大小、间距)[^1]。 - **图标视图创建**:对于每个`AppInfo`对象,系统创建`BubbleTextView`实例作为图标的视图载体。此视图包含应用图标(`Drawable`)和标签(`TextView`),并处理点击和长按事件(如启动应用或进入编辑模式)[^1]。 - 代码片段示意: ```java // 伪代码示例:图标创建 BubbleTextView iconView = new BubbleTextView(context); iconView.applyFromApplicationInfo(appInfo); // 设置图标和标签 ``` #### 3. **图标布局与添加阶段** - **图标添加到容器**:`ShortcutAndWidgetContainer`通过`addView()`方法将`BubbleTextView`添加到指定单元格位置。位置计算基于网格索引(例如,第2行第3列),确保图标自动对齐[^1]。 - 关键点:如果工作区已满,系统会自动创建新页面(新的`CellLayout`)。 - **动态排列**:`CellLayout`使用`layoutChildren()`方法重新计算布局,处理图标拖拽、删除或添加时的动态调整。例如,卸载图标会触发`DeleteDropTarget`区域的响应[^1]。 - **最终渲染**:所有视图绑定完成后,`Workspace`刷新UI,`PageIndicator`更新页面指示器位置。图标加载过程结束,用户可见桌面图标[^1]。 #### 4. **关键类与组件角色** - `Workspace`:桌面主容器,管理页面生命周期[^1]。 - `CellLayout`:单页面网格布局,处理图标排列[^1]。 - `ShortcutAndWidgetContainer`:图标直接父容器,继承自`ViewGroup`[^1]。 - `BubbleTextView`:图标视图实现,支持交互事件[^1]。 - `LauncherModel`:后台数据加载器,与`PackageManager`交互[^1]。 #### 流程总结 整个加载流程以异步方式运行,确保性能优化:数据加载在后台完成,UI绑定在主线程执行。用户首次启动Launcher时可能会短暂延迟,但后续加载会缓存数据提升速度。此流程高度模块化,便于定制(如第三方Launcher开发)。 引用[3]提到,当用户点击图标时,会触发Activity冷启动流程(如`ActivityThread`处理进程创建),但这属于图标交互后的行为,不直接属于加载流程[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值