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>


目录
相关文章
|
3月前
|
Java Android开发
Android面试题经典之Glide取消加载以及线程池优化
Glide通过生命周期管理在`onStop`时暂停请求,`onDestroy`时取消请求,减少资源浪费。在`EngineJob`和`DecodeJob`中使用`cancel`方法标记任务并中断数据获取。当网络请求被取消时,`HttpUrlFetcher`的`cancel`方法设置标志,之后的数据获取会返回`null`,中断加载流程。Glide还使用定制的线程池,如AnimationExecutor、diskCacheExecutor、sourceExecutor和newUnlimitedSourceExecutor,其中某些禁止网络访问,并根据CPU核心数动态调整线程数。
93 2
|
6天前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
讲解Activity的启动流程了,Activity的启动流程相对复杂一下,涉及到了Activity中的生命周期方法,涉及到了Android体系的CS模式,涉及到了Android中进程通讯Binder机制等等, 首先介绍一下Activity,这里引用一下Android guide中对Activity的介绍:
23 4
|
6天前
|
Android开发 开发者
Android面试之Activity启动流程简述
每个Android开发者都熟悉的Activity,但你是否了解它的启动流程呢?本文将带你深入了解。启动流程涉及四个关键角色:Launcher进程、SystemServer的AMS、应用程序的ActivityThread及Zygote进程。核心在于AMS与ActivityThread间的通信。文章详细解析了从Launcher启动Activity的过程,包括通过AIDL获取AMS、Zygote进程启动以及ActivityThread与AMS的通信机制。接着介绍了如何创建Application及Activity的具体步骤。整体流程清晰明了,帮助你更深入理解Activity的工作原理。
14 0
|
2月前
|
Android开发
我的Android进阶修炼:安卓启动流程之init(1)
本文深入分析了Android系统中的init进程,包括其源码结构、主要功能以及启动流程的详细注解,旨在帮助读者理解init作为用户空间的1号进程在Android启动过程中的关键作用。
31 1
|
2月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
View的绘制和事件处理是两个重要的主题,上一篇《图解 Android事件分发机制》已经把事件的分发机制讲得比较详细了,这一篇是针对View的绘制,View的绘制如果你有所了解,基本分为measure、layout、draw 过程,其中比较难理解就是measure过程,所以本篇文章大幅笔地分析measure过程,相对讲得比较详细,文章也比较长,如果你对View的绘制还不是很懂,对measure过程掌握得不是很深刻,那么耐心点,看完这篇文章,相信你会有所收获的。
78 2
|
2月前
|
存储 缓存 Java
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
34 0
|
2月前
|
Java Android开发 Kotlin
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
25 0
|
3月前
|
Java Android开发
android 设置系统时间的流程
android 设置系统时间的方法
250 2
|
4月前
|
ARouter IDE 开发工具
Android面试题之App的启动流程和启动速度优化
App启动流程概括: 当用户点击App图标,Launcher通过Binder IPC请求system_server启动Activity。system_server指示Zygote fork新进程,接着App进程向system_server申请启动Activity。经过Binder通信,Activity创建并回调生命周期方法。启动状态分为冷启动、温启动和热启动,其中冷启动耗时最长。优化技巧包括异步初始化、避免主线程I/O、类加载优化和简化布局。
63 3
Android面试题之App的启动流程和启动速度优化
|
4月前
|
安全 网络协议 算法
Android网络基础面试题之HTTPS的工作流程和原理
HTTPS简述 HTTPS基于TCP 443端口,通过CA证书确保服务器身份,使用DH算法协商对称密钥进行加密通信。流程包括TCP握手、证书验证(公钥解密,哈希对比)和数据加密传输(随机数加密,预主密钥,对称加密)。特点是安全但慢,易受特定攻击,且依赖可信的CA。每次请求可能复用Session ID以减少握手。
54 2