Launcher3源码分析 — 加载Workspace的数据

Launcher3的数据加载过程涉及到了两个主要的类LauncherProvider和LauncherModel。

LauncherProvider


LauncherProvider继承自ContentProvider类,内部基于数据库存储实现了ContentProvider的CRUD接口,这个类主要用于更新数据库的数据。LauncherProvider内部维护了两张数据表,favorites(用于存储workspace上的内容信息)和workspaceScreens(用于存储screen的排序和页数的信息)。


favorites表的创建语句:

db.execSQL("CREATE TABLE favorites (" +
                    "_id INTEGER PRIMARY KEY," +                          // id
                    "title TEXT," +                                       // 名字
                    "intent TEXT," +                                      // intent的字符串描述
                    "container INTEGER," +                                // 容器类型,desktop或者hotseat
                    "screen INTEGER," +                                   // 所在的屏幕号  
                    "cellX INTEGER," +                                    // item左上方所在的格子x位置
                    "cellY INTEGER," +                                    // item左上方所在的格子y位置
                    "spanX INTEGER," +                                    // item横向占用的格子数
                    "spanY INTEGER," +                                    // item纵向占用的格子数
                    "itemType INTEGER," +                                 // item的类型,app,widget,folder
                    "appWidgetId INTEGER NOT NULL DEFAULT -1," +          // widget的id
                    "isShortcut INTEGER," +                               // 是否是快捷方式
                    "iconType INTEGER," +                                 ...
                    "iconPackage TEXT," +
                    "iconResource TEXT," +
                    "icon BLOB," +
                    "uri TEXT," +
                    "displayMode INTEGER," +
                    "appWidgetProvider TEXT," +
                    "modified INTEGER NOT NULL DEFAULT 0" +
                    ");");
favorites用于存储workspace上的内容信息,它存储了内容的类型和所在的位置等信息。


workspaceScreens表的创建语句:

            db.execSQL("CREATE TABLE " + TABLE_WORKSPACE_SCREENS + " (" +
                    LauncherSettings.WorkspaceScreens._ID + " INTEGER," +
                    LauncherSettings.WorkspaceScreens.SCREEN_RANK + " INTEGER," +
                    LauncherSettings.ChangeLogColumns.MODIFIED + " INTEGER NOT NULL DEFAULT 0" +
                    ");");

LauncherModel

当从数据库获取了数据后,需要一个数据对象在内存中维护这些信息。Launcher3中定义了一系列的数据类,如下图所示:


AppInfo:代表所有应用界面的一个app

FolderInfo:代表一个文件夹

LauncherAppWidgetInfo:代表一个widget

ShortcutInfo:代表workspace和folder里的app


    LauncherModel用于维护内存中的数据,通过ContentResolver来更新LauncherProvider的数据,即数据库的数据。LauncherModel内部有个继承自Runnable的LoaderTask引用,Launcher的数据加载就是在这个类中执行,当调用LauncherModel.startLoader()时就会执行LoaderTask.run()方法,开始数据的加载工作。

    LauncherModel内部维护了几个列表,用于存储从数据库获取的数据:

    // sBgItemsIdMap存储了所有的ItemInfos (shortcuts, folders, and widgets),以item的id作为key
    static final HashMap<Long, ItemInfo> sBgItemsIdMap = new HashMap<Long, ItemInfo>();
    // sBgWorkspaceItems将作为参数传递给bindItems, 存储了在workspace上显示的所有app和folder信息
    static final ArrayList<ItemInfo> sBgWorkspaceItems = new ArrayList<ItemInfo>();
    // sBgAppWidgets存储了workspace上的widget信息,作为参数传递给bindAppWidget()
    static final ArrayList<LauncherAppWidgetInfo> sBgAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
    // sBgFolders存储了workspace上的folder信息,作为参数传递给bindFolders()
    static final HashMap<Long, FolderInfo> sBgFolders = new HashMap<Long, FolderInfo>();
    // sBgDbIconCache存储了在数据库维护的item的图片
    static final HashMap<Object, byte[]> sBgDbIconCache = new HashMap<Object, byte[]>();
    // sBgWorkspaceScreens按顺序存储了workspace上的屏幕
    static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();

LauncherModel的结构图:



Workspace数据的加载过程

Launcher3的数据加载分为两部分,一个是Workspace页面的数据:Launcher最主要的界面,用户可自由编辑内容(widget,app, folder,screen),第二部分是所有应用界面。下面我们先来看Workspace的数据加载过程,通过在LoaderTask.run()方法里调用loadAndBindWorkspace()开始整个过程,下面是具体代码:

        /** Returns whether this is an upgrade path */
        private boolean loadAndBindWorkspace() {
            mIsLoadingAndBindingWorkspace = true;

            boolean isUpgradePath = false;
            if (!mWorkspaceLoaded) {
                // Load the workspace
                isUpgradePath = loadWorkspace();
                synchronized (LoaderTask.this) {
                    if (mStopped) {
                        return isUpgradePath;
                    }
                    mWorkspaceLoaded = true;
                }
            }

            // Bind the workspace
            bindWorkspace(-1, isUpgradePath);
            return isUpgradePath;
        }
    整个过程分为两步,load和bind,完成第一步后会判断任务是否终止,如果是则不继续下一步。代码中用到了synchronized块,因为这个过程涉及到多线程处理。我们先看loadWorkspace(),也就是workspace的数据加载过程,以下是大体流程:


1. 如果数据库为空,先加载xml的数据

加载时,首先会判断数据库的类容是否为空,如果是,会先从一个xml文件中加载workspace的类容,Launcher3的默认xml文件路径为res/xml/default_workspace.xml,里面定义了默认的app和widget信息,这个过程由loadFavorates()实现。


默认xml的内容如下:

<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
    <!-- Far-left screen [0] -->

    <!-- Left screen [1] -->
    <appwidget
        launcher:packageName="com.android.settings"
        launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"
        launcher:screen="1"
        launcher:x="0"
        launcher:y="3"
        launcher:spanX="4"
        launcher:spanY="1" />

    <!-- Right screen [3] -->
    <favorite
        launcher:packa
  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值