Android10.0 Launcher3 启动和加载流程(下)

简介: 笔记

invDistWeightedInterpolate

调用这个方法时传进去的参数是当前手机真实的宽和高,以及经过排序后得到的与目标匹配度由高到低的profiles集合。具体的操作在代码中进行了注解,其实,很多手机型号一致的,计算的时候不算多,有些许差别,计算出来的偏差值也不多,所以这个偏差值纠正就分析到这里。

static DisplayOption invDistWeightedInterpolate(float width, float height,
              ArrayList<DisplayOption> points) {
      float weights = 0;
      DisplayOption p = points.get(0);
      if (dist(width, height, p.minWidthDps, p.minHeightDps) == 0) {
          return p;
      }
      DisplayOption out = new DisplayOption();
      out.name = "";
      for (int i = 0; i < points.size() && i < KNEARESTNEIGHBOR; ++i) {
          p = points.get(i);
          float w = weight(width, height, p.minWidthDps, p.minHeightDps, WEIGHT_POWER);
          weights += w;
          out.add(new DisplayOption().add(p).multiply(w));
          if (!TextUtils.isEmpty(out.name)) {
              out.name += "&";
          }
          out.name += "<" + (p.grid != null ? p.grid.name : "not found") + "," + p.name + ">";
      }
      return out.multiply(1.0f / weights);
  }

//获取默认的gridname,在该版本中返回的是空值
 private String getDefaultGridName(Context context) {
   String defaultGridName = "";
   DesktopGridController gridController = mMonitor.getDesktopGridController();
   if (gridController != null) {
       defaultGridName = gridController.getDefaultGridName();
       if (mMonitor.getSRController() != null
               && !gridController.isGridNameValid(defaultGridName)) {
           if (LogUtils.DEBUG) {
               LogUtils.d(TAG, "The default grid name configured is invalid:" + defaultGridName);
           }
           defaultGridName = mMonitor.getSRController().getGridNameFromStorage(context);
       }
       if (LogUtils.DEBUG) {
           LogUtils.d(TAG, "getDefaultGridName: defaultGridName = " + defaultGridName);
       }
   }
   return defaultGridName;

}

GridOption和DiaplayOption

