Launcher布局加载流程

本文详细解析了AndroidManifest文件中与桌面启动相关的配置,包括Launcher活动、设置活动和Launcher提供者。接着深入探讨了桌面布局的组成,如DragLayer、Workspace、SearchDropTargetBar等组件。接着,介绍了Launcher的onCreate方法、LauncherModel的startLoader方法及LoaderTask的运行流程,详细阐述了workspace的加载过程,包括从数据库加载数据和显示在界面上的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、AndroidManifest文件

    <application
        android:backupAgent="com.android.launcher3.LauncherBackupAgent"
        android:fullBackupOnly="true"
        android:fullBackupContent="@xml/backupscheme"
        android:hardwareAccelerated="true"
        android:icon="@drawable/ic_launcher_home"
        android:label="@string/derived_app_name"
        android:theme="@style/AppTheme"
        android:largeHeap="@bool/config_largeHeap"
        android:restoreAnyVersion="true"
        android:supportsRtl="true" >
        
        <activity
            android:name="com.android.launcher3.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="unspecified"
            android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
            android:resizeableActivity="true"
            android:resumeWhilePausing="true"
            android:taskAffinity=""
            android:enabled="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
                <category android:name="android.intent.category.LAUNCHER_APP" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.android.launcher3.SettingsActivity"
            android:label="@string/settings_button_text"
            android:theme="@android:style/Theme.DeviceDefault.Settings"
            android:autoRemoveFromRecents="true">
            <intent-filter>
                <action android:name="android.intent.action.APPLICATION_PREFERENCES" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <provider
            android:name="com.android.launcher3.LauncherProvider"
            android:authorities="com.android.launcher3.settings"
            android:exported="true"
            android:writePermission="com.android.launcher3.permission.WRITE_SETTINGS"
            android:readPermission="com.android.launcher3.permission.READ_SETTINGS" />

    </application>
</manifest>


在Application的标签下,有两个activity和一个provider,它们分别是:Launcher、SettingsActivity和LauncherProvider;

Launcher即我们手机看到的桌面;
SettingsActivity是桌面的设置页面;
LauncherProvider是用来存储页面布局信息的。

二、桌面布局

1.布局

在这里插入图片描述

  • DragLayer是根布局,用来处理子View的拖动的布局;
  • Workspace是用来装载桌面上其它所有布局的控件;
  • SearchDropTargetBar是用来显示移除和卸载的控件;
  • CellLayout是用来显示应用和桌面小工具的,一个Workspace中可以显示多个CellLayout;
  • PageIndicator是用来指示当前为第几页的CellLayout;
  • Hotseat是常用应用显示控件。

2. Launcher界面配置文件

路径是:\Launcher\res\xml\default_workspace.xml 。

<appwidget    // 插件
launcher:className= "  " // 该应用的类
launcher:packageName= ""  // 该应用的包名
launcher:screen= " 1 "    // 第1屏,0-4屏共5屏
launcher:x= " 2 "       // 图标X位置,左上角第一个为0,向左递增,0-4共5个
launcher:y= " 1 "     // 图标Y位置,左上角第一个为0,向下递增,0-2共3个
launcher:spanX= "3 "   // 在x方向上所占格数
launcher:spanY= " 2 " />

3 Launcher.java的onCreate方法:

protected void onCreate(Bundle savedInstanceState) {
    ......
    //建立LauncherAppState对象
    LauncherAppState app = LauncherAppState.getInstance();
    ......
    //建立LauncherModel对象
    mModel = app.setLauncher(this);
    //一些其他对象初始化
    ......
    setContentView(R.layout.launcher);
    setupViews();
    if (!mRestoring) {
            if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
                // 如果用户离开启动器,那么我们应该在项目返回时异步加载它们。
                mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
            } else {
                // 只有当启动器在前台时,用户旋转(或触发配置更改),我们才会同步加载页面
                mModel.startLoader(mWorkspace.getRestorePage());
            }
    }
    ......
}

