// LauncherModel.java
private void loadAllApps() {
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfoCompat app = apps.get(i);
// 这里创建了icon信息
mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache));
}
}
// AppInfo.java
public AppInfo(Context context, LauncherActivityInfoCompat info, UserHandleCompat user, IconCache iconCache) {
this.componentName = info.getComponentName();
this.container = ItemInfo.NO_ID;
flags = initFlags(info);
firstInstallTime = info.getFirstInstallTime();
// 采用图标缓存器获取应用名和图标
iconCache.getTitleAndIcon(this, info, true /* useLowResIcon */);
intent = makeLaunchIntent(context, info, user);
this.user = user;
}
// IconCache.java
public synchronized void getTitleAndIcon(AppInfo application,
LauncherActivityInfoCompat info, boolean useLowResIcon) {
UserHandleCompat user = info == null ? application.user : info.getUser();
// 很熟悉的cacheLocked方法
CacheEntry entry = cacheLocked(application.componentName, info, user,
false, useLowResIcon, application.unreadNum);
application.title = Utilities.trim(entry.title);
application.iconBitmap = getNonNullIcon(entry, user);
application.contentDescription = entry.contentDescription;
application.usingLowResIcon = entry.isLowResIcon;
}
private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
UserHandleCompat user, boolean usePackageIcon, boolean useLowResIcon, int unreadNum) {
if (entry == null || (entry.isLowResIcon && !useLowResIcon)) {
entry = new CacheEntry();
mCache.put(cacheKey, entry);
if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
if (info != null) {
// 这里通过LauncherActivityInfoCompat的getBadgedIcon方法创建bitmap
// 注意传入的mIconDpi是图标的dpi
entry.icon = Utilities.createIconBitmap(info.getBadgedIcon(mIconDpi), mContext);
} else {
}
}
}
}
// LauncherActivityInfoCompatVL.java
public class LauncherActivityInfoCompatVL extends LauncherActivityInfoCompat {
public Drawable getBadgedIcon(int density) {
// 这里调用了框架层的LauncherActivityInfo.java的getBadgedIcon方法
return mLauncherActivityInfo.getBadgedIcon(density);
}
}
// IconCache.java
public IconCache(Context context, InvariantDeviceProfile inv) {
iconSize = interpolatedDeviceProfileOut.iconSize;
iconBitmapSize = Utilities.pxFromDp(iconSize, dm);
// InvariantDeviceProfile的fillResIconDpi成员
mIconDpi = inv.fillResIconDpi;
}
// InvariantDeviceProfile.java
InvariantDeviceProfile(Context context) {
fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
}
// 最终核心方法,根据Launcher3需要的图标大小来计算需要取用哪个dpi的图标
private int getLauncherIconDensity(int requiredSize) {
int[] densityBuckets = new int[] {
DisplayMetrics.DENSITY_LOW,
DisplayMetrics.DENSITY_MEDIUM,
DisplayMetrics.DENSITY_TV,
DisplayMetrics.DENSITY_HIGH,
DisplayMetrics.DENSITY_XHIGH,
DisplayMetrics.DENSITY_XXHIGH,
DisplayMetrics.DENSITY_XXXHIGH
};
int density = DisplayMetrics.DENSITY_XXXHIGH;
for (int i = densityBuckets.length - 1; i >= 0; i--) {
float expectedSize = ICON_SIZE_DEFINED_IN_APP_DP * densityBuckets[i]
/ DisplayMetrics.DENSITY_DEFAULT;
if (expectedSize >= requiredSize) {
density = densityBuckets[i];
}
}
return density;
}
石器时代