当我们手指触摸屏幕上指定App图标Logo的时候,App就由Launcher开始启动了。
Launcher到底是一个概念呢?

Launcher本质上也是一个应用程序,和我们的App一样,也是继承自Activity

packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

public final class Launcher extends Activityimplements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,View.OnTouchListener {}

Launcher类中实现了点击OnClickListener、长按OnLongClickListener等回调接口,来接收用户的输入操作。

比如,我们点击一个图标,是怎么打来应用呢?
 通过捕捉图标对应的点击事件操作,然后调用startActivity()发送对应的Intent请求,Launcher就是这么做的。

那么到底是处理的哪个对象的点击事件呢?既然Launcher是App,并且有界面,那么肯定有布局文件,是的,我找到了布局文件launcher.xml

<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"android:id="@+id/launcher"><com.android.launcher2.DragLayerandroid:id="@+id/drag_layer"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"><!-- Keep these behind the workspace so that they are not visible whenwe go into AllApps -->//底部操作栏和上面图标布局的分割线<includeandroid:id="@+id/dock_divider"layout="@layout/workspace_divider"android:layout_marginBottom="@dimen/button_bar_height"android:layout_gravity="bottom" />//页面指示器<includeandroid:id="@+id/paged_view_indicator"layout="@layout/scroll_indicator"android:layout_gravity="bottom"android:layout_marginBottom="@dimen/button_bar_height" /><!-- The workspace contains 5 screens of cells -->//包含了5个屏幕的单元格。类似于手机首页 底部打电话 短信 浏览器 通讯录等底部按钮<com.android.launcher2.Workspaceandroid:id="@+id/workspace"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingStart="@dimen/workspace_left_padding"android:paddingEnd="@dimen/workspace_right_padding"android:paddingTop="@dimen/workspace_top_padding"android:paddingBottom="@dimen/workspace_bottom_padding"launcher:defaultScreen="2"launcher:cellCountX="@integer/cell_count_x"launcher:cellCountY="@integer/cell_count_y"launcher:pageSpacing="@dimen/workspace_page_spacing"launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right"><include android:id="@+id/cell1" layout="@layout/workspace_screen" /><include android:id="@+id/cell2" layout="@layout/workspace_screen" /><include android:id="@+id/cell3" layout="@layout/workspace_screen" /><include android:id="@+id/cell4" layout="@layout/workspace_screen" /><include android:id="@+id/cell5" layout="@layout/workspace_screen" /></com.android.launcher2.Workspace>...ignore some code...</com.android.launcher2.DragLayer>
</FrameLayout>

从上面这些我们应该可以看出一些东西来:Launcher大量使用include标签来实现界面的复用,而且定义了很多的自定义控件实现界面效果,dock_divider从布局的参数声明上可以猜出,是底部操作栏和上面图标布局的分割线,而paged_view_indicator则是页面指示器,和App首次进入的引导页下面的界面引导是一样的道理。当然,我们最关心的是Workspace这个布局,因为注释里面说在这里面包含了5个屏幕的单元格,想必你也猜到了,这个就是在首页存放我们图标的那五个界面(不同的ROM会做不同的DIY,数量不固定)。

workspace_screen布局:

<com.android.launcher2.CellLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingStart="@dimen/cell_layout_left_padding"android:paddingEnd="@dimen/cell_layout_right_padding"android:paddingTop="@dimen/cell_layout_top_padding"android:paddingBottom="@dimen/cell_layout_bottom_padding"android:hapticFeedbackEnabled="false"launcher:cellWidth="@dimen/workspace_cell_width"launcher:cellHeight="@dimen/workspace_cell_height"launcher:widthGap="@dimen/workspace_width_gap"launcher:heightGap="@dimen/workspace_height_gap"launcher:maxGap="@dimen/workspace_max_gap" />

系统界面布局分析:
1.底部快捷入口View:
 就一个CellLayout自定义布局,那么我们就可以猜到了,既然可以存放图标,那么这个自定义的布局很有可能是继承自ViewGroup或者是其子类,实际上,CellLayout确实是继承自ViewGroup。在CellLayout里面,只放了一个子View,那就是ShortcutAndWidgetContainer。从名字也可以看出来,ShortcutAndWidgetContainer这个类就是用来存放快捷图标和Widget小部件的,那么里面放的是什么对象呢?

