Launcher的含义、如何启动的详解
当我们手指触摸屏幕上指定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的含义、如何启动的详解相关推荐
- Android9.0 Launcher启动Activity详解(一)
一.开始 Launcher中点击应用图标启动Activity,其开始方法是 public boolean startActivitySafely(View v, Intent intent, Item ...
- Android系统(187)---最易懂的Activity启动模式详解
Android基础:最易懂的Activity启动模式详解 前言 Android基础中,Activity的启动模式非常重要 本文将全面介绍 Activity的启动模式 目录 目录 1. 定义 即Acti ...
- 【正点原子Linux连载】第三十二章 U-Boot启动流程详解 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
- idea 执行java maven,IDEA的run maven方式启动步骤详解
安装jetty插件 1. 找到Plugins,查找jetty插件,安装"IDEA Jetty Runner",安装好后重启IDEA 安装插件:Maven Helper 方法同Jet ...
- sshd系统自带启动脚本详解
SSH 为 Secure Shell 的缩写.sshd服务是linux系统中最经常使用的服务之一.由于其规避了明文传送口令.内容本文及中间人***的安全隐患,因此经常作为远程管理系统的首选方案.虽然各 ...
- Linux开启动过程详解
Linux开启动过程详解 Linux启动过程 前言: Linux是一种自由和开放源代码的类UNIX操作系统.该操作系统的内核由林纳斯·托瓦兹在1991年10月5日首次发布.在加上用户空间的应用程序之后 ...
- centos7 启动流程图_Linux启动过程详解
Linux启动过程详解 作者:江远航 一.启动流程图如下 图1 Linux启动流程图 BIOS ---> MBR ---> Kernel---> Init 二.Linux启动顺序 一 ...
- SpringBatch 配置并行启动Job详解 (八)
文章目录 一.创建并行job 前言:在日常业务中可能需要job并行执行,SpringBatch支持job并行步执行,并且配置简单. 代码已上传GitHub上面地址:https://github.com ...
- Activity的启动模式详解
Activity的启动模式详解 Activity有四种载入模式:standard(默认), singleTop, singleTask和 singleInstance. (1).standard(默认 ...
- U-Boot启动流程详解
参考:U-Boot顶层目录链接脚本文件(u-boot.lds)介绍 作者:一只青木呀 发布时间: 2020-10-23 13:52:23 网址:https://blog.csdn.net/weixin ...
最新文章
- Gin 框架学习笔记(02)— 参数自动绑定到结构体
- java后台图片的上传预览接口 IO流
- Linux-sort排序
- grub4dos命令引导自定义映像_DOS的常用命令二
- 日历对象导哪个包_java.util的的Date类和Calendar类
- 软件工程---16.基于构件的软件工程
- Python html 代码转成 word(docx)
- 期刊投稿状态_追踪期刊在线系统投稿状态(十七)
- JAVA 泛型 入门
- php如何优化递归函数,php递归函数怎么用才有效?php递归函数典型例子
- 特征向量的归一化方法
- 【c4d学习笔记】对称方向不对的问题
- 使用putty进行Linux串口连接
- 自动切换输入法 for Mac(输入法辅助工具)
- 用计算机弹奏天下,天下手游大荒怪题答题器 大荒怪题题库及答案大全
- 手机上不了电信宽带连接服务器无响应怎么办,当网页都打不开该怎么办?
- 科大奥锐干涉法测微小量实验的数据,大学物理实验教材课后思考题答案 (4)
- 【概率入门(一)】排列组合?我们再来捋一捋
- 如何为豆瓣FM写一个chrome的歌词插件
- 设计模式超简单的解释!