• launcher5.0-资源加载


    桌面启动

    执行LauncherApplication.java ----onCreate()方法

    @Override
        public void onCreate() {
            super.onCreate();
    
            // set sIsScreenXLarge and sScreenDensity *before* creating icon cache
            sIsScreenLarge = getResources().getBoolean(R.bool.is_large_screen);
            sScreenDensity = getResources().getDisplayMetrics().density;
    
            recreateWidgetPreviewDb();
            mIconCache = new IconCache(this);
            mModel = new LauncherModel(this, mIconCache);
            LauncherApps launcherApps = (LauncherApps)
                    getSystemService(Context.LAUNCHER_APPS_SERVICE);
            launcherApps.registerCallback(mModel.getLauncherAppsCallback());
    
            // Register intent receivers
            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_LOCALE_CHANGED);
            filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
            registerReceiver(mModel, filter);
            filter = new IntentFilter();
            filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
            registerReceiver(mModel, filter);
            filter = new IntentFilter();
            filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
            registerReceiver(mModel, filter);
    
            // Register for changes to the favorites
            ContentResolver resolver = getContentResolver();
            resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,
                    mFavoritesObserver);
        }

    注册 favorites observer

        /**
         * Receives notifications whenever the user favorites have changed.
         */
        private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
            @Override
            public void onChange(boolean selfChange) {
                // If the database has ever changed, then we really need to force a reload of the
                // workspace on the next load
                mModel.resetLoadedState(false, true);
                mModel.startLoaderFromBackground();
            }
        };

    执行 mModel.startLoaderFromBackground();

        /**
         * When the launcher is in the background, it's possible for it to miss paired
         * configuration changes.  So whenever we trigger the loader from the background
         * tell the launcher that it needs to re-run the loader when it comes back instead
         * of doing it now.
         */
        public void startLoaderFromBackground() {
            boolean runLoader = false;
            if (mCallbacks != null) {
                Callbacks callbacks = mCallbacks.get();
                if (callbacks != null) {
                    // Only actually run the loader if they're not paused.
                    if (!callbacks.setLoadOnResume()) {
                        runLoader = true;
                    }
                }
            }
            if (runLoader) {
                startLoader(false, -1);
            }
        }

    执行 startLoader(false, -1);

    public void startLoader(boolean isLaunching, int synchronousBindPage) {
            synchronized (mLock) {
                if (DEBUG_LOADERS) {
                    Log.d(TAG, "startLoader isLaunching=" + isLaunching);
                }
    
                // Clear any deferred bind-runnables from the synchronized load process
                // We must do this before any loading/binding is scheduled below.
                mDeferredBindRunnables.clear();
    
                // Don't bother to start the thread if we know it's not going to do anything
                if (mCallbacks != null && mCallbacks.get() != null) {
                    // If there is already one running, tell it to stop.
                    // also, don't downgrade isLaunching if we're already running
                    isLaunching = isLaunching || stopLoaderLocked();
                    mLoaderTask = new LoaderTask(mApp, isLaunching);
                    if (synchronousBindPage > -1 && mAllAppsLoaded && mWorkspaceLoaded) {
                        mLoaderTask.runBindSynchronousPage(synchronousBindPage);
                    } else {
                        sWorkerThread.setPriority(Thread.NORM_PRIORITY);
                        sWorker.post(mLoaderTask);
                    }
                }
            }
        }

    如上加载资源执行mLoaderTask ,mLoaderTask implements Runnable 方法 看下mLoaderTask run

       public void run() {
                synchronized (mLock) {
                    mIsLoaderTaskRunning = true;
                }
    
                keep_running: {
                    // Elevate priority when Home launches for the first time to avoid
                    // starving at boot time. Staring at a blank home is not cool.
                    synchronized (mLock) {
                        if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +
                                (mIsLaunching ? "DEFAULT" : "BACKGROUND"));
                        Process.setThreadPriority(mIsLaunching
                                ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
                    }
    
                    // First step. Load workspace first, this is necessary since adding of apps from
                    // managed profile in all apps is deferred until onResume. See http://b/17336902.
                    if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
                    loadAndBindWorkspace();
    
                    if (mStopped) {
                        break keep_running;
                    }
    
                    // Whew! Hard work done.  Slow us down, and wait until the UI thread has
                    // settled down.
                    synchronized (mLock) {
                        if (mIsLaunching) {
                            if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to BACKGROUND");
                            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        }
                    }
                    waitForIdle();
    
                    // Second step. Load all apps.
                    if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
                    loadAndBindAllApps();
    
                    // Restore the default thread priority after we are done loading items
                    synchronized (mLock) {
                        Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                    }
                }
    
    
                // Update the saved icons if necessary
                if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");
                synchronized (sBgLock) {
                    for (Object key : sBgDbIconCache.keySet()) {
                        updateSavedIcon(mContext, (ShortcutInfo) key, sBgDbIconCache.get(key));
                    }
                    sBgDbIconCache.clear();
                }
    
                // Clear out this reference, otherwise we end up holding it until all of the
                // callback runnables are done.
                mContext = null;
    
                synchronized (mLock) {
                    // If we are still the last one to be scheduled, remove ourselves.
                    if (mLoaderTask == this) {
                        mLoaderTask = null;
                    }
                    mIsLoaderTaskRunning = false;
                }
            }

        loadAndBindWorkspace()方法是加载和绑定桌面资源 (从资源文件和旧偏好)

      loadAndBindAllApps()桌面绑定app信息

     private void loadAndBindWorkspace() {
                mIsLoadingAndBindingWorkspace = true;
    
                // Load the workspace
                if (DEBUG_LOADERS) {
                    Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
                }
    
                if (!mWorkspaceLoaded) {
                    loadWorkspace();
                    synchronized (LoaderTask.this) {
                        if (mStopped) {
                            return;
                        }
                        mWorkspaceLoaded = true;
                    }
                }
    
                // Bind the workspace
                bindWorkspace(-1);
            }
    

      

    loadWorkspace()加载桌面资源
    bindWorkspace()绑定资源到桌面

      private void loadWorkspace() {
                final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
    
                final Context context = mContext;
                final ContentResolver contentResolver = context.getContentResolver();
                final PackageManager manager = context.getPackageManager();
                final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
                final boolean isSafeMode = manager.isSafeMode();
    
                // Make sure the default workspace is loaded, if needed
                mApp.getLauncherProvider().loadDefaultFavoritesIfNecessary(0, false);
    
                synchronized (sBgLock) {
                    sBgWorkspaceItems.clear();
                    sBgAppWidgets.clear();
                    sBgFolders.clear();
                    sBgItemsIdMap.clear();
                    sBgDbIconCache.clear();
    
                    final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
    
                    final Cursor c = contentResolver.query(
                            LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
    
                    // +1 for the hotseat (it can be larger than the workspace)
                    // Load workspace in reverse order to ensure that latest items are loaded first (and
                    // before any earlier duplicates)
                    final ItemInfo occupied[][][] =
                            new ItemInfo[Launcher.SCREEN_COUNT + 1][mCellCountX + 1][mCellCountY + 1];
    
                    try {
                        final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
                        final int intentIndex = c.getColumnIndexOrThrow
                                (LauncherSettings.Favorites.INTENT);
                        final int titleIndex = c.getColumnIndexOrThrow
                                (LauncherSettings.Favorites.TITLE);
                        final int iconTypeIndex = c.getColumnIndexOrThrow(
                                LauncherSettings.Favorites.ICON_TYPE);
                        final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
                        final int iconPackageIndex = c.getColumnIndexOrThrow(
                                LauncherSettings.Favorites.ICON_PACKAGE);
                        final int iconResourceIndex = c.getColumnIndexOrThrow(
                                LauncherSettings.Favorites.ICON_RESOURCE);
                        final int containerIndex = c.getColumnIndexOrThrow(
                                LauncherSettings.Favorites.CONTAINER);
                        final int itemTypeIndex = c.getColumnIndexOrThrow(
                                LauncherSettings.Favorites.ITEM_TYPE);
                        final int appWidgetIdIndex = c.getColumnIndexOrThrow(
                                LauncherSettings.Favorites.APPWIDGET_ID);
                        final int screenIndex = c.getColumnIndexOrThrow(
                                LauncherSettings.Favorites.SCREEN);
                        final int cellXIndex = c.getColumnIndexOrThrow
                                (LauncherSettings.Favorites.CELLX);
                        final int cellYIndex = c.getColumnIndexOrThrow
                                (LauncherSettings.Favorites.CELLY);
                        final int spanXIndex = c.getColumnIndexOrThrow
                                (LauncherSettings.Favorites.SPANX);
                        final int spanYIndex = c.getColumnIndexOrThrow(
                                LauncherSettings.Favorites.SPANY);
                        final int profileIdIndex = c.getColumnIndexOrThrow(
                                LauncherSettings.Favorites.PROFILE_ID);
                        //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
                        //final int displayModeIndex = c.getColumnIndexOrThrow(
                        //        LauncherSettings.Favorites.DISPLAY_MODE);
    
                        ShortcutInfo info;
                        String intentDescription;
                        LauncherAppWidgetInfo appWidgetInfo;
                        int container;
                        long id;
                        Intent intent;
                        UserHandle user;
    
                        while (!mStopped && c.moveToNext()) {
                            try {
                                int itemType = c.getInt(itemTypeIndex);
    
                                switch (itemType) {
                                case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                                    intentDescription = c.getString(intentIndex);
                                    int serialNumber = c.getInt(profileIdIndex);
                                    user = mUserManager.getUserForSerialNumber(serialNumber);
                                    // If the user doesn't exist anymore, skip.
                                    if (user == null) {
                                        itemsToRemove.add(c.getLong(idIndex));
                                        continue;
                                    }
                                    try {
                                        intent = Intent.parseUri(intentDescription, 0);
                                    } catch (URISyntaxException e) {
                                        continue;
                                    }
    
                                    if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                                            info = getShortcutInfo(
                                                    manager, intent, user, context, c, iconIndex,
                                                titleIndex, mLabelCache);
                                    } else {
                                        info = getShortcutInfo(c, context, iconTypeIndex,
                                                iconPackageIndex, iconResourceIndex, iconIndex,
                                                titleIndex);
    
                                        // App shortcuts that used to be automatically added to Launcher
                                        // didn't always have the correct intent flags set, so do that
                                        // here
                                        if (intent.getAction() != null &&
                                            intent.getCategories() != null &&
                                            intent.getAction().equals(Intent.ACTION_MAIN) &&
                                            intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
                                            intent.addFlags(
                                                Intent.FLAG_ACTIVITY_NEW_TASK |
                                                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                                        }
                                    }
    
                                    if (info != null) {
                                        info.intent = intent;
                                        info.id = c.getLong(idIndex);
                                        container = c.getInt(containerIndex);
                                        info.container = container;
                                        info.screen = c.getInt(screenIndex);
                                        info.cellX = c.getInt(cellXIndex);
                                        info.cellY = c.getInt(cellYIndex);
                                        info.intent.putExtra(ItemInfo.EXTRA_PROFILE, info.user);
    
                                        // check & update map of what's occupied
                                        if (!checkItemPlacement(occupied, info)) {
                                            break;
                                        }
    
                                        switch (container) {
                                        case LauncherSettings.Favorites.CONTAINER_DESKTOP:
                                        case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
                                            sBgWorkspaceItems.add(info);
                                            break;
                                        default:
                                            // Item is in a user folder
                                            FolderInfo folderInfo =
                                                    findOrMakeFolder(sBgFolders, container);
                                            folderInfo.add(info);
                                            break;
                                        }
                                        sBgItemsIdMap.put(info.id, info);
    
                                        // now that we've loaded everthing re-save it with the
                                        // icon in case it disappears somehow.
                                        queueIconToBeChecked(sBgDbIconCache, info, c, iconIndex);
                                    } else {
                                        // Failed to load the shortcut, probably because the
                                        // activity manager couldn't resolve it (maybe the app
                                        // was uninstalled), or the db row was somehow screwed up.
                                        // Delete it.
                                        id = c.getLong(idIndex);
                                        Log.e(TAG, "Error loading shortcut " + id + ", removing it");
                                        contentResolver.delete(LauncherSettings.Favorites.getContentUri(
                                                    id, false), null, null);
                                    }
                                    break;
    
                                case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                                    id = c.getLong(idIndex);
                                    FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);
    
                                    folderInfo.title = c.getString(titleIndex);
                                    folderInfo.id = id;
                                    container = c.getInt(containerIndex);
                                    folderInfo.container = container;
                                    folderInfo.screen = c.getInt(screenIndex);
                                    folderInfo.cellX = c.getInt(cellXIndex);
                                    folderInfo.cellY = c.getInt(cellYIndex);
    
                                    // check & update map of what's occupied
                                    if (!checkItemPlacement(occupied, folderInfo)) {
                                        break;
                                    }
                                    switch (container) {
                                        case LauncherSettings.Favorites.CONTAINER_DESKTOP:
                                        case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
                                            sBgWorkspaceItems.add(folderInfo);
                                            break;
                                    }
    
                                    sBgItemsIdMap.put(folderInfo.id, folderInfo);
                                    sBgFolders.put(folderInfo.id, folderInfo);
                                    break;
    
                                case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
                                    // Read all Launcher-specific widget details
                                    int appWidgetId = c.getInt(appWidgetIdIndex);
                                    id = c.getLong(idIndex);
    
                                    final AppWidgetProviderInfo provider =
                                            widgets.getAppWidgetInfo(appWidgetId);
    
                                    if (!isSafeMode && (provider == null || provider.provider == null ||
                                            provider.provider.getPackageName() == null)) {
                                        String log = "Deleting widget that isn't installed anymore: id="
                                            + id + " appWidgetId=" + appWidgetId;
                                        Log.e(TAG, log);
                                        Launcher.sDumpLogs.add(log);
                                        itemsToRemove.add(id);
                                    } else {
                                        appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
                                                provider.provider);
                                        appWidgetInfo.id = id;
                                        appWidgetInfo.screen = c.getInt(screenIndex);
                                        appWidgetInfo.cellX = c.getInt(cellXIndex);
                                        appWidgetInfo.cellY = c.getInt(cellYIndex);
                                        appWidgetInfo.spanX = c.getInt(spanXIndex);
                                        appWidgetInfo.spanY = c.getInt(spanYIndex);
                                        int[] minSpan = Launcher.getMinSpanForWidget(context, provider);
                                        appWidgetInfo.minSpanX = minSpan[0];
                                        appWidgetInfo.minSpanY = minSpan[1];
    
                                        container = c.getInt(containerIndex);
                                        if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
                                            container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
                                            Log.e(TAG, "Widget found where container != " +
                                                "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
                                            continue;
                                        }
                                        appWidgetInfo.container = c.getInt(containerIndex);
    
                                        // check & update map of what's occupied
                                        if (!checkItemPlacement(occupied, appWidgetInfo)) {
                                            break;
                                        }
                                        sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);
                                        sBgAppWidgets.add(appWidgetInfo);
                                    }
                                    break;
                                }
                            } catch (Exception e) {
                                Log.w(TAG, "Desktop items loading interrupted:", e);
                            }
                        }
                    } finally {
                        c.close();
                    }
    
                    if (itemsToRemove.size() > 0) {
                        ContentProviderClient client = contentResolver.acquireContentProviderClient(
                                        LauncherSettings.Favorites.CONTENT_URI);
                        // Remove dead items
                        for (long id : itemsToRemove) {
                            if (DEBUG_LOADERS) {
                                Log.d(TAG, "Removed id = " + id);
                            }
                            // Don't notify content observers
                            try {
                                client.delete(LauncherSettings.Favorites.getContentUri(id, false),
                                        null, null);
                            } catch (RemoteException e) {
                                Log.w(TAG, "Could not remove id = " + id);
                            }
                        }
                    }
    
                    if (DEBUG_LOADERS) {
                        Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
                        Log.d(TAG, "workspace layout: ");
                        for (int y = 0; y < mCellCountY; y++) {
                            String line = "";
                            for (int s = 0; s < Launcher.SCREEN_COUNT; s++) {
                                if (s > 0) {
                                    line += " | ";
                                }
                                for (int x = 0; x < mCellCountX; x++) {
                                    line += ((occupied[s][x][y] != null) ? "#" : ".");
                                }
                            }
                            Log.d(TAG, "[ " + line + " ]");
                        }
                    }
                }
            }
    mApp.getLauncherProvider().loadDefaultFavoritesIfNecessary(0, false); 从资源default_workspace.xml中读取默认的偏好到默认favorite数据库中,即初始化favorite,然后获取数据库信息解析分类加载到内存
    看下初始化favorite
     private int loadFavorites(SQLiteDatabase db, int workspaceResourceId) {
                Intent intent = new Intent(Intent.ACTION_MAIN, null);
                intent.addCategory(Intent.CATEGORY_LAUNCHER);
                ContentValues values = new ContentValues();
    
                PackageManager packageManager = mContext.getPackageManager();
                int allAppsButtonRank =
                        mContext.getResources().getInteger(R.integer.hotseat_all_apps_index);
                int i = 0;
                try {
                    XmlResourceParser parser = mContext.getResources().getXml(workspaceResourceId);
                    AttributeSet attrs = Xml.asAttributeSet(parser);
                    beginDocument(parser, TAG_FAVORITES);
    
                    final int depth = parser.getDepth();
    
                    int type;
                    while (((type = parser.next()) != XmlPullParser.END_TAG ||
                            parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
    
                        if (type != XmlPullParser.START_TAG) {
                            continue;
                        }
    
                        boolean added = false;
                        final String name = parser.getName();
    
                        TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Favorite);
    
                        long container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
                        if (a.hasValue(R.styleable.Favorite_container)) {
                            container = Long.valueOf(a.getString(R.styleable.Favorite_container));
                        }
    
                        String screen = a.getString(R.styleable.Favorite_screen);
                        String x = a.getString(R.styleable.Favorite_x);
                        String y = a.getString(R.styleable.Favorite_y);
    
                        // If we are adding to the hotseat, the screen is used as the position in the
                        // hotseat. This screen can't be at position 0 because AllApps is in the
                        // zeroth position.
                        if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
                                && Integer.valueOf(screen) == allAppsButtonRank) {
                            throw new RuntimeException("Invalid screen position for hotseat item");
                        }
    
                        values.clear();
                        values.put(LauncherSettings.Favorites.CONTAINER, container);
                        values.put(LauncherSettings.Favorites.SCREEN, screen);
                        values.put(LauncherSettings.Favorites.CELLX, x);
                        values.put(LauncherSettings.Favorites.CELLY, y);
    
                        if (TAG_FAVORITE.equals(name)) {
                            long id = addAppShortcut(db, values, a, packageManager, intent);
                            added = id >= 0;
                        } else if (TAG_SEARCH.equals(name)) {
                            added = addSearchWidget(db, values);
                        } else if (TAG_CLOCK.equals(name)) {
                            added = addClockWidget(db, values);
                        } else if (TAG_APPWIDGET.equals(name)) {
                            added = addAppWidget(parser, attrs, type, db, values, a, packageManager);
                        } else if (TAG_SHORTCUT.equals(name)) {
                            long id = addUriShortcut(db, values, a);
                            added = id >= 0;
                        } else if (TAG_FOLDER.equals(name)) {
                            String title;
                            int titleResId =  a.getResourceId(R.styleable.Favorite_title, -1);
                            if (titleResId != -1) {
                                title = mContext.getResources().getString(titleResId);
                            } else {
                                title = mContext.getResources().getString(R.string.folder_name);
                            }
                            values.put(LauncherSettings.Favorites.TITLE, title);
                            long folderId = addFolder(db, values);
                            added = folderId >= 0;
    
                            ArrayList<Long> folderItems = new ArrayList<Long>();
    
                            int folderDepth = parser.getDepth();
                            while ((type = parser.next()) != XmlPullParser.END_TAG ||
                                    parser.getDepth() > folderDepth) {
                                if (type != XmlPullParser.START_TAG) {
                                    continue;
                                }
                                final String folder_item_name = parser.getName();
    
                                TypedArray ar = mContext.obtainStyledAttributes(attrs,
                                        R.styleable.Favorite);
                                values.clear();
                                values.put(LauncherSettings.Favorites.CONTAINER, folderId);
    
                                if (TAG_FAVORITE.equals(folder_item_name) && folderId >= 0) {
                                    long id =
                                        addAppShortcut(db, values, ar, packageManager, intent);
                                    if (id >= 0) {
                                        folderItems.add(id);
                                    }
                                } else if (TAG_SHORTCUT.equals(folder_item_name) && folderId >= 0) {
                                    long id = addUriShortcut(db, values, ar);
                                    if (id >= 0) {
                                        folderItems.add(id);
                                    }
                                } else {
                                    throw new RuntimeException("Folders can " +
                                            "contain only shortcuts");
                                }
                                ar.recycle();
                            }
                            // We can only have folders with >= 2 items, so we need to remove the
                            // folder and clean up if less than 2 items were included, or some
                            // failed to add, and less than 2 were actually added
                            if (folderItems.size() < 2 && folderId >= 0) {
                                // We just delete the folder and any items that made it
                                deleteId(db, folderId);
                                if (folderItems.size() > 0) {
                                    deleteId(db, folderItems.get(0));
                                }
                                added = false;
                            }
                        }
                        if (added) i++;
                        a.recycle();
                    }
                } catch (XmlPullParserException e) {
                    Log.w(TAG, "Got exception parsing favorites.", e);
                } catch (IOException e) {
                    Log.w(TAG, "Got exception parsing favorites.", e);
                } catch (RuntimeException e) {
                    Log.w(TAG, "Got exception parsing favorites.", e);
                }
    
                return i;
            }

    需要解析default_workspace.xml内容如下:

    <favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher5">
        <!-- 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" />
    
        <!-- Middle screen [2] -->
        <appwidget
            launcher:packageName="com.android.deskclock"
            launcher:className="com.android.alarmclock.AnalogAppWidgetProvider"
            launcher:screen="2"
            launcher:x="1"
            launcher:y="0"
            launcher:spanX="2"
            launcher:spanY="2" />
        <favorite
            launcher:packageName="com.android.camera2"
            launcher:className="com.android.camera.CameraLauncher"
            launcher:screen="2"
            launcher:x="0"
            launcher:y="3" />
    
        <!-- Right screen [3] -->
        <favorite
            launcher:packageName="com.android.gallery3d"
            launcher:className="com.android.gallery3d.app.Gallery"
            launcher:screen="3"
            launcher:x="1"
            launcher:y="3" />
        <favorite
            launcher:packageName="com.android.settings"
            launcher:className="com.android.settings.Settings"
            launcher:screen="3"
            launcher:x="2"
            launcher:y="3" />
    
        <!-- Far-right screen [4] -->
    
        <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
        <favorite
            launcher:packageName="com.android.dialer"
            launcher:className="com.android.dialer.DialtactsActivity"
            launcher:container="-101"
            launcher:screen="0"
            launcher:x="0"
            launcher:y="0" />
        <favorite
            launcher:packageName="com.android.contacts"
            launcher:className="com.android.contacts.activities.PeopleActivity"
            launcher:container="-101"
            launcher:screen="1"
            launcher:x="1"
            launcher:y="0" />
        <favorite
            launcher:packageName="com.android.mms"
            launcher:className="com.android.mms.ui.ConversationList"
            launcher:container="-101"
            launcher:screen="3"
            launcher:x="3"
            launcher:y="0" />
        <favorite
            launcher:packageName="com.android.browser"
            launcher:className="com.android.browser.BrowserActivity"
            launcher:container="-101"
            launcher:screen="4"
            launcher:x="4"
            launcher:y="0" />
    </favorites>

    解析:

     <appwidget // widget
            launcher:packageName="com.android.settings" // pkg
            launcher:className="com.android.settings.widget.SettingsAppWidgetProvider" // 启动actName
            launcher:screen="1" //第几屏
            launcher:x="0" //行
            launcher:y="3" //列
            launcher:spanX="4" //x占格
            launcher:spanY="1" /> // y占格
     <favorite // 快捷方式
            launcher:packageName="com.android.browser"
            launcher:className="com.android.browser.BrowserActivity"
            launcher:container="-101"//底部快捷方式
            launcher:screen="4"
            launcher:x="4"
            launcher:y="0" />
    //除了appwidget favorite 还有如下

         private static final String TAG_FAVORITES = "favorites"; private static final String TAG_FAVORITE = "favorite"; private static final String TAG_CLOCK = "clock"; private static final String TAG_SEARCH = "search"; private static final String TAG_APPWIDGET = "appwidget"; private static final String TAG_SHORTCUT = "shortcut"; private static final String TAG_FOLDER = "folder"; private static final String TAG_EXTRA = "extra";

    到此loadWorkspace()资源加载完。

    workspace信息加载后分布如下几个集合中:

      sBgItemsIdmap:   map<id,iteminfo>  所有元素 包括 桌面快捷方式,底部栏快捷方式,文件夹,小控件

      sBgWorkspaceItems:   List  括 桌面快捷方式,底部栏快捷方式,

      sBgAppWidgets:  List  小控件

      sBgFolders:  hashmap<folderId,folderItem>  文件夹

     接下来研究绑定

     /**
             * Binds all loaded data to actual views on the main thread.
             */
            private void bindWorkspace(int synchronizeBindPage) {
                final long t = SystemClock.uptimeMillis();
                Runnable r;
    
                // Don't use these two variables in any of the callback runnables.
                // Otherwise we hold a reference to them.
                final Callbacks oldCallbacks = mCallbacks.get();
                if (oldCallbacks == null) {
                    // This launcher has exited and nobody bothered to tell us.  Just bail.
                    Log.w(TAG, "LoaderTask running with no launcher");
                    return;
                }
    
                final boolean isLoadingSynchronously = (synchronizeBindPage > -1);
                final int currentScreen = isLoadingSynchronously ? synchronizeBindPage :
                    oldCallbacks.getCurrentWorkspaceScreen();
    
                // Load all the items that are on the current page first (and in the process, unbind
                // all the existing workspace items before we call startBinding() below.
                unbindWorkspaceItemsOnMainThread();
                ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();
                ArrayList<LauncherAppWidgetInfo> appWidgets =
                        new ArrayList<LauncherAppWidgetInfo>();
                HashMap<Long, FolderInfo> folders = new HashMap<Long, FolderInfo>();
                HashMap<Long, ItemInfo> itemsIdMap = new HashMap<Long, ItemInfo>();
                synchronized (sBgLock) {
                    workspaceItems.addAll(sBgWorkspaceItems);
                    appWidgets.addAll(sBgAppWidgets);
                    folders.putAll(sBgFolders);
                    itemsIdMap.putAll(sBgItemsIdMap);
                }
    
                ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();
                ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();
                ArrayList<LauncherAppWidgetInfo> currentAppWidgets =
                        new ArrayList<LauncherAppWidgetInfo>();
                ArrayList<LauncherAppWidgetInfo> otherAppWidgets =
                        new ArrayList<LauncherAppWidgetInfo>();
                HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();
                HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();
    
                // Separate the items that are on the current screen, and all the other remaining items
                filterCurrentWorkspaceItems(currentScreen, workspaceItems, currentWorkspaceItems,
                        otherWorkspaceItems);
                filterCurrentAppWidgets(currentScreen, appWidgets, currentAppWidgets,
                        otherAppWidgets);
                filterCurrentFolders(currentScreen, itemsIdMap, folders, currentFolders,
                        otherFolders);
                sortWorkspaceItemsSpatially(currentWorkspaceItems);
                sortWorkspaceItemsSpatially(otherWorkspaceItems);
    
                // Tell the workspace that we're about to start binding items
                r = new Runnable() {
                    public void run() {
                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                        if (callbacks != null) {
                            callbacks.startBinding();
                        }
                    }
                };
                runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
    
                // Load items on the current page
                bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,
                        currentFolders, null);
                if (isLoadingSynchronously) {
                    r = new Runnable() {
                        public void run() {
                            Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                            if (callbacks != null) {
                                callbacks.onPageBoundSynchronously(currentScreen);
                            }
                        }
                    };
                    runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
                }
    
                // Load all the remaining pages (if we are loading synchronously, we want to defer this
                // work until after the first render)
                mDeferredBindRunnables.clear();
                bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,
                        (isLoadingSynchronously ? mDeferredBindRunnables : null));
    
                // Tell the workspace that we're done binding items
                r = new Runnable() {
                    public void run() {
                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                        if (callbacks != null) {
                            callbacks.finishBindingItems();
                        }
    
                        // If we're profiling, ensure this is the last thing in the queue.
                        if (DEBUG_LOADERS) {
                            Log.d(TAG, "bound workspace in "
                                + (SystemClock.uptimeMillis()-t) + "ms");
                        }
    
                        mIsLoadingAndBindingWorkspace = false;
                    }
                };
                if (isLoadingSynchronously) {
                    mDeferredBindRunnables.add(r);
                } else {
                    runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
                }
            }
    

    bindWorkspaceItems

    绑定当前页面,绑定其他页

    private void bindWorkspaceItems(final Callbacks oldCallbacks,
                    final ArrayList<ItemInfo> workspaceItems,
                    final ArrayList<LauncherAppWidgetInfo> appWidgets,
                    final HashMap<Long, FolderInfo> folders,
                    ArrayList<Runnable> deferredBindRunnables) {
    
                final boolean postOnMainThread = (deferredBindRunnables != null);
    
                // Bind the workspace items
                int N = workspaceItems.size();
                for (int i = 0; i < N; i += ITEMS_CHUNK) {
                    final int start = i;
                    final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);
                    final Runnable r = new Runnable() {
                        @Override
                        public void run() {
                            Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                            if (callbacks != null) {
                                callbacks.bindItems(workspaceItems, start, start+chunkSize);
                            }
                        }
                    };
                    if (postOnMainThread) {
                        deferredBindRunnables.add(r);
                    } else {
                        runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
                    }
                }
    
                // Bind the folders
                if (!folders.isEmpty()) {
                    final Runnable r = new Runnable() {
                        public void run() {
                            Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                            if (callbacks != null) {
                                callbacks.bindFolders(folders);
                            }
                        }
                    };
                    if (postOnMainThread) {
                        deferredBindRunnables.add(r);
                    } else {
                        runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
                    }
                }
    
                // Bind the widgets, one at a time
                N = appWidgets.size();
                for (int i = 0; i < N; i++) {
                    final LauncherAppWidgetInfo widget = appWidgets.get(i);
                    final Runnable r = new Runnable() {
                        public void run() {
                            Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                            if (callbacks != null) {
                                callbacks.bindAppWidget(widget);
                            }
                        }
                    };
                    if (postOnMainThread) {
                        deferredBindRunnables.add(r);
                    } else {
                        runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
                    }
                }
            }
    

      

    private static final int ITEMS_CHUNK = 6;

    绑定顺序:

    绑定快捷方式:callbacks.bindItems(workspaceItems, start, start+chunkSize);

    绑定文件夹:callbacks.bindFolders(folders);

    绑定小控件:callbacks.bindAppWidget(widget);

    再下来研究具体绑定函数:Launcher。java 中的bindItems方式的实现

    /**
         * Bind the items start-end from the list.
         *
         * Implementation of the method from LauncherModel.Callbacks.
         */
        public void bindItems(final ArrayList<ItemInfo> shortcuts, final int start, final int end) {
            if (waitUntilResume(new Runnable() {
                    public void run() {
                        bindItems(shortcuts, start, end);
                    }
                })) {
                return;
            }
    
            // Get the list of added shortcuts and intersect them with the set of shortcuts here
            Set<String> newApps = new HashSet<String>();
            newApps = mSharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);
    
            Workspace workspace = mWorkspace;
            for (int i = start; i < end; i++) {
                final ItemInfo item = shortcuts.get(i);
    
                // Short circuit if we are loading dock items for a configuration which has no dock
                if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
                        mHotseat == null) {
                    continue;
                }
    
                switch (item.itemType) {
                    case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                        ShortcutInfo info = (ShortcutInfo) item;
                        String uri = info.intent.toUri(0).toString();
                        View shortcut = createShortcut(info);
                        workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,
                                item.cellY, 1, 1, false);
                        boolean animateIconUp = false;
                        synchronized (newApps) {
                            if (newApps.contains(uri)) {
                                animateIconUp = newApps.remove(uri);
                            }
                        }
                        if (animateIconUp) {
                            // Prepare the view to be animated up
                            shortcut.setAlpha(0f);
                            shortcut.setScaleX(0f);
                            shortcut.setScaleY(0f);
                            mNewShortcutAnimatePage = item.screen;
                            if (!mNewShortcutAnimateViews.contains(shortcut)) {
                                mNewShortcutAnimateViews.add(shortcut);
                            }
                        }
                        break;
                    case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                        FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
                                (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
                                (FolderInfo) item, mIconCache);
                        workspace.addInScreen(newFolder, item.container, item.screen, item.cellX,
                                item.cellY, 1, 1, false);
                        break;
                }
            }
    
            workspace.requestLayout();
        }
    waitUntilResume函数暂不看 在pause情况下才执行
    快捷方式和应用图标,文件夹生成相应View后加入workspace,具体如何加入view 待分析自定义workspace控件再看。
    mNewShortcutAnimateViews 在绑定完成后统一执行动画显示 如下:
    public void finishBindingItems() {
            if (waitUntilResume(new Runnable() {
                    public void run() {
                        finishBindingItems();
                    }
                })) {
                return;
            }
            if (mSavedState != null) {
                if (!mWorkspace.hasFocus()) {
                    mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus();
                }
                mSavedState = null;
            }
    
            mWorkspace.restoreInstanceStateForRemainingPages();
    
            // If we received the result of any pending adds while the loader was running (e.g. the
            // widget configuration forced an orientation change), process them now.
            for (int i = 0; i < sPendingAddList.size(); i++) {
                completeAdd(sPendingAddList.get(i));
            }
            sPendingAddList.clear();
    
            // Update the market app icon as necessary (the other icons will be managed in response to
            // package changes in bindSearchablesChanged()
            updateAppMarketIcon();
    
            // Animate up any icons as necessary
            if (mVisible || mWorkspaceLoading) {
                Runnable newAppsRunnable = new Runnable() {
                    @Override
                    public void run() {
                        runNewAppsAnimation(false);
                    }
                };
    
                boolean willSnapPage = mNewShortcutAnimatePage > -1 &&
                        mNewShortcutAnimatePage != mWorkspace.getCurrentPage();
                if (canRunNewAppsAnimation()) {
                    // If the user has not interacted recently, then either snap to the new page to show
                    // the new-apps animation or just run them if they are to appear on the current page
                    if (willSnapPage) {
                        mWorkspace.snapToPage(mNewShortcutAnimatePage, newAppsRunnable);
                    } else {
                        runNewAppsAnimation(false);
                    }
                } else {
                    // If the user has interacted recently, then just add the items in place if they
                    // are on another page (or just normally if they are added to the current page)
                    runNewAppsAnimation(willSnapPage);
                }
            }
    
            mWorkspaceLoading = false;
        }
     /**
         * Runs a new animation that scales up icons that were added while Launcher was in the
         * background.
         *
         * @param immediate whether to run the animation or show the results immediately
         */
        private void runNewAppsAnimation(boolean immediate) {
            AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
            Collection<Animator> bounceAnims = new ArrayList<Animator>();
    
            // Order these new views spatially so that they animate in order
            Collections.sort(mNewShortcutAnimateViews, new Comparator<View>() {
                @Override
                public int compare(View a, View b) {
                    CellLayout.LayoutParams alp = (CellLayout.LayoutParams) a.getLayoutParams();
                    CellLayout.LayoutParams blp = (CellLayout.LayoutParams) b.getLayoutParams();
                    int cellCountX = LauncherModel.getCellCountX();
                    return (alp.cellY * cellCountX + alp.cellX) - (blp.cellY * cellCountX + blp.cellX);
                }
            });
    
            // Animate each of the views in place (or show them immediately if requested)
            if (immediate) {
                for (View v : mNewShortcutAnimateViews) {
                    v.setAlpha(1f);
                    v.setScaleX(1f);
                    v.setScaleY(1f);
                }
            } else {
                for (int i = 0; i < mNewShortcutAnimateViews.size(); ++i) {
                    View v = mNewShortcutAnimateViews.get(i);
                    ValueAnimator bounceAnim = LauncherAnimUtils.ofPropertyValuesHolder(v,
                            PropertyValuesHolder.ofFloat("alpha", 1f),
                            PropertyValuesHolder.ofFloat("scaleX", 1f),
                            PropertyValuesHolder.ofFloat("scaleY", 1f));
                    bounceAnim.setDuration(InstallShortcutReceiver.NEW_SHORTCUT_BOUNCE_DURATION);
                    bounceAnim.setStartDelay(i * InstallShortcutReceiver.NEW_SHORTCUT_STAGGER_DELAY);
                    bounceAnim.setInterpolator(new SmoothPagedView.OvershootInterpolator());
                    bounceAnims.add(bounceAnim);
                }
                anim.playTogether(bounceAnims);
                anim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (mWorkspace != null) {
                            mWorkspace.postDelayed(mBuildLayersRunnable, 500);
                        }
                    }
                });
                anim.start();
            }
    
            // Clean up
            mNewShortcutAnimatePage = -1;
            mNewShortcutAnimateViews.clear();
            new Thread("clearNewAppsThread") {
                public void run() {
                    mSharedPrefs.edit()
                                .putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, -1)
                                .putStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, null)
                                .commit();
                }
            }.start();
        }

    自此bindWorkspaceItems()完结

    loadAndBindWorkspace()方法是加载和绑定桌面资源 (从资源文件和旧偏好)

    开始分析  loadAndBindAllApps()桌面绑定app信息

         private void loadAndBindAllApps() {
                if (DEBUG_LOADERS) {
                    Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
                }
                if (!mAllAppsLoaded) {
                    loadAllAppsByBatch();
                    synchronized (LoaderTask.this) {
                        if (mStopped) {
                            return;
                        }
                        mAllAppsLoaded = true;
                    }
                } else {
                    onlyBindAllApps();
                }
            }

    如上 执行loadAllAppsByBatch();

    private void loadAllAppsByBatch() {
                final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
    
                // Don't use these two variables in any of the callback runnables.
                // Otherwise we hold a reference to them.
                final Callbacks oldCallbacks = mCallbacks.get();
                if (oldCallbacks == null) {
                    // This launcher has exited and nobody bothered to tell us.  Just bail.
                    Log.w(TAG, "LoaderTask running with no launcher (loadAllAppsByBatch)");
                    return;
                }
    
                final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
                mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    
                final List<UserHandle> profiles = mUserManager.getUserProfiles();
    
                mBgAllAppsList.clear();
                final int profileCount = profiles.size();
                for (int p = 0; p < profileCount; p++) {
                    UserHandle user = profiles.get(p);
                    List<LauncherActivityInfo> apps = null;
                    int N = Integer.MAX_VALUE;
    
                    int startIndex;
                    int i = 0;
                    int batchSize = -1;
                    while (i < N && !mStopped) {
                        if (i == 0) {
                            final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
                            apps = mLauncherApps.getActivityList(null, user);
                            if (DEBUG_LOADERS) {
                                Log.d(TAG, "queryIntentActivities took "
                                        + (SystemClock.uptimeMillis()-qiaTime) + "ms");
                            }
                            if (apps == null) {
                                return;
                            }
                            N = apps.size();
                            if (DEBUG_LOADERS) {
                                Log.d(TAG, "queryIntentActivities got " + N + " apps");
                            }
                            if (N == 0) {
                                // There are no apps?!?
                                return;
                            }
                            if (mBatchSize == 0) {
                                batchSize = N;
                            } else {
                                batchSize = mBatchSize;
                            }
    
                            final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
                            Collections.sort(apps,
                                    new LauncherModel.ShortcutNameComparator(mLabelCache));
                            if (DEBUG_LOADERS) {
                                Log.d(TAG, "sort took "
                                        + (SystemClock.uptimeMillis()-sortTime) + "ms");
                            }
                        }
    
                        final long t2 = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
    
                        startIndex = i;
                        for (int j=0; i<N && j<batchSize; j++) {
                            // This builds the icon bitmaps.
                            mBgAllAppsList.add(new ApplicationInfo(apps.get(i), user,
                                    mIconCache, mLabelCache));
                            i++;
                        }
    
                        final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                        final ArrayList<ApplicationInfo> added = mBgAllAppsList.added;
                        final boolean firstProfile = p == 0;
                        mBgAllAppsList.added = new ArrayList<ApplicationInfo>();
                        mHandler.post(new Runnable() {
                            public void run() {
                                final long t = SystemClock.uptimeMillis();
                                if (callbacks != null) {
                                    if (firstProfile) {
                                        callbacks.bindAllApplications(added);
                                    } else {
                                        callbacks.bindAppsAdded(added);
                                    }
                                    if (DEBUG_LOADERS) {
                                        Log.d(TAG, "bound " + added.size() + " apps in "
                                            + (SystemClock.uptimeMillis() - t) + "ms");
                                    }
                                } else {
                                    Log.i(TAG, "not binding apps: no Launcher activity");
                                }
                            }
                        });
    
                        if (DEBUG_LOADERS) {
                            Log.d(TAG, "batch of " + (i-startIndex) + " icons processed in "
                                    + (SystemClock.uptimeMillis()-t2) + "ms");
                        }
    
                        if (mAllAppsLoadDelay > 0 && i < N) {
                            try {
                                if (DEBUG_LOADERS) {
                                    Log.d(TAG, "sleeping for " + mAllAppsLoadDelay + "ms");
                                }
                                Thread.sleep(mAllAppsLoadDelay);
                            } catch (InterruptedException exc) { }
                        }
                    }
    
                    if (DEBUG_LOADERS) {
                        Log.d(TAG, "cached all " + N + " apps in "
                                + (SystemClock.uptimeMillis()-t) + "ms"
                                + (mAllAppsLoadDelay > 0 ? " (including delay)" : ""));
                    }
                }
            }

     apps = mLauncherApps.getActivityList(null, user);

    mBgAllAppsList.add(new ApplicationInfo(apps.get(i), user,
    mIconCache, mLabelCache));

    mBgAllAppsList 为所有app 

    回调 Laucher.java 中 callbacks.bindAllApplications(added);方法

    
    
    
     /**
         * Add the icons for all apps.
         *
         * Implementation of the method from LauncherModel.Callbacks.
         */
        public void bindAllApplications(final ArrayList<ApplicationInfo> apps) {
            Runnable setAllAppsRunnable = new Runnable() {
                public void run() {
                    if (mAppsCustomizeContent != null) {
                        mAppsCustomizeContent.setApps(apps);
                    }
                }
            };
    
            // Remove the progress bar entirely; we could also make it GONE
            // but better to remove it since we know it's not going to be used
            View progressBar = mAppsCustomizeTabHost.
                findViewById(R.id.apps_customize_progress_bar);
            if (progressBar != null) {
                ((ViewGroup)progressBar.getParent()).removeView(progressBar);
    
                // We just post the call to setApps so the user sees the progress bar
                // disappear-- otherwise, it just looks like the progress bar froze
                // which doesn't look great
                mAppsCustomizeTabHost.post(setAllAppsRunnable);
            } else {
                // If we did not initialize the spinner in onCreate, then we can directly set the
                // list of applications without waiting for any progress bars views to be hidden.
                setAllAppsRunnable.run();
            }
        }

    AppsCustomizePagedView为所有app界面

    mAppsCustomizeContent.setApps(apps);所有app数据表示绑定所有app界面完成

    自此 loadAndBindAllApps()桌面绑定app信息完结

    即launcher资源加载全部完成了!

     参考了:http://blog.csdn.net/wdaming1986/article/details/7585649



  • 相关阅读:
    象棋
    支持向量机
    朴素贝叶斯分类
    规则归纳
    监督学习
    序列模式
    关联规则
    从《数据挖掘概念与技术》到《Web数据挖掘》
    数据挖掘在大数据中的应用综述
    join sql图
  • 原文地址:https://www.cnblogs.com/wjw334/p/4308414.html
Copyright © 2020-2023  润新知