launcher7:Android Launcher7.0首次数据加载逻辑

    

Launcher3简介

  Laucnher3采用mv模式。 数据层为LauncherModel,采用异步加载方式读写数据。界面层为Launcher

(1~7     )       准备工作

(8~12   )      工作线程sWorkThread 执行任务LoadTask

(11~18 )      找到适配的xml配置文件

(17~ 27)      解析xml数据,存入到workScreens  favorites数据库


解析XML代码分析

解析各个标签Google采用了策略模式,各个节点都需要解析,但是只是解析方法不同,Google将解析逻辑抽调出来,采用策略模式,降低耦合性。

21 (1)拿到根据屏幕尺寸匹配出来的default_workspace_*x*.xml文件生成解析器XmlResourceParser (2)得到各个节点解析器对象集合 (3)循环调用parseAndAddNode开始解析节点

protected int parseLayout(int layoutId, ArrayList<Long> screenIds) throws XmlPullParserException, IOException { XmlResourceParser parser = mSourceRes.getXml(layoutId); beginDocument(parser, mRootTag); final int depth = parser.getDepth(); int type; HashMap<String, TagParser> tagParserMap = getLayoutElementsMap(); int count = 0; while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { if (type != XmlPullParser.START_TAG) { continue; } count += parseAndAddNode(parser, tagParserMap, screenIds); } return count;}

22

(1)得到<include>节点标签名,拿到dw_phone_hotseat.xml id

(2)递归调用方法parseLayout 去解析 dw_phone_hotseat.xml

(3)解析container,screen属性存入到contentValues里面

(4)解析x,y属性存入到contentValues里面

(5)得到<resolve>节点标签名,去map中得到ResolveParser对象

(6)存入screenId

