前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android之Launcher介绍(二)

Android之Launcher介绍(二)

作者头像
李小白是一只喵
发布2021-03-17 09:43:25
6220
发布2021-03-17 09:43:25
举报
文章被收录于专栏:算法微时光算法微时光

Launcher启动

上文讲到Launcher的Activity被启动。

接下来就执行Activity的生命周期。

代码Launcher.java中:

代码语言:javascript
复制
    protected void onCreate(Bundle savedInstanceState) {
        ……
        super.onCreate(savedInstanceState);

        // 调用LauncherAppState实例
        LauncherAppState app = LauncherAppState.getInstance(this);

        mDeviceProfile = app.getInvariantDeviceProfile().getDeviceProfile(this);
        if (isInMultiWindowModeCompat()) {
            Display display = getWindowManager().getDefaultDisplay();
            Point mwSize = new Point();
            display.getSize(mwSize);
            mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize);
        }

        mSharedPrefs = Utilities.getPrefs(this);
        mIsSafeModeEnabled = getPackageManager().isSafeMode();
        // 将Launcher传入LauncherAppState实例
        mModel = app.setLauncher(this);
        mModelWriter = mModel.getWriter(mDeviceProfile.isVerticalBarLayout());
        mIconCache = app.getIconCache();
        mAccessibilityDelegate = new LauncherAccessibilityDelegate(this);

        ……
    }

进入LauncherAppState.java 中看一下。 getInstance函数和LauncherAppState的构造函数:

代码语言:javascript
复制
    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<LauncherAppState>() {
                        @Override
                        public LauncherAppState call() throws Exception {
                            return LauncherAppState.getInstance(context);
                        }
                    }).get();
                } catch (InterruptedException|ExecutionException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return INSTANCE;
    }

    private LauncherAppState(Context context) {
        ……
        mInvariantDeviceProfile = new InvariantDeviceProfile(mContext);
        mIconCache = new IconCache(mContext, mInvariantDeviceProfile);
        mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);

        // 创建LauncherModel对象
        mModel = new LauncherModel(this, mIconCache,
                Utilities.getOverrideObject(AppFilter.class, mContext, R.string.app_filter_class));

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

setLauncher函数:

代码语言:javascript
复制
    LauncherModel setLauncher(Launcher launcher) {
        getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
        mModel.initialize(launcher);
        return mModel;
    }

setLauncherhan函数中调用了LauncherModel对象的initialize函数,传入的变量就是Launcer对象。

进入LauncherModel看下:

代码语言:javascript
复制
    public void initialize(Callbacks callbacks) {
        synchronized (mLock) {
            Preconditions.assertUIThread();
            // Remove any queued UI runnables
            mHandler.cancelAll();
            mCallbacks = new WeakReference<>(callbacks);
        }
    }

因为Launcer类是继承了Callbacks类的,所以这里将Launcer封装成了一个弱引用对象。

继续看Launcher的onCreate函数:

代码语言:javascript
复制
    protected void onCreate(Bundle savedInstanceState) {
        ……
        super.onCreate(savedInstanceState);

        // 将Launcher传入LauncherAppState实例
        mModel = app.setLauncher(this);
        mModelWriter = mModel.getWriter(mDeviceProfile.isVerticalBarLayout());
        ……

        if (!mModel.startLoader(currentScreen)) {
            mDragLayer.setAlpha(0);
        } else {
            mWorkspace.setCurrentPage(currentScreen);

            setWorkspaceLoading(true);
        }
    }

会获取LauncherModel后,执行startLoader函数, 不过之前先看一段代码:

代码语言:javascript
复制
    @Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
    static {
        sWorkerThread.start();
    }
    @Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());

这段代码就是创建一个具有消息循环的HandlerThread,主要用来处理消息。

startLoader函数:

