Launcher3 loadAndBindWorkspace

皇甫聪
2023-12-01
看一下LauncherModel是怎么加载应用的
在LoaderTask的run方法中调用了
/** Returns whether this is an upgrade path */
 
 
private boolean loadAndBindWorkspace() {
    mIsLoadingAndBindingWorkspace = true;
    boolean isUpgradePath = false;
    if (!mWorkspaceLoaded) {
        isUpgradePath = loadWorkspace();
        synchronized (LoaderTask.this) {
            if (mStopped) {
                return isUpgradePath;
            }
            mWorkspaceLoaded = true;
        }
    }
    // Bind the workspace
    bindWorkspace(-1, isUpgradePath);
    return isUpgradePath;
}
关键代码:
 isUpgradePath = loadWorkspace();//加载应用
 bindWorkspace(-1, isUpgradePath);//将应用添加到主屏上
 
  
private boolean loadWorkspace() {
 
  
   final Context context = mContext;
  final ContentResolver contentResolver = context.getContentResolver();
  final PackageManager manager = context.getPackageManager();
  final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
  //初始化变量
  final boolean  isSdCardReady = context.registerReceiver( null ,
 
  
new IntentFilter(StartupReceiver.SYSTEM_READY)) != null
   //这个真没搞懂是干啥的应该和sd卡上的应用有关系吧
   DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
  int countX = (int) grid.numColumns;
  int countY = (int) grid.numRows;
//DeviceProfile 存储了布局信息,拿到网格x,y的值
  if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {
Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);
    LauncherAppState.getLauncherProvider().deleteDatabase();
  }
//判断是否需要删除数据库
 
  
  if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) {
    // append the user's Launcher2 shortcuts
     Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true);
     LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts();
  } else {
    // Make sure the default workspace is loaded
     Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);
     LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();
  }
//从launcher2的数据库加载布局,或者加载默认布局
 
  
先看migrateLauncher2Shortcuts
  这个方法体里面主要的操作是
  c = resolver.query(uri, null, null, null, "title ASC")
  查询launcher2的contentprovider
  遍历cursor
  if (itemType != Favorites.ITEM_TYPE_FOLDER)
  如果item并不是文件夹,获取intent
  intent = Intent.parseUri(intentStr, 0)
  cn = intent.getComponent();
  LauncherModel.isValidPackageActivity(mContext, cn,userHandle)
  //判断获取的应用是否有效
//判断的方式:android L>>LauncherApps isActivityEnabled  (LauncherApps 通过getSystemService("launcherApp")得到)    
     低版本 >> ActivityInfo info = mPm.getActivityInfo(component, 0);
                        return info != null && info.isEnabled()
构造contentvalue,设置value的值,将所有数据遍历完之后放入一个集合中,开启事务,遍历集合,将所有数据存入数据库,然后,保存screen数据到数据库中。 遍历的时候根据item的类型有不同的操作,可以进去看一下,这里不详细分析了
 
  
看loadDefaultFavoritesIfNecessary()
 WorkspaceLoader loader 这个东西没看懂,字面上是workspace加载器
 WorkspaceLoader loader = AutoInstallsLayout.get(getContext(),
mOpenHelper.mAppWidgetHost, mOpenHelper);
这个方法不知道做了什么操作,跟进去也没看明白,反正就是queryBroadcastReceivers()
   获取指定intent("android.autoinstalls.config.action.PLAY_AUTO_INSTALL")的应用,说实话,真心没懂这个intent是干嘛的,Android L增加了很多新api
 Partner partner 这个也没看懂
 loader = new SimpleWorkspaceLoader(mOpenHelper, getContext().getResources(),
getDefaultWorkspaceResourceId());
创建加载器 getDefaultWorkspaceResourceId 这个获取带不带抽屉的default_workspace.xml
 
  
mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(), loader);//关键代码,加载保存数据
进入private int loadFavorites(SQLiteDatabase db, WorkspaceLoader loader){. ..}
 
  
获取每个节点定义的内容,构造ContentVaule
 
  
if (TAG_FAVORITE.equals(name)) {
    long id = addAppShortcut(db, values, parser);
    added = id >= 0;
} else if (TAG_APPWIDGET.equals(name)) {
    added = addAppWidget(parser, type, db, values);
} else if (TAG_SHORTCUT.equals(name)) {
    long id = addUriShortcut(db, values, res, parser);
    added = id >= 0;
} else if (TAG_RESOLVE.equals(name)) {
    // This looks through the contained favorites (or meta-favorites) and
    // attempts to add them as shortcuts in the fallback group's location
    // until one is added successfully.
    added = false;
    final int groupDepth = parser.getDepth();
    while ((type = parser.next()) != XmlPullParser.END_TAG ||
            parser.getDepth() > groupDepth) {
        if (type != XmlPullParser.START_TAG) {
            continue;
        }
        final String fallback_item_name = parser.getName();
        if (!added) {
            if (TAG_FAVORITE.equals(fallback_item_name)) {
                final long id = addAppShortcut(db, values, parser);
                added = id >= 0;
            } else {
                Log.e(TAG, "Fallback groups can contain only favorites, found "
                        + fallback_item_name);
            }
        }
    }
 } else if (TAG_FOLDER.equals(name)) {
    // Folder contents are nested in this XML file
    added = loadFolder(db, values, res, parser);

}else if (TAG_PARTNER_FOLDER.equals(name)) {
// Folder contents come from an external XML resource
    final Partner partner = Partner.get(mPackageManager);
    if (partner != null) {
        final Resources partnerRes = partner.getResources();
        final int resId = partnerRes.getIdentifier(Partner.RES_FOLDER,
                "xml", partner.getPackageName());
        if (resId != 0) {
            final XmlResourceParser partnerParser = partnerRes.getXml(resId);
            beginDocument(partnerParser, TAG_FOLDER);
            added = loadFolder(db, values, partnerRes, partnerParser);
        }
    }
}
根据定义的内容不同做不同的操作(item类型不同)
都是把不同的item,构造ContentValue,设置不同的值,然后存入数据库中
其中loadFolder,把XmlpullPaser传过去,又做了一次递归读取文档的操作,遍历,然后将子item存入数据库,然后会判断 folder里面包含的数据,如果小于2,则会删除文件夹,将数据重新存入数据库,改变container为桌面
还有一个Resolve的标签,会将这个标签下的应用第一个加载到数据库,
然后将返回screen count
对screen排序,然后插入数据库
然后计算
 
  
mMaxItemId = initializeMaxItemId(db);
mMaxScreenId = initializeMaxScreenId(db);
默认布局加载完毕
int count = loader.loadLayout(db, screenIds);
最后调用了loadFavoritesRecursive//递归加载default_workspace.xml定义的内容
进入loadFavoritesRecursive
这里面做的操作就是使用XmlResourceParser解析xml文件

 类似资料:

相关阅读

相关文章

相关问答