【源码剖析】Launcher 8.0 源码 (2) --- Launcher 启动流程 第一步(1)之LauncherAppState 对象创建简述

从综述将启动流程拆分成7步,其中第一步,重点是通过手机的硬件来获取信息。

关于第一步在oncreate中的源码如下:

@Override
protected void onCreate(Bundle savedInstanceState) {

if (mLauncherCallbacks != null) {
    mLauncherCallbacks.preOnCreate();
}
super.onCreate(savedInstanceState);
LauncherAppState app = LauncherAppState.getInstance(this);

 

从源码看,重点就做了一件事情,创建LauncherAppState 对象。

这是因为在Launcher的启动流程中,手机硬件参数获取不是在Launcher.java这个类中完成。

 

LauncherAppState.getInstance(this) 这段代码是初始化一个LauncherAppState的对象app,其初始化方法是通过一个静态方法getInstance来创建,创建的时候需要传入Launcher对象作为参数,那么说明在LauncherAppState中会用到Launcher的对象,下面详细看getInstance方法。

  源码如下:

public static LauncherAppState getInstance(final Context context) {
    if (INSTANCE == null) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            INSTANCE = new LauncherAppState(context.getApplicationContext());
        } else {
            try {
                return new MainThreadExecutor().submit(new Callable() {
                    @Override
                    public LauncherAppState call() throws Exception {
                        return LauncherAppState.getInstance(context);
                    }
                }).get();
            } catch (InterruptedException|ExecutionException e) {
                throw new RuntimeException(e);
            }
        }
    }
    return INSTANCE;
}

 

这是一个设计模式中的单例模式。其实一开始从方法名getInstance就可以看出这是单例模式。单例模式的核心是创建且只创建一次对象,于是整个代码的核心是创建对象

“new LauncherAppState(context.getApplicationContext())”

单例模式是只创建一次对象的,如果是第一次调用,则会创建这个对象,并赋值给INSTANCE ,而如果不是第一次调用,这个时候INSTANCE 已经被赋值对象了,就将这个对象交给调用者。

这里有个细节,本方法使用了context.getApplicationContext(),这说明之前后面需要使用的不是activity的对象,而只需要获取其context。在Android使用过程中,如果我们需要获取的是context而不是activity本身,都建议使用activity的getApplicationContext()方法,防止内存泄露,增加代码健壮性。

 

我们所关注LauncherAppState的源码如下:

 

private LauncherAppState(Context context) {
    mContext = context;

    mInvariantDeviceProfile = new InvariantDeviceProfile(mContext);
    mIconCache = new IconCache(mContext, mInvariantDeviceProfile);
    mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);

    mModel = new LauncherModel(this, mIconCache,
            Utilities.getOverrideObject(AppFilter.class, mContext, R.string.app_filter_class));

    LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel);

    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_LOCALE_CHANGED);
    filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
    filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
    filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
    filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
    filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
      if (Utilities.ATLEAST_NOUGAT) {
        filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
    }
    mContext.registerReceiver(mModel, filter);
    UserManagerCompat.getInstance(mContext).enableAndResetCache();
    new ConfigMonitor(mContext).register();
}

 

在这构造器中,最关键的是InvariantDeviceProfile类,因为这个方便是获取硬件参数的类。也是第一步当中最重要的行为。

而后还创建了mIconCache 、mWidgetCache 、mModel 三个对象,创建这些对象是因为在本类中会用到这写对象所以创建。这三个类对于Launcher启动流程的第一步不是强相关的。

比如LauncherModer的创建,主要是为了注册广播,这个属于Launcher的后台部分。之前提到过Launcher三部分:启动,触摸,后台。本文只讲启动部分,启动部分包含了所有的UI。

以上就是第一步的整体流程,除开在java中的代码,还有一个res中的xml文件作为配合,也是第一步,通过手机硬件获取对应参数的关键。

 

是名为device_profiles的xml文件,此文件是由很多profile文件组成。

其中一个profile如下。

    launcher:name="Nexus S"
    launcher:minWidthDps="296"
    launcher:minHeightDps="491.33"
    launcher:numRows="4"
    launcher:numColumns="4"
    launcher:numFolderRows="4"
    launcher:numFolderColumns="4"
    launcher:minAllAppsPredictionColumns="4"
    launcher:iconSize="48"
    launcher:iconTextSize="13.0"
    launcher:numHotseatIcons="5"
    launcher:hotseatIconSize="48"
    launcher:defaultLayoutId="@xml/default_workspace_4x4"
    />

 

device_profiles.xml中一共有11个profile,也只包含11个profile没有其他内容。

 

示例中的profile就是google官方给出的一个模型。

这个模型有物理的最小长度,最小宽度,布局的行列数,文件夹的行列数,allapp的行列数,图标大小,图标名字代销,快捷栏图标大小,快捷栏图标数,以及默认布局文件。

 

在这个参数中,其中涉及手机尺寸的是物理的最小长度,最小宽度即minWidthDps和minHeightDps 。

在11个模型中

长宽从launcher:minWidthDps="255" launcher:minHeightDps="300"

到launcher:minWidthDps="1527"launcher:minHeightDps="2527"

这从小屏按键机,到20寸的大型显示器都包含了。

 

整个Launcher能够实现的Launcher布局模式只能够按照这11中模型来做,实际的手机和模型做比较,选取最接近的模型来作为本手机的实际模型。

 

整个代码在mInvariantDeviceProfile 的构造器中完成,将在后面继续讲解

你可能感兴趣的:(源码剖析)