private static final class DisplayOption {
      private final GridOption grid;
      private String name;
      private final float minWidthDps;
      private final float minHeightDps;
      private final boolean canBeDefault;
      private float iconSize;
      private float landscapeIconSize;
      private float iconTextSize;
      ...
}
   public static final class GridOption {
       public static final String TAG_NAME = "grid-option";
       public final String name;
       public final int numRows;
       public final int numColumns;
       private final int numFolderRows;
       private final int numFolderColumns;
       private final int numHotseatIcons;
       private final int defaultLayoutId;
       private final int demoModeLayoutId;
       private final SparseArray<TypedValue> extraAttrs;

##com.android.launcher3.prefs.xml
这是Launcher3应用主要的sharedprefs文件,作为分析时的参考
`/data/data/com.android.launcher3/shared_prefs/com.android.launcher3.prefs.xml`
```                                                                             <
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <int name="launcher.home_bounce_count" value="4" />
    <string name="migration_src_workspace_size">2,2</string>
    <boolean name="pref_add_icon_to_home" value="true" />
    <int name="migration_src_hotseat_count" value="0" />
    <boolean name="pref_add_icon_to_home_initialized" value="true" />
    <boolean name="sl_EMPTY_DATABASE_CREATED" value="true" />
    <int name="migration_src_density_dpi" value="140" />
    <string name="idp_grid_name">3_by_3</string>
</map>

MultiModeController.java


packages/apps/Launcher3/src/com/sprd/ext/multimode/MultiModeController.java

import static com.android.launcher3.LauncherProvider.SCHEMA_VERSION; //28
   public static String getKeyByMode(Context context, String originalKey) {
       return getKeyByMode(context, originalKey, SCHEMA_VERSION, isSingleLayerMode(context));
   }
    //参数:key, 数据库版本,是单层还是双层显示
   public static String getKeyByMode(
           Context context, String originalKey, int dbVersion, boolean isSingleLayerMode) {
       initControllerIfNeeded(context);
       return MultiModeUtilities.getKeyByMode(originalKey, isSingleLayerMode, dbVersion);
   }
   public static String getKeyByPreMode(Context context, String originalKey) {
       return getKeyByMode(context, originalKey, SCHEMA_VERSION, !isSingleLayerMode(context));
   }
    public static boolean isSingleLayerMode() {
        throwIfControllerNotInited();
        return sIsSingleLayerMode; //返回变量sIsSingleLayerMode
    }
    public static void setSingleLayerMode(Context context, boolean isSingleMode) {
        MultiModeUtilities.syncSaveNewModel(context,
                isSingleMode ? MultiModeUtilities.SINGLE : MultiModeUtilities.DUAL);
        //sIsSingleLayerMode在构造方法中赋值
        sIsSingleLayerMode = MultiModeUtilities.isSingleLayerMode(context);
        sIsDefaultMode = MultiModeUtilities.isDefaultMode(context);
    }
   public MultiModeController(Context context, LauncherAppMonitor monitor) {
       super(context);
        //是否支持动态显示
       sIsSupportDynamicChange = MultiModeUtilities.isSupportDynamicHomeStyle(context);
        //是否是单层显示
       sIsSingleLayerMode = MultiModeUtilities.isSingleLayerMode(context);
       sIsDefaultMode = MultiModeUtilities.isDefaultMode(context);
       monitor.registerCallback(mAppMonitorCallback);
       LogUtils.d(TAG, this);
   }
    //是否支持动态变化
   public static boolean isSupportDynamicChange() {
       throwIfControllerNotInited();
       return sIsSupportDynamicChange;
   }
   public static void setSupportDynamicChange(boolean isSupport) {
       sIsSupportDynamicChange = isSupport;
   }

MultiModeUtilities


packages/apps/Launcher3/src/com/sprd/ext/multimode/MultiModeUtilities.java

static final String SINGLE = "single";
   static final String DUAL = "dual";
   static final String SL_PREFIX = "sl_";
    //判断是否是单层显示
   static boolean isSingleLayerMode(Context context) {
       return FeatureOption.SPRD_MULTI_MODE_SUPPORT.get()
               && SINGLE.equals(getHomeScreenStylePrefValue(context));
   }
    //在sharepref中获取显示风格的值
   static String getHomeScreenStylePrefValue(Context context) {
       if (context == null) {
           return DUAL;
       }
       Resources res = context.getResources();
       return Utilities.getPrefs(context)
               .getString(LauncherSettingsExtension.PREF_HOME_SCREEN_STYLE_KEY,
                       res.getString(R.string.default_home_screen_style)); 
              //默认值为R.string.default_home_screen_style
   }
    // We add SL_PREFIX only single layer mode & support dynamic change.
    static String getKeyByMode(String originalKey, boolean isSingleMode, int dbVersion) {
        if (TextUtils.isEmpty(originalKey)) {
            throw new RuntimeException("getKeyByMode() the original key is empty!");
        }
        String outKey = originalKey;
        //如果支持多模式,再进行判断,如果不支持,则使用双层模式
        //我修改了show_home_screen_style_settings的值为false,outKey=idp_grid_name
        if (MultiModeController.isSupportDynamicChange()) {
            switch (dbVersion) {
                case 27:
                    // Android P db version is 27.
                    outKey = isSingleMode ? SINGLE + "_" + originalKey : DUAL + "_" + originalKey;
                    break;
                default:
                    //我的设备是单层显示,所以返回的是sl_idp_grid_name
                    outKey = isSingleMode ? SL_PREFIX + originalKey : originalKey;
                    break;
            }
        }
        return outKey;
    }
  //是否支持动态显示
   static boolean isSupportDynamicHomeStyle(Context context) {
       return FeatureOption.SPRD_MULTI_MODE_SUPPORT.get()
               && context.getResources().getBoolean(R.bool.show_home_screen_style_settings);
   }

LauncherSettingsExtension


packages/apps/Launcher3/src/com/sprd/ext/LauncherSettingsExtension.java

public static final String PREF_HOME_SCREEN_STYLE_KEY = "pref_home_screen_style";

FeatureOption


packages/apps/Launcher3/src/com/sprd/ext/FeatureOption.java

public static final TogglableFlag SPRD_MULTI_MODE_SUPPORT = new TogglableFlag(
          "SPRD_MULTI_MODE_SUPPORT", getProp("ro.launcher.multimode"),
          "enable user can select user aosp mode or singlelayer mode");
  public static final TogglableFlag SPRD_DESKTOP_GRID_SUPPORT = new TogglableFlag(
          "SPRD_DESKTOP_GRID_SUPPORT", getProp("ro.launcher.desktopgrid"),
          "enable allows customization of the columns and rows on the desktop");

config_ext.xml


packages/apps/Launcher3/res/values/config_ext.xml

//从上面分析可以得出结论
    <!--default value of launcher style allapps or singlelayer 是否显示单层/双层设置显示-->
    <bool name="show_home_screen_style_settings">false</bool>
    <!--The value must be dual or single 默认为单层还是双层-->
    <string name="default_home_screen_style" translatable="false">dual</string>

device_profiles.xml


位置:packages/apps/Launcher3/res/xml/device_profiles.xml

<profiles xmlns:launcher="http://schemas.android.com/apk/res-auto" >
    <grid-option
        launcher:name="2_by_2"
        launcher:numRows="2"
        launcher:numColumns="2"
        launcher:numFolderRows="2"
        launcher:numFolderColumns="2"
        launcher:numHotseatIcons="3" 
        launcher:defaultLayoutId="@xml/default_workspace_3x3" >
        <display-option
            launcher:name="Super Short Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="300"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Shorter Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="400"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
    </grid-option>
    <grid-option
        launcher:name="3_by_3"
        launcher:numRows="3"
        launcher:numColumns="3"
        launcher:numFolderRows="2"
        launcher:numFolderColumns="3"
        launcher:numHotseatIcons="3"
        launcher:defaultLayoutId="@xml/default_workspace_3x3" >
        <display-option
            launcher:name="Super Short Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="300"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Shorter Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="400"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
    </grid-option>
    <grid-option
        launcher:name="4_by_4"
        launcher:numRows="4"
        launcher:numColumns="4"
        launcher:numFolderRows="3"
        launcher:numFolderColumns="4"
        launcher:numHotseatIcons="4"
        launcher:defaultLayoutId="@xml/default_workspace_4x4" >
        <display-option
            launcher:name="Short Stubby"
            launcher:minWidthDps="275"
            launcher:minHeightDps="420"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="450"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Nexus S"
            launcher:minWidthDps="296"
            launcher:minHeightDps="491.33"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Nexus 4"
            launcher:minWidthDps="359"
            launcher:minHeightDps="567"
            launcher:iconImageSize="54"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Nexus 5"
            launcher:minWidthDps="335"
            launcher:minHeightDps="567"
            launcher:iconImageSize="54"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
    </grid-option>
</profiles>


目录
相关文章
|
6月前
|
Java Android开发
Android面试题经典之Glide取消加载以及线程池优化
Glide通过生命周期管理在`onStop`时暂停请求,`onDestroy`时取消请求,减少资源浪费。在`EngineJob`和`DecodeJob`中使用`cancel`方法标记任务并中断数据获取。当网络请求被取消时,`HttpUrlFetcher`的`cancel`方法设置标志,之后的数据获取会返回`null`,中断加载流程。Glide还使用定制的线程池,如AnimationExecutor、diskCacheExecutor、sourceExecutor和newUnlimitedSourceExecutor,其中某些禁止网络访问,并根据CPU核心数动态调整线程数。
175 2
|
3月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
98 6
|
3月前
|
Android开发 UED
Android 中加载 Gif 动画
【10月更文挑战第20天】加载 Gif 动画是 Android 开发中的一项重要技能。通过使用第三方库或自定义实现,可以方便地在应用中展示生动的 Gif 动画。在实际应用中,需要根据具体情况进行合理选择和优化,以确保用户体验和性能的平衡。可以通过不断的实践和探索,进一步掌握在 Android 中加载 Gif 动画的技巧和方法,为开发高质量的 Android 应用提供支持。
|
3月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
3月前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
34 3
|
3月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
29 2
|
3月前
|
XML 前端开发 Android开发
Android View的绘制流程和原理详细解说
Android View的绘制流程和原理详细解说
56 3
|
3月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
23 0
|
4月前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
讲解Activity的启动流程了,Activity的启动流程相对复杂一下,涉及到了Activity中的生命周期方法,涉及到了Android体系的CS模式,涉及到了Android中进程通讯Binder机制等等, 首先介绍一下Activity,这里引用一下Android guide中对Activity的介绍:
61 4
|
4月前
|
Android开发 开发者
Android面试之Activity启动流程简述
每个Android开发者都熟悉的Activity,但你是否了解它的启动流程呢?本文将带你深入了解。启动流程涉及四个关键角色:Launcher进程、SystemServer的AMS、应用程序的ActivityThread及Zygote进程。核心在于AMS与ActivityThread间的通信。文章详细解析了从Launcher启动Activity的过程,包括通过AIDL获取AMS、Zygote进程启动以及ActivityThread与AMS的通信机制。接着介绍了如何创建Application及Activity的具体步骤。整体流程清晰明了,帮助你更深入理解Activity的工作原理。
64 0