3.LauncherModel的startLoader的方法

startLoader里面,最重要的就是启动了LoaderTask

mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage);

4.LoaderTask的run方法

public void run() {
            ......
            keep_running: {
                // step 1: loading workspace
                loadAndBindWorkspace();
                if (mStopped) {
                    break keep_running;
                }
                waitForIdle();
                // step 2: loading all apps
                loadAndBindAllApps();
                waitForIdle();
                // step 3: loading deep shortcuts
                loadAndBindDeepShortcuts();
            }
            ......
        }

5.workspace的加载流程

workspace的加载流程主要分为loadWorkspace();和bindWorkspace(mPageToBindFirst);

5.1.loadWorkspace()

主要功能就是负责从数据库表中读取数据并转译为Launcher桌面项的数据结构。
1、进行一些预处理
2、加载默认值

LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary()
int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT, "xml", partner.getPackageName());

3、初始化数据,清空之前的内存数据

/** Clears all the sBg data structures */
        private void clearSBgDataStructures() {
            synchronized (sBgLock) {
                sBgWorkspaceItems.clear();
                sBgAppWidgets.clear();
                sBgFolders.clear();
                sBgItemsIdMap.clear();
                sBgWorkspaceScreens.clear();
            }
        }

4、查询ContentProvider,返回favorites表的结果集

final HashMap<String, Integer> installingPkgs = PackageInstallerCompat
                        .getInstance(mContext).updateAndGetActiveSessionCache();

                final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
                final ArrayList<Long> restoredRows = new ArrayList<Long>();
                final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
                if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
                final Cursor c = contentResolver.query(contentUri, null, null, null, null);

5、根据不同的类型,将数据保存到对应的arrayList中。
6、根据类型,将数据保存到一下全局变量里面
sBgItemsIdMap,sBgWorkspaceItemsm,sBgAppWidgets,sBgFolders
另外,如果有空的文件夹、空的屏幕,也会delete掉,最终,把所有屏幕加载进全局变量sBgWorkspaceScreens中。

5.2.bindWorkspace

将上面获取到的数据由Launcher显示出来。
1、首先复制数据:

            synchronized (sBgLock) {
                workspaceItems.addAll(sBgWorkspaceItems);
                appWidgets.addAll(sBgAppWidgets);
                orderedScreenIds.addAll(sBgWorkspaceScreens);

                folders = sBgFolders.clone();
                itemsIdMap = sBgItemsIdMap.clone();
            }

2、装载数据并排序

            //装载桌面项数据
            filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,
                    otherWorkspaceItems);
            //装载widget        
            filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets,
                    otherAppWidgets);
            //装载文件夹
            filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders,
                    otherFolders);
            //排序        
            sortWorkspaceItemsSpatially(currentWorkspaceItems);
            sortWorkspaceItemsSpatially(otherWorkspaceItems);

3、开始绑定

6

在这里插入图片描述

参考资料

https://blog.youkuaiyun.com/yangshuangyue/article/details/122320642
https://blog.youkuaiyun.com/Picasso_L/article/details/70140694?ops_request_misc=&request_id=&biz_id=102&utm_term=default_workspace%20%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-70140694.142v9control,157v4control&spm=1018.2226.3001.4187
(如有侵权,立即删除)

