我是靠谱客的博主 尊敬灯泡,这篇文章主要介绍墨香带你学Launcher之(三)-绑定屏幕、图标、文件夹和Widget,现在分享给大家,希望可以做个参考。

上一章我们讲了Launcher的数据加载,包括:默认配置应用、文件夹以及widget的加载,所有应用的加载以及所有Widget的加载,数据加载完成后开始分批进行绘制到桌面上,包含默认配置bind,所有应用bind,所有小部件bind。下面我就从这几个方面进行分析,看看他们的加载过程。

1.默认配置图标、Widget、文件夹的绑定(bind)


上一章讲到默认配置加载的位置:

复制代码
1
2
3
4
5
6
7
8
9
private void loadAndBindWorkspace() { ... if (!mWorkspaceLoaded) { loadWorkspace(); ... } // Bind the workspace bindWorkspace(-1); }

这里主要是加载默认配置,然后调用bindWorkspace进行绑定,我们先看一下流程图:

![01](https://img-blog.csdn.net/20170113170233665?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzg5OTcwNg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 整个流程看似东西很多,其实就是准备数据,然后开始绑定,下面我们看bindWorkspace的主要代码:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void bindWorkspace(int synchronizeBindPage) { //准备参数 ... //开始绑定 ... bindWorkspaceScreens(oldCallbacks, orderedScreenIds); // Load items on the current page bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets, currentFolders, null); ... bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders, (isLoadingSynchronously ? mDeferredBindRunnables : null)); //结束绑定 ... }

我们先分析第一个方法:bindWorkspaceScreens,我们知道桌面上的图标、文件夹等是放置到CellLayout(实际内部还有一个容器)中的,因此我们要首先添加CellLayout整个容器,
也就是这个方法,代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
private void bindWorkspaceScreens(final Callbacks oldCallbacks, final ArrayList<Long> orderedScreens) { final Runnable r = new Runnable() { @Override public void run() { Callbacks callbacks = tryGetCallbacks(oldCallbacks); if (callbacks != null) { callbacks.bindScreens(orderedScreens); } } }; runOnMainThread(r); }

代码很简单,就是调用回调函数callbacks.bindScreens,这个回调函数是在Launcher中实现的,因此我们看流程图:

![02](https://img-blog.csdn.net/20170113170317853?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzg5OTcwNg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 代码实现就是在bindAddScreens方法中通过for循环添加CellLayout,比较简单不再贴代码。 我们接着看第二第三个函数,这两个函数是一样的,但是参数不一样,从参数名字可以看到第一个bind当前页面的图标、文件夹、widget的,第二个是bind其他屏幕图标、文件夹、widget的,因此我们只讲一个流程,剩下的是一样的。 我们先看流程图:
![03](https://img-blog.csdn.net/20170113170417417?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzg5OTcwNg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 从流程图看其实就是三个for循环,分别绑定图标、文件夹、小部件,
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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); // 如果是在Hotseat中并且没有Hotseat则跳过继续 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); }

在上面的switch语句中判断Item的类型,根据不同类型来生成不同的View,最后通过workspace.addInScreenFromBind方法将view绑定到桌面上,我们接着看一下addInScreenFromBind这个方法,这个方法最后调用到Workspace中的addInScreen方法,在这个方法中有两个参数spanX、spanY没有讲过,我来解释一下,我们第一章讲了图标排列到桌面上是按照4x4后者4x5等形式,那么每个单元是一个图标位置,但是,小部件的占用不只是一个图标,有可能几个图标的位置,而spanX就是横向占用的单元格个数,相应的spanY就是Y方向的占用个数。根据控件的起始位置,以及占用单元格个数就可以确定他在桌面上的位置。addInScreen代码我就不贴了,我只是在这说一下过程,进入这个方法,首先判断container的类型,也就是父容器的类型:CellLayout还是Hotseat,然后判断是文件夹还是图标,最后通过调用layout.addViewToCellLayout方法根据相应的参数来添加到相应的容器里面。

其他两个的绑定也是差不多的,只是widget的相对复杂一点,这里不再讲解,后面我会单独写一章来讲解widget的加载添加。

2.所有应用绑定(bind)


绑定所有应用其实是绑定二级界面的所有应用图标,代码开始位置是:LauncherModel中的loadAllApps方法,首先加载手机里的所有应用信息,然后生成对应的对象,最后通过调用callbacks.bindAllApplications方法将所有应用绑定到二级界面,回调函数依然是在Launcher中实现,二级界面是AllAppsContainerView,根据代码流程调用onAppsUpdated方法,在这个方法中排序最后调用updateAdapterItems方法,这个界面是一个RecyclerView,准备好数据库,刷新适配器即可。

3.所有Widget的绑定(bind)


绑定Widget也是从loadAllApps这个方法开始的,在这个方法的最后面有个loadAndBindWidgetsAndShortcuts,通过这个方法绑定快捷方式和widget到小部件界面,看代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void loadAndBindWidgetsAndShortcuts(final Callbacks callbacks, final boolean refresh) { runOnWorkerThread(new Runnable() { @Override public void run() { updateWidgetsModel(refresh); final WidgetsModel model = mBgWidgetsModel.clone(); mHandler.post(new Runnable() { @Override public void run() { 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()); } }); }

首先调用updateWidgetsModel方法,

复制代码
1
2
3
4
5
6
7
8
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); }

在这个方法中首先调用getWidgetProviders方法来加载所有的小部件信息,然后通过packageManager.queryIntentActivities方法加载所有的快捷方式信息,最后将所有的信息放置到WidgetsModel中,完成后通过调用callbacks.bindAllPackages回调函数开始绑定所有的小部件和快捷方式,回调函数在Launcher中实现,然后调用WidgetsContainerView中的addWidgets方法传入WidgetsModel对象,然后通过调用刷新适配器来刷新小部件界面。

最后:这一章相对简单,主要是UI的绘制,有一些流程我没有讲,主要是UI绘制其实和自定义view相关,很多人一看就会了,所以不再讲解,不会的可以去看看源码。

Github地址:https://github.com/yuchuangu85/Launcher3_mx

同步发布:墨香博客

微信公众账号:Code-MX
这里写图片描述

注:本文原创,转载请注明出处,多谢。

最后

以上就是尊敬灯泡最近收集整理的关于墨香带你学Launcher之(三)-绑定屏幕、图标、文件夹和Widget的全部内容,更多相关墨香带你学Launcher之(三)-绑定屏幕、图标、文件夹和Widget内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(110)

评论列表共有 0 条评论

立即
投稿
返回
顶部