代码语言:javascript
复制
    public boolean startLoader(int synchronousBindPage) {
        InstallShortcutReceiver.enableInstallQueue();
        synchronized (mLock) {
             if (mCallbacks != null && mCallbacks.get() != null) {
                final Callbacks oldCallbacks = mCallbacks.get();
                runOnMainThread(new Runnable() {
                    public void run() {
                        oldCallbacks.clearPendingBinds();
                    }
                });
                
                stopLoaderLocked();
                // 执行LoaderTask函数
                mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage);
                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
                        && mModelLoaded && !mIsLoaderTaskRunning) {
                    mLoaderTask.runBindSynchronousPage(synchronousBindPage);
                    return true;
                } else {
                    sWorkerThread.setPriority(Thread.NORM_PRIORITY);
                    // 将mLoaderTask传入到消息线程中处理
                    sWorker.post(mLoaderTask);
                }
            }
        }
        return false;
    }

当消息被执行时候会调用LoaderTask类的run函数:

代码语言:javascript
复制
private class LoaderTask implements Runnable {
        ……
        public void run() {
            synchronized (mLock) {
                if (mStopped) {
                    return;
                }
                mIsLoaderTaskRunning = true;
            }

            try {
                if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace");
                // Set to false in bindWorkspace()
                mIsLoadingAndBindingWorkspace = true;
                // 加载桌面
                loadWorkspace();

                verifyNotStopped();
                if (DEBUG_LOADERS) Log.d(TAG, "step 1.2: bind workspace workspace");
                // 绑定桌面
                bindWorkspace(mPageToBindFirst);

                if (DEBUG_LOADERS) Log.d(TAG, "step 1 completed, wait for idle");
                waitForIdle();
                verifyNotStopped();
                if (DEBUG_LOADERS) Log.d(TAG, "step 2.1: loading all apps");
                // 加载所有的app
                loadAllApps();

                verifyNotStopped();
                if (DEBUG_LOADERS) Log.d(TAG, "step 2.2: Update icon cache");
                updateIconCache();

                if (DEBUG_LOADERS) Log.d(TAG, "step 2 completed, wait for idle");
                waitForIdle();
                verifyNotStopped();

                if (DEBUG_LOADERS) Log.d(TAG, "step 3.1: loading deep shortcuts");
                loadDeepShortcuts();

                verifyNotStopped();
                if (DEBUG_LOADERS) Log.d(TAG, "step 3.2: bind deep shortcuts");
                bindDeepShortcuts();

                if (DEBUG_LOADERS) Log.d(TAG, "step 3 completed, wait for idle");
                waitForIdle();
                verifyNotStopped();

                if (DEBUG_LOADERS) Log.d(TAG, "step 4.1: loading widgets");
                refreshAndBindWidgetsAndShortcuts(getCallback(), false /* bindFirst */,
                        null /* packageUser */);

                synchronized (mLock) {
                    mModelLoaded = true;
                    mHasLoaderCompletedOnce = true;
                }
            } catch (CancellationException e) {
              // Loader stopped, ignore
            } finally {
                mContext = null;

                synchronized (mLock) {
                    if (mLoaderTask == this) {
                        mLoaderTask = null;
                    }
                    mIsLoaderTaskRunning = false;
                }
            }
        }
        ……
    }

其中会执行加载桌面和加载app。

之后再loadAllApps函数中:

代码语言:javascript
复制
        private void loadAllApps() {
            ……
            mHandler.post(new Runnable() {
                public void run() {

                    final long bindTime = SystemClock.uptimeMillis();
                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                    if (callbacks != null) {
                        // 绑定apps
                        callbacks.bindAllApplications(added);
                        if (DEBUG_LOADERS) {
                            Log.d(TAG, "bound " + added.size() + " apps in "
                                    + (SystemClock.uptimeMillis() - bindTime) + "ms");
                        }
                    } else {
                        Log.i(TAG, "not binding apps: no Launcher activity");
                    }
                }
            });
            ……
        }

因为callbacks就是之前传进来的Launcher对象,所以这里就将app传给了Launcher对象。

bindAllApplication函数中:

代码语言:javascript
复制
    public void bindAllApplications(final ArrayList<AppInfo> apps) {
        if (waitUntilResume(mBindAllApplicationsRunnable, true)) {
            mTmpAppsList = apps;
            return;
        }

        if (mAppsView != null) {
            mAppsView.setApps(apps);
        }
        if (mLauncherCallbacks != null) {
            mLauncherCallbacks.bindAllApplications(apps);
        }
    }

这里就将app信息传递给了mAppsView界面。这样基本就将app显示出来了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Launcher启动
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档