在桌面上的图标,使用的是BubbleTextView对象,这个对象在TextView的基础之上,添加了一些特效,比如你长按移动图标的时候,图标位置会出现一个背景(不同版本的效果不同),所以我们找到BubbleTextView对象的点击事件,就可以找到Launcher如何开启一个App了。

2.程序列表中的点击:
除了桌面上图标之外,在程序列表中点击图标,也可以开启对应的程序。这里的图标使用的不是BubbleTextView对象,而是PagedViewIcon对象,我们如果找到它的点击事件,就也可以找到Launcher如何开启一个App。

底部快捷的BubbleTextView对象的点击事件在哪里呢?我来告诉你:在Launcher.onClick(View v)里面。

   /*** Launches the intent referred by the clicked shortcut*/public void onClick(View v) {...ignore some code...Object tag = v.getTag();if (tag instanceof ShortcutInfo) {// Open shortcutfinal Intent intent = ((ShortcutInfo) tag).intent;int[] pos = new int[2];v.getLocationOnScreen(pos);intent.setSourceBounds(new Rect(pos[0], pos[1],pos[0] + v.getWidth(), pos[1] + v.getHeight()));//开始开启Activity咯~boolean success = startActivitySafely(v, intent, tag);if (success && v instanceof BubbleTextView) {mWaitingForResume = (BubbleTextView) v;mWaitingForResume.setStayPressed(true);}} else if (tag instanceof FolderInfo) {//如果点击的是图标文件夹,就打开文件夹if (v instanceof FolderIcon) {FolderIcon fi = (FolderIcon) v;handleFolderClick(fi);}} else if (v == mAllAppsButton) {...ignore some code...}}

程序列表中的点击:

程序列表界面使用的是AppsCustomizePagedView对象,所以我在这个类里面找到了onClick(View v)。

com.android.launcher2.AppsCustomizePagedView.java

/*** The Apps/Customize page that displays all the applications, widgets, and shortcuts.*/
public class AppsCustomizePagedView extends PagedViewWithDraggableItems implementsView.OnClickListener, View.OnKeyListener, DragSource,PagedViewIcon.PressedCallback, PagedViewWidget.ShortPressListener,LauncherTransitionable {@Overridepublic void onClick(View v) {...ignore some code...if (v instanceof PagedViewIcon) {mLauncher.updateWallpaperVisibility(true);mLauncher.startActivitySafely(v, appInfo.intent, appInfo);} else if (v instanceof PagedViewWidget) {...ignore some code..}}      }

两种方式,殊途同归!

不管从哪里点击图标,调用的都是Launcher.startActivitySafely()方法。

下面一起来看一下Launcher.startActivitySafely()的流程

 boolean startActivitySafely(View v, Intent intent, Object tag) {boolean success = false;try {success = startActivity(v, intent, tag);} catch (ActivityNotFoundException e) {Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);}return success;}boolean startActivity(View v, Intent intent, Object tag) {//Activity会添加到一个新的Task栈intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);try {boolean useLaunchAnimation = (v != null) &&!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);if (useLaunchAnimation) {if (user == null || user.equals(android.os.Process.myUserHandle())) {startActivity(intent, opts.toBundle());} else {launcherApps.startMainActivity(intent.getComponent(), user,intent.getSourceBounds(),opts.toBundle());}} else {if (user == null || user.equals(android.os.Process.myUserHandle())) {startActivity(intent);} else {launcherApps.startMainActivity(intent.getComponent(), user,intent.getSourceBounds(), null);}}return true;} catch (SecurityException e) {...}return false;}//实际调用的是 startActivityForResult方法@Overridepublic void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {startActivityForResult(intent, -1, options);} else {// Note we want to go through this call for compatibility with// applications that may have overridden the method.startActivityForResult(intent, -1);}}

所以,Launcher开启一个App,其实和我们在Activity中直接startActivity()基本一样,都是调用了Activity.startActivityForResult()。

Launcher的含义、如何启动的详解相关推荐

  1. Android9.0 Launcher启动Activity详解(一)

    一.开始 Launcher中点击应用图标启动Activity,其开始方法是 public boolean startActivitySafely(View v, Intent intent, Item ...

  2. Android系统(187)---最易懂的Activity启动模式详解

    Android基础:最易懂的Activity启动模式详解 前言 Android基础中,Activity的启动模式非常重要 本文将全面介绍 Activity的启动模式 目录 目录 1. 定义 即Acti ...

  3. 【正点原子Linux连载】第三十二章 U-Boot启动流程详解 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  4. idea 执行java maven,IDEA的run maven方式启动步骤详解

    安装jetty插件 1. 找到Plugins,查找jetty插件,安装"IDEA Jetty Runner",安装好后重启IDEA 安装插件:Maven Helper 方法同Jet ...

  5. sshd系统自带启动脚本详解

    SSH 为 Secure Shell 的缩写.sshd服务是linux系统中最经常使用的服务之一.由于其规避了明文传送口令.内容本文及中间人***的安全隐患,因此经常作为远程管理系统的首选方案.虽然各 ...

  6. Linux开启动过程详解

    Linux开启动过程详解 Linux启动过程 前言: Linux是一种自由和开放源代码的类UNIX操作系统.该操作系统的内核由林纳斯·托瓦兹在1991年10月5日首次发布.在加上用户空间的应用程序之后 ...

  7. centos7 启动流程图_Linux启动过程详解

    Linux启动过程详解 作者:江远航 一.启动流程图如下 图1 Linux启动流程图 BIOS ---> MBR ---> Kernel---> Init 二.Linux启动顺序 一 ...

  8. SpringBatch 配置并行启动Job详解 (八)

    文章目录 一.创建并行job 前言:在日常业务中可能需要job并行执行,SpringBatch支持job并行步执行,并且配置简单. 代码已上传GitHub上面地址:https://github.com ...

  9. Activity的启动模式详解

    Activity的启动模式详解 Activity有四种载入模式:standard(默认), singleTop, singleTask和 singleInstance. (1).standard(默认 ...

  10. U-Boot启动流程详解

    参考:U-Boot顶层目录链接脚本文件(u-boot.lds)介绍 作者:一只青木呀 发布时间: 2020-10-23 13:52:23 网址:https://blog.csdn.net/weixin ...

最新文章

  1. Gin 框架学习笔记(02)— 参数自动绑定到结构体
  2. java后台图片的上传预览接口 IO流
  3. Linux-sort排序
  4. grub4dos命令引导自定义映像_DOS的常用命令二
  5. 日历对象导哪个包_java.util的的Date类和Calendar类
  6. 软件工程---16.基于构件的软件工程
  7. Python html 代码转成 word(docx)
  8. 期刊投稿状态_追踪期刊在线系统投稿状态(十七)
  9. JAVA 泛型 入门
  10. php如何优化递归函数,php递归函数怎么用才有效?php递归函数典型例子
  11. 特征向量的归一化方法
  12. 【c4d学习笔记】对称方向不对的问题
  13. 使用putty进行Linux串口连接
  14. 自动切换输入法 for Mac(输入法辅助工具)
  15. 用计算机弹奏天下,天下手游大荒怪题答题器 大荒怪题题库及答案大全
  16. 手机上不了电信宽带连接服务器无响应怎么办,当网页都打不开该怎么办?
  17. 科大奥锐干涉法测微小量实验的数据,大学物理实验教材课后思考题答案 (4)
  18. 【概率入门(一)】排列组合?我们再来捋一捋
  19. 如何为豆瓣FM写一个chrome的歌词插件
  20. 设计模式超简单的解释!

热门文章

  1. java的几个生命周期(部分简单总结)
  2. 北邮+校徽+logo+矢量图+透明
  3. 将txt文件数据转成bin文件.
  4. ☼ 什么是DST以及它对IT设备、软件的影响 ☼
  5. CUDA笔记2-循环展开
  6. 计算机组成原理真数,对数函数基础解答题(含答案).doc
  7. 04 Python基本数据类型
  8. Python实现BBS自动登录并发帖
  9. Spring+SpringMVC+Hibernate实现投票/调查问卷网站
  10. ChatGPT惨遭围剿?多国封杀、近万人联名抵制……