Launcher3主页面加载显示流程分析

布局结构

抓取布局后,可以看到每个图标是一个DoubleShadowBubbleTextView,父布局是CellLayout、workspace。

我们可以在CellLayout添加子view打印出调用堆栈信息,可以整体上看页面加载显示流程。
在这里插入图片描述

主要类

  • Launcher.java:主界面,即MainActivity
  • launcher.xml:主界面布局文件
  • LauncherModel.java:管理Launcher状态,包括加载任务、状态回调等
  • LoaderTask.java:加载任务,是一个Runnable
  • LoaderResults.java:加载结果
  • BgDataModel#Callbacks:数据回调接口,Launcher实现该接口,加载任务通过该接口回调给Launcher
  • LauncherProvider:桌面数据提供者,采用db保存桌面图标数据(包括排列位置、类型等)
  • LauncherSettings:封装访问LauncherProvider时的uri、column等一些常量,通过ContentResolver来访问LauncherProvider,不直接操作db
  • LoaderCursor:封装cursor操作

流程图

在这里插入图片描述

创建Activity

主界面创建的时候,常规的setContentView和findView,创建LauncherModel并开始加载数据

// Launcher.java
protected void onCreate(Bundle savedInstanceState) {
   
   
    super.onCreate(savedInstanceState);
    // 1.创建LauncherAppState和LauncherModel
    LauncherAppState app = LauncherAppState.getInstance(this);
    mModel = app.getModel();
    
    // 2.infalte布局文件,找到view
    setupViews();
    
    // 3. 设置loader监听,开始加载数据,加载完成后回调给主界面
    if (!mModel.addCallbacksAndLoad(this)) {
   
   
        if (!internalStateHandled) {
   
   
            // If we are not binding synchronously, pause drawing until initial bind complete,
            // so that the system could continue to show the device loading prompt
            mOnInitialBindListener = Boolean.FALSE::booleanValue;
        }
    }
   
    // 4. 设置view给Activity
    setContentView(getRootView());

加载数据

创建加载任务

mModel.addCallbacksAndLoad将Launcher设置给LauncherModel,然后创建了加载任务

// LauncherModel.java    
/**
 * Adds a callbacks to receive model updates
 * @return true if workspace load was performed synchronously
 */
public boolean addCallbacksAndLoad(@NonNull final Callbacks callbacks) {
   
   
    synchronized (mLock) {
   
   
        addCallbacks(callbacks);
        return startLoader(new Callbacks[] {
   
    callbacks });
    }
}

private boolean startLoader(@NonNull final Callbacks[] newCallbacks) {
   
   
    synchronized (mLock) {
   
   
        // 1.取消旧的加载任务
        boolean wasRunning = stopLoader(); // 之前没有loader任务,wasRunning为false
        boolean bindDirectly = mModelLoaded && !mIsLoaderTaskRunning;// 之前没有加载过,bindDirectly为false
        boolean bindAllCallbacks = wasRunning || !bindDirectly || newCallbacks.length == 0; // bindAllCallbacks为true, 上一步已经addCallbacks了,所以callbacksList里面包含从Launcher.java传进来的callbacks
        final Callbacks[] callbacksList = bindAllCallbacks ? getCallbacks() : newCallbacks;
        if (callbacksList.length > 0) {
   
   
            // 2.清空PendingBind
            for (Callbacks cb : callbacksList) {
   
   
                MAIN_EXECUTOR.execute(cb::clearPendingBinds);
            }
            // 3.创建LoaderResults和LoaderTask,开始加载数据
            LoaderResults loaderResults = new LoaderResults(
                    mApp, mBgDataModel, mBgAllAppsList, callbacksList);
            if (bindDirectly) {
   
   
                loaderResults.bindWorkspace(bindAllCallbacks);
                loaderResults.bindAllApps();
                loaderResults.bindDeepShortcuts();
                loaderResults.bindWidgets();
                return true;
            } else {
   
   
                stopLoader();
                mLoaderTask = new LoaderTask(
                        mApp, mBgAllAppsList, mBgDataModel, mModelDelegate, loaderResults);
                MODEL_EXECUTOR.post(mLoaderTask);
            }
        }
    }
}

整体加载步骤

LoaderTask#run中根据类型加载步骤分为了5步,图标的加载主要看第一步

// LoaderTask.java
public v
<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、付费专栏及课程。

余额充值