In the last chapter, we talked about the data loading of the Launcher, including loading the default configuration application, folders, and widgets, loading all applications, and loading all widgets. Once the data is loaded, we start drawing the data to the desktop in batches, including the default configuration BIND, all applications BIND, and all widgets Bind. Here I will analyze them from these aspects and look at their loading process.

1. Bind ICONS, widgets, and folders by default


The previous chapter explained where the default configuration is loaded:

 private void loadAndBindWorkspace(a) {...if(! mWorkspaceLoaded) { loadWorkspace(); . }// Bind the workspace
            bindWorkspace(-1);
        }
Copy the code

Load the default configuration and then call bindWorkspace to bind. Let’s look at the flow chart:

The process looks like a lot of stuff, but in fact it’s just preparing the data and then starting the binding. Let’s look at the main code for bindWorkspace:

private void bindWorkspace(int synchronizeBindPage) {
			  // Prepare parameters.// Start binding. bindWorkspaceScreens(oldCallbacks, orderedScreenIds);// Load items on the current page
            bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,
                    currentFolders, null); . bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders, (isLoadingSynchronously ? mDeferredBindRunnables :null));

			  // End the binding. }Copy the code

We will first analyze the first method: bindWorkspaceScreens. We know that ICONS, folders, etc. on the desktop are placed in CellLayout (there is actually a container inside), so we will first add CellLayout as a whole container, which is this method:

private void bindWorkspaceScreens(final Callbacks oldCallbacks,
                                          final ArrayList<Long> orderedScreens) {
            final Runnable r = new Runnable() {
                @Override
                public void run(a) {
                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                    if(callbacks ! =null) { callbacks.bindScreens(orderedScreens); }}}; runOnMainThread(r); }Copy the code

The code is simple: call callbacks. BindScreens. This callback function is implemented in the Launcher.

The code implementation is to add CellLayout in the bindAddScreens method through the for loop, which is relatively simple and does not paste the code.

The first is bind for the ICONS, folders, and widgets on the current page. The second is bind for other screen ICONS, folders, and widgets. So we only have one process, and the rest is the same.

Let’s start with a flow chart:

There are three for loops that bind ICONS, folders, widgets,

public void bindItems(final ArrayList<ItemInfo> shortcuts, final int start, final int end,
                          final boolean forceAnimateIcons) {...for (int i = start; i < end; i++) {
            final ItemInfo item = shortcuts.get(i);

            // If it is in Hotseat and there is no Hotseat, skip it and continue
            if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
                    mHotseat == null) {
                continue;
            }

            final View view;
            switch (item.itemType) {
                case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                    ShortcutInfo info = (ShortcutInfo) item;
                    view = createShortcut(info);
                    break;
                case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                    view = FolderIcon.fromXml(R.layout.folder_icon, this,
                            (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
                            (FolderInfo) item, mIconCache);
                    break;
                default:
                    throw new RuntimeException("Invalid Item Type");
            }

            workspace.addInScreenFromBind(view, item.container, item.screenId, item.cellX,
                    item.cellY, 1.1);
}
Copy the code

In the switch statement above determine the type of Item, to generate different according to different types of View, finally through the workspace. The addInScreenFromBind method will View is bound to the desktop, then we see the addInScreenFromBind this method, This method finally calls the addInScreen method in Workspace. There are two parameters in this method that spanX and spanY haven’t talked about. Let me explain. A widget occupies not just one icon, but several icon positions, and spanX is the number of cells occupied horizontally, and spanY is the number of cells occupied in the Y direction. The control’s position on the desktop can be determined by its starting position and the number of cells it occupies. I’m not going to post the addInScreen code, I’m just going to go through the process here, go into this method, first check the type of the container, the type of the parent container: Or CellLayout Hotseat, then the judgment is a folder or icon, and finally by calling the layout. The addViewToCellLayout method according to the corresponding parameter is added to the corresponding container.

The other two bindings are similar, but the widget is a bit more complicated, which I won’t cover here. I’ll write a separate chapter on loading and adding widgets later.

2. Bind all applications


Bind all apps binds all app ICONS in the secondary interface, starting with: LauncherModel loadAllApps method, in the first loads all the application information in the mobile phone, then generate the corresponding objects, finally by calling callbacks. BindAllApplications method to apply all bound to the secondary interface, The callback function is still implemented in the Launcher, and the secondary interface is AllAppsContainerView, which calls the onAppsUpdated method according to the code flow, sorts through that method and finally calls the updateAdapterItems method, This interface is a RecyclerView, ready database, refresh adapter can be.

3. Bind all widgets


Binding Widget is also starting loadAllApps this method, a loadAndBindWidgetsAndShortcuts behind this method is the most, through this method bindings shortcuts and the Widget interface widgets to see code:

public void loadAndBindWidgetsAndShortcuts(final Callbacks callbacks, final boolean refresh) {

        runOnWorkerThread(new Runnable() {
            @Override
            public void run(a) {
                updateWidgetsModel(refresh);
                final WidgetsModel model = mBgWidgetsModel.clone();

                mHandler.post(new Runnable() {
                    @Override
                    public void run(a) {
                        Callbacks cb = getCallback();
                        if(callbacks == cb && cb ! =null) { callbacks.bindAllPackages(model); }}});// update the Widget entries inside DB on the worker thread.LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews( model.getRawList()); }}); }Copy the code

First I call the updateWidgetsModel method,

void updateWidgetsModel(boolean refresh) {
        PackageManager packageManager = mApp.getContext().getPackageManager();
        final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
        widgetsAndShortcuts.addAll(getWidgetProviders(mApp.getContext(), refresh));
        Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
        widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));
        mBgWidgetsModel.setWidgetsAndShortcuts(widgetsAndShortcuts);
    }
Copy the code

In this method first calls getWidgetProviders method to load all the small parts information, and then through the packageManager. QueryIntentActivities method to load all the shortcut information, Finally will of all the information placed in WidgetsModel, is completed by calling callbacks. BindAllPackages callback function began to bind all the widgets and shortcut, the callback function is realized in the Launcher, Then call the addWidgets method in the WidgetsContainerView to pass in the WidgetsModel object, and refresh the widget interface by calling the refresh adapter.

Finally: this chapter is relatively simple, mainly UI drawing, there are some processes I did not talk about, mainly UI drawing is actually related to custom view, a lot of people will see, so no longer explain, can not go to see the source code.

Github address: github.com/yuchuangu85…