<think>嗯,用户想了解Excel中的VLOOKUP函数的用法和参数含义。首先,我需要回忆一下VLOOKUP的基本结构。VLOOKUP是垂直查找函数,用于在表格的首列查找指定的值,然后返回该行中指定列的数据。它的四个参数分别是查找值、表格范围、列索引号和匹配模式。 接下来,我得确认每个参数的具体作用。第一个参数是lookup_value,也就是用户要查找的值,比如产品ID或者姓名。第二个参数是table_array,即查找的范围,这里要注意的是,查找值必须位于这个范围的第一列,否则函数无法正确工作。第三个参数是col_index_num,也就是用户想要返回的数据在表格范围中的第几列,这个列数是从表格范围的第一列开始算起的,不是整个工作表的列。第四个参数是range_lookup,决定是精确匹配还是近似匹配,通常用FALSE或0来指定精确匹配,避免错误。 然后,用户可能需要一个具体的例子来理解如何使用。比如,假设有一个产品价格表,用户想根据产品ID查找对应的价格。这时候,VLOOKUP就可以在ID列查找,然后返回价格列的数据。同时,要提醒用户注意表格范围最好使用绝对引用,比如$A$2:$C$100,这样在拖动公式时范围不会变化。 可能遇到的问题也需要考虑。比如,如果查找值不在表格的第一列,或者列索引号超过了表格的列数,函数会返回错误。此外,数据格式不一致也可能导致问题,比如查找值是数字,而表格中是文本格式的数字,这时候需要统一格式。还有,当出现#N/A错误时,可能是查找值不存在,或者匹配模式设置不正确,需要检查参数是否正确。 用户可能还会问到如何避免常见的错误,比如部分数据匹配出错的情况。这时候需要检查是否有多余的空格,或者数据格式不一致,或者表格范围没有锁定导致拖动时偏移。此外,XLOOKUP作为VLOOKUP的升级版,可能在某些情况下更方便,比如可以向左查找或者返回多列数据,这也是可以提及的内容。 最后,整理步骤,从基础语法到参数说明,再到具体案例,逐步引导用户理解如何使用VLOOKUP函数。同时,提供常见错误和解决方法,帮助用户在实际应用中避免问题。如果有必要,还可以比较VLOOKUP和其他查找函数的区别,比如HLOOKUP或XLOOKUP,但根据用户的问题,主要集中在VLOOKUP本身即可。</think>### Excel VLOOKUP函数详解 #### 一、基础语法与参数说明 VLOOKUP函数的语法为: $$=VLOOKUP(lookup\_value, table\_array, col\_index\_num, [range\_lookup])$$ 包含4个参数: 1. **lookup_value**(必填):要查找的值(如单元格引用或具体值) 2. **table_array**(必填):包含数据的表格范围(必须包含查找列和返回列) 3. **col_index_num**(必填):返回值所在列的序号(从table_array第一列开始计数) 4. **range_lookup**(可选):匹配类型 - `TRUE`/`1`:近似匹配(默认值,需数据升序排列) - `FALSE`/`0`:精确匹配(常用选项) [^1][^2] #### 二、使用步骤演示(工资表查询案例) 假设需要根据员工编号查询工资: 1. 建立查询单元格(如`B12`) 2. 输入公式: ```excel =VLOOKUP(A12, $A$2:$D$100, 4, 0) ``` - `A12`:待查询的员工编号 - `$A$2:$D$100`:锁定数据区域(绝对引用) - `4`:返回第4列(工资列) - `0`:精确匹配 [^2][^3] #### 三、常见错误与解决方法 | 错误现象 | 原因 | 解决方案 | |---------|------|---------| | #N/A | 查找值不存在 | 检查数据源或改用`IFERROR`容错 | | #REF! | 列序号超出范围 | 确认col_index_num ≤ 表格列数 | | 部分匹配失败 | 数据格式不一致 | 统一数值/文本格式 | | 结果错位 | 表格未锁定 | 使用`$`符号固定区域引用 | [^3][^4] #### 四、进阶技巧 1. **多条件查询**: 使用辅助列合并多个条件字段 ```excel =VLOOKUP(A2&B2, $D$2:$F$100, 3, 0) ``` 2. **通配符匹配**: `"*"`匹配任意字符,`"?"`匹配单个字符 ```excel =VLOOKUP("张*", $A$2:$C$100, 3, 0) ``` 3. **跨表查询**: 引用其他工作表数据 ```excel =VLOOKUP(A2, Sheet2!$A$2:$D$100, 4, 0) ``` [^1][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值