Launcher3的启动流程(一)

(系列文章点这里)

Launcher3作为一个用户经常使用,常驻内容的应用,运行时维护着许多信息,而这些信息都需要在开机的时候加载完,今天就来分析下Launcher3是怎样一步一步启动的。

如果你手里还没有源码,请点击这里,编译并让他在你的手机上运行。然后打开Eclipse,一步步跟着走。

在启动Launcher这个Activity之前,先看下桌面的LauncherApplication吧,任何一个组件(Component)启动之前都会启动他的。代码只有寥寥几行。

LauncherAppState我们在上一篇博客里面说过,主要用来初始化对象,注册广播接收器等等,这些都在他的构造方法里面完成了。这里监听的广播有应用的安装、卸载和更新,SD卡上应用的可用或不可用,地区变化和配置变化等等。接收应用安装更新什么的广播,都是为了方便实时更新桌面上的图标,如果用豌豆荚安装了应用会在桌面上马上显示出来,这都是这些个广播接收器在发挥作用。需要注意的是贯穿始终的LauncherModel就是在这个构造方法里初始化的。

准备工作做好了,就开始启动Launcher Activity。Activity的启动从onCreate开始查找。
(更多…)

继续阅读 →

Launcher3中的常用类

(系列文章点这里)

除了上一篇博客中布局需要用到的几个类,还有一些类是我们在代码中随时可能遇见的。

LauncherModel:从名字我们可以看出他跟数据有关系的,保存了桌面运行时的状态信息,也提供了读写数据库的API,他有一个内部类LoaderTask,桌面启动从数据库中读取数据并把图标和小工具添加上去的时候用的就是他。

BubblTextView:图标都是基于他,不过奇怪的是,他是继承自TextView,我之前一直以为是一个线性布局,上面放图片,下面放文字。

DragController:DragLayer只是一个ViewGroup,具体的拖拽的处理都放到了DragController中。

LauncherAppState:单例模式,主要在启动的时候用,他初始化了一些对象,并且注册了广播监听器和ContentObserver。

DragView:在拖动图标的时候跟随手指移动的View就是他。

DragSource,DropTarget:跟拖拽相关的接口,DragSource表示图标从哪里被拖出来,DropTarget表示图标可以被拖到哪里去。

Folder:文件夹打开时候那个view。

FolderIcon: 文件夹图标。

LauncherProvider:数据库类,Launcher3使用了SQLite,数据库文件保存在/data/data/包名/databases/launcher.db 下,有兴趣的同学可以把这个东西拷贝出来,用SQLite的工具看看里面都是怎么保存的。

ItemInfo:运行时保存了桌面上每个项目的信息,包括图标在第几屏,第几行第几列,高度宽度等信息,每一个ItemInfo对象都对应着数据库中的一条记录。在Launcher3源码路径下,会有很多以Info结尾的类,这些类都是ItemInfo的子类,具体代表了桌面上的某个项目。比如说FolderIcon和FolderInfo是对应的,BubbleTextView和ShortcutInfo是对应的,AppWidgetHostView和LauncherAppWidgetInfo是对应的。有了对应关系,可以这样通过view获取ItemInfo对象:

ItemInfo info = (ItemInfo)bubbletextview.getTag();

这样这里的info其实就是ShortcutInfo对象了。

之后我会专门写一篇讲解数据库、ItemInfo相关的博文,敬请期待

继续阅读 →

Launcher3 的布局和结构

(系列文章点这里)

首先你需要去 这里 下载下Launcher3的源码。这个是我从android源码里面拿出来的,修改删掉了一些东西,方便在eclipse上运行,你可以直接在手机上运行,有了代码和apk再来看说明,心理会很踏实的。

Launcher3其实最主要的是一个Activity,基本上所有的操作都集中在这个Activity上,在Launcher.java 当中,setContentView的参数是R.layout.launcher,我们暂时只研究下桌面竖屏的情况,相关源码在res/layout-port/launcher.xml。

请左手拿着你运行着launcher3的手机,右手打开launcher.xml,布局的最外面是一个FrameLayout,紧紧地包围了一个叫DragLayer的ViewGroup,他继承自FrameLayout,主要功能就是处理拖拽事件,当你在拖拽一个图标的时候,就是一个view放到了DragLayer里面,跟随你的手在移动。

下面在你的手机屏幕上左右滑,有好几屏,这个能滑的东西叫做Workspace,在布局文件里面可以看到的,Workspace能算是Launcher3代码里代码量前三的吧,他的父类的父类是PagedView,一个用来处理左右滑动的ViewGroup。那么Workspace里面可以滑动的单独一屏叫什么呢? 布局文件里面似乎没有写,其实是CellLayout,他负责的是图标和小部件的显示和整齐摆放。

接下来看你在滑动屏幕的时候看见下方有个指示器,告诉你桌面现在有几屏,当前是在哪一屏上。这个东西叫做PageIndicator,从名字就可以看出意义了。还有最下面的4个固定不动的图标,和中间一个Button显示所有应用,这整个叫做Hotseat,用来放置比较常用的应用,比如拨号,短信,相机等等。
(更多…)

继续阅读 →

android触摸事件处理流程

(系列文章点这里)

最近在工作中,经常需要处理触摸事件,但是有时候会出现一些奇怪的bug,比如有时候会检测不到ACTION_MOVE和ACTION_UP,我决定下决心写个测试的小程序,来研究一个触摸事件从上往下是怎么传递和处理的。

先说下大概的流程吧,这个应该在很多博客中都有讲解:当一个事件来临的时候,会先传递给最外层的ViewGroup(比如LinearLayout,FrameLayout),如果这个ViewGroup没有去拦截这个事件的话,才会给传递给下层的ViewGroup或者View。如果被拦截掉的话,它会自己去处理这个事件,这个ViewGroup内的View将无法得知上层发生了什么。

ViewGroup的拦截事件的函数为

public boolean onInterceptTouchEvent(MotionEvent ev)

onInterceptTouchEvent的参数ev就是一个触摸事件,可以从ev获取到事件的坐标,类型,当前屏幕上点的个数等等。通常我们在继承ViewGroup的时候都会重写这个方法,判断目前需不需要拦截,即返回true还是false。返回true的时候表明事件不再往下传了,否则就往下传。那返回true的时候怎么处理呢?
(更多…)

继续阅读 →

Android 4.4 Launcher3桌面源码分析

由于工作的原因,对Android的桌面有了一些了解。之前一段时间对桌面的构成十分模糊,最近看代码该代码发现渐渐有了感觉,所以准备写一系列分析安卓桌面的文章。

市面上有很多桌面产品,比如91桌面,go桌面,小米桌面等等,虽说千差万别,但都完成了桌面的基本任务,比如说组织图标,拖动图标,滑动页面,显示小工具等等功能。桌面跟其他Android App很大的不同是,他只有一个Activity,但是这个Activity却十分复杂,用几个自定义View把Android的触摸事件的处理玩儿的眼花缭乱,没有长时间的折腾是很难熟悉的。
(更多…)

继续阅读 →