protected int parseAndAddNode( XmlResourceParser parser, HashMap<String, TagParser> tagParserMap, ArrayList<Long> screenIds) throws XmlPullParserException, IOException { if (TAG_INCLUDE.equals(parser.getName())) { final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0); if (resId != 0) { // recursively load some more favorites, why not? return parseLayout(resId, screenIds); } else { return 0; } } mValues.clear(); parseContainerAndScreen(parser, mTemp); final long container = mTemp[0]; final long screenId = mTemp[1]; mValues.put(Favorites.CONTAINER, container); mValues.put(Favorites.SCREEN, screenId); mValues.put(Favorites.CELLX, convertToDistanceFromEnd(getAttributeValue(parser, ATTR_X), mColumnCount)); mValues.put(Favorites.CELLY, convertToDistanceFromEnd(getAttributeValue(parser, ATTR_Y), mRowCount)); TagParser tagParser = tagParserMap.get(parser.getName()); if (tagParser == null) { if (LOGD) Log.d(TAG, "Ignoring unknown element tag: " + parser.getName()); return 0; } long newElementId = tagParser.parseAndAdd(parser); if (newElementId >= 0) { // Keep track of the set of screens which need to be added to the db. if (!screenIds.contains(screenId) && container == Favorites.CONTAINER_DESKTOP) { screenIds.add(screenId); } return 1; } return 0; }

24

(1)循环调用对象AppShortcutWithUriParser解析节点

protected class ResolveParser implements TagParser { private final AppShortcutWithUriParser mChildParser = new AppShortcutWithUriParser(); @Override public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException, IOException { final int groupDepth = parser.getDepth(); int type; long addedId = -1; while ((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > groupDepth) { if (type != XmlPullParser.START_TAG || addedId > -1) { continue; } final String fallback_item_name = parser.getName(); if (TAG_FAVORITE.equals(fallback_item_name)) { addedId = mChildParser.parseAndAdd(parser); } else { Log.e(TAG, "Fallback groups can contain only favorites, found " + fallback_item_name); } } return addedId; } }
25

(1) 通过packageName,className属性名,得到包类名

(2-1) 如果解析出来的包类名不为空则通过包类名生成intent对象

(2-2)如果解析出来的包类名为空则调用invalidPackageOrClass方法

(3)调用addShortcut方法存入到favorites数据库

public long parseAndAdd(XmlResourceParser parser) { final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME); final String className = getAttributeValue(parser, ATTR_CLASS_NAME); if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(className)) { ActivityInfo info; try { ComponentName cn; try { cn = new ComponentName(packageName, className); info = mPackageManager.getActivityInfo(cn, 0); } catch (PackageManager.NameNotFoundException nnfe) { String[] packages = mPackageManager.currentToCanonicalPackageNames( new String[] { packageName }); cn = new ComponentName(packages[0], className); info = mPackageManager.getActivityInfo(cn, 0); } final Intent intent = new Intent(Intent.ACTION_MAIN, null) .addCategory(Intent.CATEGORY_LAUNCHER) .setComponent(cn) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); return addShortcut(info.loadLabel(mPackageManager).toString(), intent, Favorites.ITEM_TYPE_APPLICATION); } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Unable to add favorite: " + packageName + "/" + className, e); } return -1; } else { return invalidPackageOrClass(parser); } }

(1)通过uri属性名解析uri值

(2)通过uri生成Intent值

(3)调用addShortcut方法存入到favorites数据库

protected long invalidPackageOrClass(XmlResourceParser parser) { final String uri = getAttributeValue(parser, ATTR_URI); if (TextUtils.isEmpty(uri)) { Log.e(TAG, "Skipping invalid <favorite> with no component or uri"); return -1; } final Intent metaIntent; try { metaIntent = Intent.parseUri(uri, 0); } catch (URISyntaxException e) { Log.e(TAG, "Unable to add meta-favorite: " + uri, e); return -1; } ResolveInfo resolved = mPackageManager.resolveActivity(metaIntent, PackageManager.MATCH_DEFAULT_ONLY); final List<ResolveInfo> appList = mPackageManager.queryIntentActivities( metaIntent, PackageManager.MATCH_DEFAULT_ONLY); // Verify that the result is an app and not just the resolver dialog asking which // app to use. if (wouldLaunchResolverActivity(resolved, appList)) { // If only one of the results is a system app then choose that as the default. final ResolveInfo systemApp = getSingleSystemActivity(appList); if (systemApp == null) { // There is no logical choice for this meta-favorite, so rather than making // a bad choice just add nothing. Log.w(TAG, "No preference or single system activity found for " + metaIntent.toString()); return -1; } resolved = systemApp; } final ActivityInfo info = resolved.activityInfo; final Intent intent = mPackageManager.getLaunchIntentForPackage(info.packageName); if (intent == null) { return -1; } ///M: ALPS02377365,intent is different with launched from "all apps list" {@ if ("com.android.gallery3d".equals(info.packageName)) { intent.setPackage(null); } /// @} intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); return addShortcut(info.loadLabel(mPackageManager).toString(), intent, Favorites.ITEM_TYPE_APPLICATION); }26

(1)将值存入到contentValues

(2)调用LauncherProvider类静态内部类DatabaseHelper.insertAndCheck存入到数据库

protected long addShortcut(String title, Intent intent, int type) { long id = mCallback.generateNewItemId(); mValues.put(Favorites.INTENT, intent.toUri(0)); mValues.put(Favorites.TITLE, title); mValues.put(Favorites.ITEM_TYPE, type); mValues.put(Favorites.SPANX, 1); mValues.put(Favorites.SPANY, 1); mValues.put(Favorites._ID, id); if (mCallback.insertAndCheck(mDb, mValues) < 0) { return -1; } else { return id; } }

解析完所有的标签存入到数据库以后。继续执行方法loadWorkSpace()读取数据库组sBgItemsIdMap,sBgWorkspaceItems,sBgAppWidgets,sBgFolders,sBgWorkspaceScreens。


       

相关推荐

相关文章