文章目录
一、AndroidManifest文件
<application
android:backupAgent="com.android.launcher3.LauncherBackupAgent"
android:fullBackupOnly="true"
android:fullBackupContent="@xml/backupscheme"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher_home"
android:label="@string/derived_app_name"
android:theme="@style/AppTheme"
android:largeHeap="@bool/config_largeHeap"
android:restoreAnyVersion="true"
android:supportsRtl="true" >
<activity
android:name="com.android.launcher3.Launcher"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="unspecified"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
android:resizeableActivity="true"
android:resumeWhilePausing="true"
android:taskAffinity=""
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
<category android:name="android.intent.category.LAUNCHER_APP" />
</intent-filter>
</activity>
<activity
android:name="com.android.launcher3.SettingsActivity"
android:label="@string/settings_button_text"
android:theme="@android:style/Theme.DeviceDefault.Settings"
android:autoRemoveFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<provider
android:name="com.android.launcher3.LauncherProvider"
android:authorities="com.android.launcher3.settings"
android:exported="true"
android:writePermission="com.android.launcher3.permission.WRITE_SETTINGS"
android:readPermission="com.android.launcher3.permission.READ_SETTINGS" />
</application>
</manifest>
在Application的标签下,有两个activity和一个provider,它们分别是:Launcher、SettingsActivity和LauncherProvider;
Launcher即我们手机看到的桌面;
SettingsActivity是桌面的设置页面;
LauncherProvider是用来存储页面布局信息的。
二、桌面布局
1.布局
- DragLayer是根布局,用来处理子View的拖动的布局;
- Workspace是用来装载桌面上其它所有布局的控件;
- SearchDropTargetBar是用来显示移除和卸载的控件;
- CellLayout是用来显示应用和桌面小工具的,一个Workspace中可以显示多个CellLayout;
- PageIndicator是用来指示当前为第几页的CellLayout;
- Hotseat是常用应用显示控件。
2. Launcher界面配置文件
路径是:\Launcher\res\xml\default_workspace.xml 。
<appwidget // 插件
launcher:className= " " // 该应用的类
launcher:packageName= "" // 该应用的包名
launcher:screen= " 1 " // 第1屏,0-4屏共5屏
launcher:x= " 2 " // 图标X位置,左上角第一个为0,向左递增,0-4共5个
launcher:y= " 1 " // 图标Y位置,左上角第一个为0,向下递增,0-2共3个
launcher:spanX= "3 " // 在x方向上所占格数
launcher:spanY= " 2 " />
3 Launcher.java的onCreate方法:
protected void onCreate(Bundle savedInstanceState) {
......
//建立LauncherAppState对象
LauncherAppState app = LauncherAppState.getInstance();
......
//建立LauncherModel对象
mModel = app.setLauncher(this);
//一些其他对象初始化
......
setContentView(R.layout.launcher);
setupViews();
if (!mRestoring) {
if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
// 如果用户离开启动器,那么我们应该在项目返回时异步加载它们。
mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
} else {
// 只有当启动器在前台时,用户旋转(或触发配置更改),我们才会同步加载页面
mModel.startLoader(mWorkspace.getRestorePage());
}
}
......
}
3.LauncherModel的startLoader的方法
startLoader里面,最重要的就是启动了LoaderTask
mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage);
4.LoaderTask的run方法
public void run() {
......
keep_running: {
// step 1: loading workspace
loadAndBindWorkspace();
if (mStopped) {
break keep_running;
}
waitForIdle();
// step 2: loading all apps
loadAndBindAllApps();
waitForIdle();
// step 3: loading deep shortcuts
loadAndBindDeepShortcuts();
}
......
}
5.workspace的加载流程
workspace的加载流程主要分为loadWorkspace();和bindWorkspace(mPageToBindFirst);
5.1.loadWorkspace()
主要功能就是负责从数据库表中读取数据并转译为Launcher桌面项的数据结构。
1、进行一些预处理
2、加载默认值
LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary()
int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT, "xml", partner.getPackageName());
3、初始化数据,清空之前的内存数据
/** Clears all the sBg data structures */
private void clearSBgDataStructures() {
synchronized (sBgLock) {
sBgWorkspaceItems.clear();
sBgAppWidgets.clear();
sBgFolders.clear();
sBgItemsIdMap.clear();
sBgWorkspaceScreens.clear();
}
}
4、查询ContentProvider,返回favorites表的结果集
final HashMap<String, Integer> installingPkgs = PackageInstallerCompat
.getInstance(mContext).updateAndGetActiveSessionCache();
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
final ArrayList<Long> restoredRows = new ArrayList<Long>();
final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
final Cursor c = contentResolver.query(contentUri, null, null, null, null);
5、根据不同的类型,将数据保存到对应的arrayList中。
6、根据类型,将数据保存到一下全局变量里面
sBgItemsIdMap,sBgWorkspaceItemsm,sBgAppWidgets,sBgFolders
另外,如果有空的文件夹、空的屏幕,也会delete掉,最终,把所有屏幕加载进全局变量sBgWorkspaceScreens中。
5.2.bindWorkspace
将上面获取到的数据由Launcher显示出来。
1、首先复制数据:
synchronized (sBgLock) {
workspaceItems.addAll(sBgWorkspaceItems);
appWidgets.addAll(sBgAppWidgets);
orderedScreenIds.addAll(sBgWorkspaceScreens);
folders = sBgFolders.clone();
itemsIdMap = sBgItemsIdMap.clone();
}
2、装载数据并排序
//装载桌面项数据
filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,
otherWorkspaceItems);
//装载widget
filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets,
otherAppWidgets);
//装载文件夹
filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders,
otherFolders);
//排序
sortWorkspaceItemsSpatially(currentWorkspaceItems);
sortWorkspaceItemsSpatially(otherWorkspaceItems);
3、开始绑定
6
参考资料
https://blog.youkuaiyun.com/yangshuangyue/article/details/122320642
https://blog.youkuaiyun.com/Picasso_L/article/details/70140694?ops_request_misc=&request_id=&biz_id=102&utm_term=default_workspace%20%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-70140694.142v9control,157v4control&spm=1018.2226.3001.4187
(如有侵权,立即删除)