Laucnher3采用mv模式。 数据层为LauncherModel,采用异步加载方式读写数据。界面层为Launcher
(1~7 ) 准备工作
(8~12 ) 工作线程sWorkThread 执行任务LoadTask
(11~18 ) 找到适配的xml配置文件
(17~ 27) 解析xml数据,存入到workScreens favorites数据库
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)得到
(2)递归调用方法parseLayout 去解析 dw_phone_hotseat.xml
(3)解析container,screen属性存入到contentValues里面
(4)解析x,y属性存入到contentValues里面
(5)得到
(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;
}
}
(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。