Launcher3 workspace 加载默认的布局

本文主要分析launcher3 如何加载默认的icon ,基于AOSP Q Launcher3 code

1、 launcher首先会初始化设备配置属性,比如加载哪些图标,图标布局n * n等等,这些配置定义在device_profiles.xml 中,device_profiles.xml 会关联到default_workspace_n*n.xml,
2、 在LoaderTask.java 的loadworkspace函数中会去load默认的布局,其实就是去加载 1中初始化后的配置

1、InvariantDeviceProfile初始化

Launcher在oncreate的时候会通过单例初始化LauncherAppState类

LauncherAppState app = LauncherAppState.getInstance(this);

在LauncherAppState的构造中会初始化InvariantDeviceProfile,先看一下InvariantDeviceProfile构造函数,

  public InvariantDeviceProfile(Context context) {
		......
        // This guarantees that width < height
        minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), dm);
        minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y), dm);
        
        ArrayList<InvariantDeviceProfile> closestProfiles = findClosestDeviceProfiles(
                minWidthDps, minHeightDps, getPredefinedDeviceProfiles(context));
                
        InvariantDeviceProfile interpolatedDeviceProfileOut =
                invDistWeightedInterpolate(minWidthDps,  minHeightDps, closestProfiles);

        InvariantDeviceProfile closestProfile = closestProfiles.get(0);
        numRows = closestProfile.numRows;
        numColumns = closestProfile.numColumns;
        numHotseatIcons = closestProfile.numHotseatIcons;
        //这个布局就是后面load default favorites加载所需要的布局id
        defaultLayoutId = closestProfile.defaultLayoutId;
        Log.d("InvariantDeviceProfile", "InvariantDeviceProfile: defaultLayoutId: " + defaultLayoutId);
        demoModeLayoutId = closestProfile.demoModeLayoutId;
        numFolderRows = closestProfile.numFolderRows;
        numFolderColumns = closestProfile.numFolderColumns;
       ......

通过getPredefinedDeviceProfiles 去load device_profiles.xml中定义的所有profile,放到List中,然后通过findClosestDeviceProfiles从 list中找出最接近的profile。

    /**
     * Returns the closest device profiles ordered by closeness to the specified width and height
     */
    // Package private visibility for testing.
    ArrayList<InvariantDeviceProfile> findClosestDeviceProfiles(
            final float width, final float height, ArrayList<InvariantDeviceProfile> points) {

        // Sort the profiles by their closeness to the dimensions
        ArrayList<InvariantDeviceProfile> pointsByNearness = points;
        Collections.sort(pointsByNearness, new Comparator<InvariantDeviceProfile>() {
            public int compare(InvariantDeviceProfile a, InvariantDeviceProfile b) {
                return Float.compare(dist(width, height, a.minWidthDps, a.minHeightDps),
                        dist(width, height, b.minWidthDps, b.minHeightDps));
            }
        });
        return pointsByNearness;
    }

2、LoadWorkspace 加载默认的favorites

loadworkspace()是加载添加在workspace上的 shortcut、folder、widget,这里我们只看如何加载默认的图标。

        Log.d(TAG, "loadWorkspace: loading default favorites");
        LauncherSettings.Settings.call(contentResolver,
                LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES);

通过ContentResolver的call方法调用到LauncherProvider去实现,看一下launcherprovider call实现,


    @Override
    public Bundle call(String method, final String arg, final Bundle extras) {

        createDbIfNotExists();

        switch (method) {
             ......
            case LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES: {
                loadDefaultFavoritesIfNecessary();
                return null;
            }
            ......
         

loadDefaultFavoritesIfNecessary()这个流程就是找到之前已经初始化好的device profile,通过InvariantDeviceProfile中的defaultLayoutId找到对应的default_workspace_n*n.xml,然后解析加载是数据并插入到数据库中,可以看一下测试打印的调用栈

10-28 16:40:46.334 D/LauncherProvider(32452): com.android.launcher3.LauncherProvider$DatabaseHelper.insertAndCheck(LauncherProvider.java:1020)
10-28 16:40:46.334 D/LauncherProvider(32452): com.android.launcher3.AutoInstallsLayout.addShortcut(AutoInstallsLayout.java:304)
10-28 16:40:46.334 D/LauncherProvider(32452): com.android.launcher3.DefaultLayoutParser$AppShortcutWithUriParser.invalidPackageOrClass(DefaultLayoutParser.java:136)
10-28 16:40:46.334 D/LauncherProvider(32452): com.android.launcher3.AutoInstallsLayout$AppShortcutParser.parseAndAdd(AutoInstallsLayout.java:374)
10-28 16:40:46.334 D/LauncherProvider(32452): com.android.launcher3.DefaultLayoutParser$AppShortcutWithUriParser.parseAndAdd(DefaultLayoutParser.java:91)
10-28 16:40:46.334 D/LauncherProvider(32452):  com.android.launcher3.DefaultLayoutParser$ResolveParser.parseAndAdd(DefaultLayoutParser.java:220)
10-28 16:40:46.334 D/LauncherProvider(32452): com.android.launcher3.AutoInstallsLayout.parseAndAddNode(AutoInstallsLayout.java:284)
10-28 16:40:46.334 D/LauncherProvider(32452): com.android.launcher3.AutoInstallsLayout.parseLayout(AutoInstallsLayout.java:225)
10-28 16:40:46.334 D/LauncherProvider(32452): com.android.launcher3.AutoInstallsLayout.loadLayout(AutoInstallsLayout.java:201)
10-28 16:40:46.335 D/LauncherProvider(32452):  com.android.launcher3.LauncherProvider$DatabaseHelper.loadFavorites(LauncherProvider.java:1060)
10-28 16:40:46.335 D/LauncherProvider(32452): com.android.launcher3.LauncherProvider.loadDefaultFavoritesIfNecessary(LauncherProvider.java:492)
10-28 16:40:46.335 D/LauncherProvider(32452): com.android.launcher3.LauncherProvider.call(LauncherProvider.java:392)
10-28 16:40:46.335 D/LauncherProvider(32452):  android.content.ContentProvider$Transport.call(ContentProvider.java:401)
10-28 16:40:46.335 D/LauncherProvider(32452): android.content.ContentResolver.call(ContentResolver.java:1756)
10-28 16:40:46.335 D/LauncherProvider(32452): com.android.launcher3.LauncherSettings$Settings.call(LauncherSettings.java:312)
10-28 16:40:46.335 D/LauncherProvider(32452):  com.android.launcher3.model.LoaderTask.loadWorkspace(LoaderTask.java:263)
10-28 16:40:46.335 D/LauncherProvider(32452): com.android.launcher3.model.LoaderTask.run(LoaderTask.java:168)

另外,loadDefaultFavoritesIfNecessary() 通过判断if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) 是否要加载默认的workspace,一般情况下,只会加载一次,除非删除launcher.db数据库,EMPTY_DATABASE_CREATED这个key在db创建的时候会设为true,一旦加载default workspace完成,则会remove EMPTY_DATABASE_CREATED key。


版权声明:本文为wng2010原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。