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

Android Launcher7.0首次数据加载逻辑_第1张图片    

Launcher3简介

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

(1~7     )       准备工作

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

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

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


解析XML代码分析

解析各个标签Google采用了策略模式,各个节点都需要解析,但是只是解析方法不同,Google将解析逻辑抽调出来,采用策略模式,降低耦合性。
Android Launcher7.0首次数据加载逻辑_第2张图片
21
(1)拿到根据屏幕尺寸匹配出来的default_workspace_*x*.xml文件生成解析器XmlResourceParser
(2)得到各个节点解析器对象集合
(3)循环调用parseAndAddNode开始解析节点

protected int parseLayout(int layoutId, ArrayList screenIds)
            throws XmlPullParserException, IOException {
        XmlResourceParser parser = mSourceRes.getXml(layoutId);
        beginDocument(parser, mRootTag);
        final int depth = parser.getDepth();
        int type;
        HashMap 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)得到节点标签名,拿到dw_phone_hotseat.xml id

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

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

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

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

(6)存入screenId

    protected int parseAndAddNode(
            XmlResourceParser parser,
            HashMap tagParserMap,
            ArrayList 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  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 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。


       

你可能感兴趣的:(android,launcher,数据,Android,SourceCode)