Launcher布局加载流程

一、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.csdn.net/yangshuangyue/article/details/122320642
https://blog.csdn.net/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
(如有侵权,立即删除)

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值