《Android群英传》要点摘录

  1. 第1章 Android 体系与系统架构
  2. 第2章 Android 开发工具新接触
  3. 第3章 Android控件架构与自定义控件详解
  4. 第4章 ListView 使用技巧
  5. 第5章 Android Scroll 分析
  6. 第6章 Android 绘图机制与处理技巧
  7. 第7章 Android 动画机制与使用技巧
  8. 第8章 Activity 与 Activity 调用栈分析
  9. 第9章 Android 系统信息与安全机制
  10. 第10章 Android 性能优化
  11. 第11章 搭建云端服务器
  12. 第12章 Android 5.X 新特性详解

第1章 Android 体系与系统架构

1、Android 底层通过最快的 C 语言保证效率,上层使用 Java 简单、快速进行开发。(2页)
2、从宏观上讲,Android 是一个移动操作系统。Android 系统架构大致分为了四层,即 Linux 内核层、库和运行时、Framework 层和应用层。(2页)
3、Linux 层包含了 Android 系统的核心服务,包括硬件驱动、进程管理、安全系统等等。(3页)
4、Dalvik 包含了一整套的 Android 运行环境虚拟机,每个 App 都会分配 Dalvik 虚拟机来保证互相之间不受干扰,并保持独立。它的特点是在运行时编译。在 Android 5.X 版本开始,ART(Android runtime)模式已经取代了 Dalvik,ART 采用的是安装时就进行编译,以后运行时就不用编译了。(3页)
5、Android 的 App 组件架构,通常就是我们所说的 Android 四大组件,指的是 Activity、BroadCast Receiver、ContentProvider 和 Service,它们是组成一个 Android App 的最基本元素。(4页)
6、Activity 作为人机交互的第一界面,负责向用户展示信息和处理结果,而这些信息的来源,可以是通过资源获取,也可以通过 Content Provider 来获取其他应用的信息,或是 Service 从后台计算、下载、处理的结果,当然也可以是通过 BroadCast Receiver 获取到的广播信息。(5页)
7、Android 系统还提供了一个信使——Intent,作为信息传递的载体。组件与组件之间通过 Intent 来通信、传递信息、交换数据,正是通过这样一种方式,四大组件形成了各自独立而又紧密联系的关系,让整个 Android 系统 “活” 了起来。(5页)
8、在程序中,上下文可以理解为当前对象在程序中所处的一个环境,一个与系统交互的过程。(5页)
9、Android 系统的上下文对象,即在 Context 中,为我们封装了这样一个 “语境”。Activity、Service、Application 都是继承自 Context。(5页)
10、Android 应用程序会在如下所示的几个时间点创建应用上下文 Context:创建 Application、创建 Activity、创建 Service。(5页)
11、创建 Context 的时机就是在创建 Context 的实现类的时候。当应用程序第一次启动时,Android 系统都会创建一个 Application 对象,同时创建 Application Context,所有的组件都共同拥有这样一个 Context 对象,这个应用上下文对象贯穿整个应用进程的生命周期,为应用全局提供了功能和环境支持。而创建 Activity 和 Service 组件时,系统也会给它们提供运行的上下文环境,即创建 Activity 实例、Service 实例的 Context 对象。(5页)
12、Android 源代码的目录中包含了 Android 系统所有的源代码,从底层驱动到上层应用,Android 系统对所有文件都进行了详细管理。而在手机中,Android 系统的目录与源代码的目录并不是一一对应的,而是与源代码编译之后,与打包生成的 Image 文件的结构相同。(6页)
13、Eclipse、Android Studio 这些属于开发IDE(集成开发环境),它体现的是一种简化计算机与开发者的交互。很多事情,IDE 是无法完成的,比如自动化编译、定制编译、版本控制、自动测试等。(7页)
14、一个像 Android 这样的大型工程,它的源文件不计其数,不同的功能、模块,按类型分别放置在不同的目录中,这些模块通常会有一个叫 Makefile 的文件来进行管理。它定义了一系列的规则来指定模块,哪些文件需要编译,以及这些文件该按照怎样的顺序去编译。甚至,它还可以配置更复杂的功能操作,比如定义编译规则,打包规则等,因为 Makefile 就像一个 shell 脚本,不仅可以使用自己的语法,也能调用操作系统的命令。Makefile 最大的好处就是自动化编译,同时还可以做到可控制的编译,Android 通过 Makefile 来描述 Android 各个组件间的联系并指导它们进行自动化编译。Makefile 的语法,指定了各个源代码该如何连接并生成相应的可执行程序。Android 源代码目录结构,每个目录中,还会包含更多的目录,而它的每一个最小的功能单位的目录下,都会有一个 Makefile 文件,这样每一级向上,通过这样一个个 Makefile 文件,就把整个源代码有条不紊地联系在一起了。(7页)
15、Android Studio 中的 Project 就相当于 Eclipse 里面的 Workspace,而 Android Studio 中的 Module 就相当于 Eclipse 里面的 Project。(12页)

第2章 Android 开发工具新接触

1、ADB 常用命令:(25页)

  • 显示系统中全部 Android 平台:android list targets
  • 安装 Apk 程序之 Install:adb install -r 应用程序.apk
  • 安装 Apk 程序之 Push:adb push <local><remote>

2、Adb Install 是将 Apk 安装到 data/data 目录下,作为普通的用户应用程序。而 Adb Push 则不是安装命令,它是将一个文件写入手机存储系统。因此,只要拥有相应的权限,就可以把任何 Apk 放到任何目录下,甚至是放到 System 目录下,成为一个系统应用程序。(25页)
3、Adb Push 不仅可以安装 Apk,它最大的用处还是向手机写入文件。(26页)

  • 向手机写入文件:adb push <local><remote>
  • 从手机获取文件:adb pull <remote><local>

第3章 Android控件架构与自定义控件详解

1、Android 中的每个控件都会在界面中占得一块矩形的区域,而在 Android 中,控件大致被分为两类,即 ViewGroup 控件与 View 控件。ViewGroup 控件作为父控件可以包含多个 View 控件,并管理其包含的 View 控件。通过 ViewGroup,整个界面上的控件形成了一个树形结构,这也就是我们常说的控件树,上层控件负责下层子控件的测量与绘制,并传递交互事件。通常在 Activity 中使用的 findViewById() 方法,就是在控件树中以树的深度优先遍历来查找对应元素。在每棵控件树的顶部,都有一个 ViewParent 对象,这就是整棵树的控制核心,所有的交互管理事件都由它来统一调度和分配,从而可以对整个试图进行整体控制。(33页)
2、通常情况下,在 Activity 中使用 setContentView() 方法来设置一个布局,在调用该方法后,布局内容才真正地显示出来。(33页)
3、每个 Activity 都包含一个 Window 对象,在 Android 中 Window 对象通常由 PhoneWindow 来实现。PhoneWindow 将一个 DecorView 设置为整个应用窗口的根 View。DecorView 作为窗口界面的顶层视图,封装了一些窗口操作的通用方法。可以说,DecorView 将要显示的具体内容呈现在了 PhoneWindow 上,这里面的所有 View 的监听事件,都通过 WindowManagerService 来进行接收,并通过 Activity 对象来回调相应的 onClickListener。在显示上,它将屏幕分成两部分,一个是 TitleView,另一个是 ContentView。(33页)
4、在代码中,当程序在 onCreate() 方法中调用 setContentView() 方法后,ActivityMangerService 会回调 onResume() 方法,此时系统才会把整个 DecorView 添加到 PhoneWindow 中,并让其显示出来,从而最终完成界面的绘制。(34页)
4、Android 系统在绘制 View 前,必须对 View 进行测量,即告诉系统该画一个多大的 View。这个过程在 onMeasure() 方法中进行。(34页)
5、Android 系统给我们提供了一个设计短小精悍却功能强大的类—— MeasureSpec 类,通过它来帮助我们测量 View。MeasureSpec 是一个 32 位的 int 值,其中高 2 位为测量的模式,低 30 位为测量的大小,在计算中使用位运算的原因是为了提高并优化效率。(35页)
6、测量的模式可以为以下三种:(35页)

  • EXACTLY:即精确值模式,当我们将控件的 layout_width 属性或 layout_height 属性指定为具体数值或者指定为 match_parent 属性时(占据父 View 的大小),系统使用的是 EXACTLY 模式。
  • AT_MOST:即最大值模式,当控件的 layout_width 属性或 layout_height 属性指定为 wrap_content 时,控件大小一般随着控件的子控件或内容的变化而变化,此时控件的尺寸只要不超过父控件允许的最大尺寸即可。
  • UNSPECIFIED:它不指定其大小测量模式,View 想多大就多大,通常情况下在绘制自定义 View 时才会使用。

7、View 类默认的 onMeasure() 方法只支持 EXACTLY 模式,所以如果在自定义控件的时候不重写 onMeasure() 方法的话,就只能使用 EXACTLY 模式。控件可以响应你指定的具体宽高值或者是 match_parent 属性。而如果要让自定义 View 支持 wrap_content 属性,那么就必须重写 onMeasure() 方法来指定 wrap_content 时的大小。(35页)
8、通过 MeasureSpec 这一个类,我们就获取了 View 的测量模式和 View 想要绘制的大小。有了这些信息,我们就可以控制 View 最后显示的大小。(35页)
9、当测量好了一个 View 之后,我们就可以简单地重写 onDraw() 方法,并在 Canvas 对象上来绘制所需要的图形。要想在 Android 的界面中绘制相应的图像,就必须在 Canvas 上进行绘制。Canvas 就像是一个画板,使用 Paint 就可以在上面作画了。通常需要通过继承 View 并重写它的 onDraw() 方法来完成绘图。(37页)
10、ViewGroup 会去管理其子 View,其中一个管理项目就是负责子 View 的显示大小。当 ViewGroup 的大小为 wrap_content 时,ViewGroup 就需要对子 View 进行遍历,以便获得所有子 View 的大小,从而来决定自己的大小。而在其他模式下则会通过具体的指定值来设置自身的大小。(38页)
11、ViewGroup 在测量时通过遍历所有子 View,从而调用子 View 的 Measure 方法来获得每一个子 View 的测量结果。当子 View 测量完毕后,就需要将子 View 放到合适的位置,这个过程就是 View 的 Layout 过程。ViewGroup 在执行 Layout 过程时,同样是使用遍历来调用子 View 的 Layout 方法,并指定其具体显示的位置,从而来决定其布局位置。(39页)
12、在自定义 ViewGroup 时,通常会去重写 onLayout() 方法来控制其子 View 显示位置的逻辑。同样,如果需要支持 wrap_content 属性,那么它还必须重写 onMeasure() 方法。(39页)
13、ViewGroup 通常情况下不需要绘制,因为它本身就没有需要绘制的东西,如果不是指定了 ViewGroup 的背景颜色,那么 ViewGroup 的 onDraw() 方法都不会被调用。但是,ViewGroup 会使用 dispatchDraw() 方法来绘制其子 View,其过程同样是通过遍历所有子 View,并调用子 View 的绘制方法来完成绘制工作。(39页)
14、了解 Android 系统自定义 View 的过程,可以帮助我们了解系统的绘图机制。(40页)
15、在自定义 View 时,我们通常会去重写 onDraw() 方法来绘制 View 的显示内容。如果该 View 还需要使用 wrap_content 属性,那么还必须重写 onMeasure() 方法。另外,通过自定义 attrs 属性,还可以设置新的属性配置值。(40页)
16、通常情况下,有以下三种方法来实现自定义的控件:对现有控件进行拓展、通过组合来实现新的控件和重写 View 来实现全新的控件。(40页)
17、一般来说,我们可以在 onDraw() 方法中对原生控件行为进行拓展。(40页)
18、创建复合控件可以很好地创建出具有重用功能的控件集合。这种方式通常需要继承一个合适的 ViewGroup,再给它添加指定功能的控件,从而组合成新的复合控件。通过这种方式创建的控件,我们一般会给它指定一些可配置的属性,让它具有更强的拓展性。(43页)
19、使用自定义的 View 与系统原生的 View 最大的区别就是在申明控件时,需要指定完整的包名,而在引用自定义的属性时,需要使用自定义的 xmlns 名字。(50页)
20、触摸事件就是捕获触摸屏幕后产生的事件。当点击一个按钮时,通常就会产生两个或者三个事件——按钮按下,这是事件一;如果不小心滑动一点,这就是事件二;当手抬起,这是事件三。(59页)

第4章 ListView 使用技巧

1、ListView——列表,它作为一个非常重要的显示方式,不管是在 Web 中还是移动平台中,都是一个非常好的、不可或缺的展示信息的工具。(65页)
2、ViewHolder 模式是提高 ListView 效率的一个很重要的方法。ViewHolder 模式充分利用了 ListView 的试图缓存机制,避免了每次在调用 getView() 的时候都去通过 findViewById() 实例化控件。据测试,使用 ViewHolder 将提高 50% 以上的效率。使用 ViewHolder 模式来优化 ListView 非常简单,只需要在自定义 Adapter 中定义一个内部类 ViewHolder,并将布局中的控件作为成员变量。接下来,只要在 getView() 方法中通过视图缓存机制来重用以缓存即可。(66页)
3、ListView 的各个项目之间,可以通过设置分割线来进行区分,系统提供了 divider 和 dividerHeight 这样两个属性来帮助我们实现这一功能。通过这两个属性,也可以控制 ListView 之间的分割线和它的高度。当然,分割线不仅仅可以设置为一个颜色,同样也可以设置为一个图片资源。(68页)
4、默认的 ListView 在滚动时,在右边会显示滚动条,指示当前滑动的位置,我们可以设置 scrollbars 属性,控制 ListView 的滚动条状态。特别地,当设置 scrollbars 属性为 none 的时候,ListView 滚动或者不滚动,就都不会出现滚动条了。(68页)
5、当点击 ListView 中的一项时,系统默认会出现一个点击效果,在 Android 5.X 上是一个波纹效果,而在 Android 5.X 之下的版本则是一个改变背景颜色的效果,但可以通过修改 listSelector 属性来取消掉点击后的回馈效果。(68页)
6、ListView 的滑动监听,是 ListView 中最重要的技巧,很多重写的 ListView,基本上都是在滑动事件的处理上下功夫,通过判断滑动事件进行不同的逻辑处理。而为了更加精确地监听滑动事件,开发者通常还需要使用 GestureDetector 手势识别、VelocityTracker 滑动速度检测等辅助类来完成更好的监听。有两种监听 ListView 滑动事件的方法,一个是通过 OnTouchListener 来实现监听,另一个是使用 OnScrollListener 来实现监听。(72页)
7、OnTouchListener 是 View 中的监听事件,通过监听 ACTION_DOWN、ACTION_MOVE、ACTION_UP 这三个事件发生时的坐标,就可以根据坐标判断用户滑动的方向,并在不同的事件中进行相应的逻辑处理。(72页)
8、OnScrollListener 是 AbsListView 中的监听事件,它封装了很多与 ListView 相关的信息,使用起来也更加灵活。(72页)
9、OnScrollListener 中有两个回调方法——onScrollStateChanged() 和 onScroll()。(73页)
    onScrollStateChanged() 方法根据它的参数 scrollState 来决定其回调的次数,scrollState 有以下三种模式:

  • OnScrollListener.SCROLL_STATE_IDLE:滚动停止时。
  • OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:正在滚动时。
  • OnScrollListener.SCROLL_STATE_FLING:手指抛动时,即手指用力滑动,在离开后 ListView 由于惯性继续滑动的状态。

当用户没有做手指抛动的状态时,这个方法只会回调 2 次,否则会回调 3 次,差别就是手指抛动的这个状态。通常情况下,我们会在这个方法中通过不同的状态来设置一些标志 Flag,来区分不同的滑动状态,供其他方法处理。
    onScroll() 方法在 ListView 滚动时会一直回调,而方法中的后三个 int 类型的参数,则非常精确地显示了当前 ListView 滚动的状态。

  • firstVisibleItem:当前能看见的第一个 Item 的 ID(从 0 开始)。
  • visibleItemCount:当前能看见的 Item 总数。
  • totalItemCount:整个 ListView 的 Item 总数。

需要注意的是,当前能看见的 Item 数,包括没有显示完整的 Item,即显示一小半的 Item 也包括在内了。
10、通常情况下,如果要动态地改变点击 Item 的布局来达到一个 Focus 的效果,一般有两种方法。一种是将两种布局写在一起,通过控制布局的显示、隐藏,来达到切换布局的效果;另一种则是在 getView() 的时候,通过判断来选择加载不同的布局。(85页)

第5章 Android Scroll 分析

1、滑动一个 View,本质上来说就是移动一个 View。改变其当前所处的位置,它的原理与动画效果的实现非常相似,都是通过不断地改变 View 的坐标来实现这一效果。所以,要实现 View 的滑动,就必须监听用户触摸的事件,并根据事件传入的坐标,动态且不断地改变 View 的坐标,从而实现 View 跟随用户触摸的滑动而滑动。(88页)
2、在 Android 中,将屏幕最左上角的顶点作为 Android 坐标系的原点,从这个点向右是 X 轴正方向,从这个点向下是 Y 轴正方向。(88页)
3、系统提供了 getLocationOnScreen(intlocation[]) 这样的方法来获取 Android 坐标系中点的位置,即该试图左上角在 Android 坐标系中的坐标。另外,在触控事件中使用 getRawX()、getRawY() 方法所获得的坐标同样是 Android 坐标系中的坐标。(88页)
4、Android 中的视图坐标系描述了子视图在父视图中的位置关系。与 Android 坐标系类似,视图坐标系同样是以原点向右为 X 轴正方向,以原点向下为 Y 轴正方向,只不过在视图坐标系中,原点不再是 Android 坐标系中的屏幕最左上角,而是以父视图左上角为坐标原点。在触控事件中,通过 getX()、getY() 所获得的坐标就是视图坐标系中的坐标。(88页)
5、通常情况下,我们会在 onTouchEvent(MotionEvent event) 方法中通过 event.getAction() 方法来获取触控事件的类型,并使用 switch-case 方法来进行筛选。(89页)
6、在 Android 中,系统提供了非常多的方法来获取坐标值、相对距离等。(90页)

这些方法可以分成如下两个类别:

  • View 提供的获取坐标方法

    • getTop():获取到的是 View 自身的顶边到其父布局顶边的距离
    • getLeft():获取到的是 View 自身的左边到其父布局左边的距离
    • getRight():获取到的是 View 自身的右边到其父布局左边的距离
    • getBottom():获取到的是 View 自身的底边到其父布局顶边的距离
  • MotionEvent 提供的方法

    • getX():获取点击事件距离控件左边的距离,即视图坐标
    • getY():获取点击事件距离控件顶边的距离,即视图坐标
    • getRawX():获取点击事件距离整个屏幕左边的距离,即绝对坐标
    • getRawY():获取点击事件距离整个屏幕顶边的距离,即绝对坐标

7、当触摸 View 时,系统记下当前触摸点坐标;当手指移动时,系统记下移动后的触摸点坐标,从而获取到相对于前一次坐标点的偏移量,并通过偏移量来修改 View 的坐标,这样不断重复,从而实现滑动过程。(91页)
8、在一个 View 中,系统提供了 scrollTo、scrollBy 两种方式来改变一个 View 的位置。scrollTo(x,y) 表示移动到一个具体的坐标点 (x,y),而 scrollBy(dx,dy) 表示移动的增量为 dx、dy。(94页)
9、如果在 ViewGroup 中使用 scrollTo、scrollBy 方法,那么移动的将是所有子 View,但如果在 View 中使用,那么移动的将是 View 的内容。(95页)
10、如果将 scrollBy 中的参数 dx 和 dy 设置为正数,那么 content 将向坐标轴负方向移动;如果将 scrollBy 中的参数 dx 和 dy 设置为负数,那么 content 将向坐标轴正方向移动。(95页)
11、Google 建议使用自然的过度动画来实现移动效果。通过 Scroller 类可以实现平滑移动的效果,而不再是瞬间完成的移动。一般情况下,使用 Scroller 类需要如下三个步骤:(96页)

  • 初始化 Scroller
  • 重写 computeScroll() 方法,实现模拟滑动
  • startScroll 开启模拟过程

12、Google 在其 support 库中为我们提供了 DrawerLayout 和 SlidingPaneLayout 两个布局来帮助开发者实现侧边栏滑动的效果。通过 ViewDragHelper,基本可以实现各种不同的滑动、拖放需求。(98页)

第6章 Android 绘图机制与处理技巧

1、一块屏幕通常具有以下几个参数:(107页)

  • 屏幕大小:指屏幕对角线的长度,通常使用 “寸” 来度量,例如 4.7寸手机、5.5 寸手机等。
  • 分辨率:分辨率是指手机屏幕的像素点个数,例如 720 × 1280 就是指屏幕的分辨率,指宽有 720 个像素点,而高有 1280 个像素点。
  • PPI:每英寸像素(Pixels Per Inch)又被称为 DPI(Dots Per Inch)。它是由对角线的像素点数除以屏幕的大小得到的,通常达到 400 PPI 就已经是非常高的屏幕密度了。

2、标准DPI(107页)

密度 ldpi mdpi hdpi xhdpi xxhdpi
密度值 120 160 240 320 480
分辨率 240×320 320×480 480×800 720×1280 1080×1920

3、由于各种屏幕密度的不同,导致同样像素大小的长度,在不同密度的屏幕上显示长度不同。因为相同长度的屏幕,高密度的屏幕包含更多的像素点。Android 系统使用 mdpi 即密度值为 160 的屏幕作为标准,在这个屏幕上 1 px = 1 dp。(107页)
4、各个密度值的换算公式:在 mdpi 中 1 dp = 1 px,在 hdpi 中 1 dp = 1.5 px,在 xhdpi 中 1 dp = 2 px,在 xxhdpi 中 1 dp = 3 px。各个分辨率直接的换算比例,即 ldpi:mdpi:hdpi:xhdpi:xxhdpi = 3:4:6:8:12。(108页)
5、Selector 的作用在于帮助开发者实现静态绘图中的事件反馈,通过给不同的事件设置不同的图像,从而在程序中根据用户输入,返回不同的效果。(116页)
6、Android 对于图片的处理,最常使用到的数据结构是位图——Bitmap,它包含了一张图片所有的数据。整个图片都是由点阵和颜色值组成的,所谓点阵就是一个包含像素的矩阵,每一个元素对应着图片的一个像素。而颜色值——ARGB,分别对应透明度、红、绿、蓝这四个通道分量,它们共同决定了每个像素点显示的颜色。(122页)
7、在色彩处理中,通常使用以下三个角度来描述一个图像:(122页)

  • 色调——物体传播的颜色
  • 饱和度——颜色的纯度,从 0(灰)到100%(饱和)来进行描述
  • 亮度——颜色的相对明暗程度

8、在 Android 中,系统使用一个颜色矩阵——ColorMatrix,来处理图像的这些色彩效果。Android 中的颜色矩阵是一个 4×5 的数字矩阵,它用来对图片的色彩进行处理。而对于每个像素点,都有一个颜色分量矩阵用来保存颜色的 RGBA 值。(122页)
9、Android 系统提供了 setRotate(int axis,float degree) 来帮助我们设置颜色的色调。第一个参数,系统分别使用 0、1、2来代表 Red、Green、Blue 三种颜色的处理;而第二个参数,就是需要处理的值。Android 系统提供了 setSaturation(float sat) 方法来设置颜色的饱和度,参数即代表设置颜色饱和度的值。当饱和度为 0 时,图像就变成灰度图像了。当三原色以相同的比例进行混合的时候,就会显示出白色。系统也正是使用这个原理来改变一个图像的亮度。当亮度为 0 时,图像就变为全黑了。(125页)
10、作为更加精确的图像处理方式,可以通过改变每个像素点的具体 ARGB 值,来达到处理一张图像效果的目的。要注意的是,传递进来的原始图片是不能修改的(mutable),一般根据原始图片生成一张新的图片来修改。(134页)
11、在 Android 中,系统提供了 Bitmap.getPixels() 方法来帮我们提取整个 Bitmap 中的像素点,并保存到一个数组中。(134页)
12、图像的变形处理通常包含以下四类基本变换:(138页)

  • Translate——平移变换
  • Rotate——旋转变换
  • Scale——缩放变换
  • Skew——错切变换

13、如果以任意点 O 为旋转中心来进行旋转变换,通常需要以下三个步骤:(139页)

  • 将坐标原点平移到 O 点
  • 使用以坐标原点为中心的旋转方法进行旋转变换
  • 将坐标原点还原

14、一个像素点是不存在缩放的概念的,但是由于图像是由很多个像素点组成的,如果将每个点的坐标都进行相同比例的缩放,最终就会形成让整个图像缩放的效果。(139页)
15、错切变换(skew)在数学上又称为 Shear mapping(可译为 “剪切变换”)或者 Transvection(缩并),它是一种比较特殊的线性变换。错切变换的效果就是让所有点的 x 坐标(或者 y 坐标)保持不变,而对应的 y 坐标(或者 x 坐标)则按比例发生平移,且平移的大小和该点到 x 轴(或 y 轴)的垂直距离成正比。错切变换通常包含两种——水平错切与垂直错切。(140页)
16、View 通过刷新来重绘视图,Android 系统通过发出 VSYNC 信号来进行屏幕的重绘,刷新的间隔时间为 16ms。如果在 16ms 内 View 完成了你所需要执行的所有操作,那么用户在视觉上,就不会产生卡顿的感觉;而如果执行的操作逻辑太多,特别是需要频繁刷新的界面上,例如游戏界面,那么就会不断阻塞主线程,从而导致画面卡顿。(155页)
17、SurfaceView 与 View 的区别:(155页)

  • View 主要适用于主动更新的情况下,而 SurfaceView 主要适用于被动更新,例如频繁地刷新。
  • View 在主线程中对画面进行刷新,而 SurfaceView 通常会通过一个子线程来进行页面的刷新。
  • View 在绘图时没有使用双缓冲机制,而 SurfaceView 在底层实现机制中就已经实现了双缓冲机制。

如果自定义 View 需要频繁刷新,或者刷新时数据处理量比较大,那么就可以考虑使用 SurfaceView 来取代 View。

第7章 Android 动画机制与使用技巧

1、Animation 框架定义了透明度、旋转、缩放和位移几种常见的动画,而且控制的是整个 View,实现原理是每次绘制视图时 View 所在的 ViewGroup 中的 drawChild 函数获取该 View 的 Animation 的 Transformation 值,然后调用 canvas.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧。如果动画没有完成,就继续调用 invalidate() 函数,启动下次绘制来驱动动画,从而完成整个动画的绘制。(163页)
2、视图动画使用简单,效果丰富,它提供了 AlphaAnimation、RotateAnimation、TranslateAnimation、ScaleAnimation 四种动画方式,并提供了 AnimationSet 动画集合,混合使用多种动画。相比属性动画,视图动画的一个非常大的缺陷就是不具备交互性,当某个元素发生视图动画后,其响应事件的位置还依然在动画前的地方,所以视图动画只能做普通的动画效果,避免交互的发生。但是它的优点也非常明显,即效率比较高且使用方便。(163页)
3、在 Animator 框架中使用最多的就是 AnimatorSet 和 ObjectAnimator 配合,使用 ObjectAnimator 进行更精细化控制,只控制一个对象的一个属性值,而使用多个 ObjectAnimator 组合到 AnimatorSet 形成一个动画。而且 ObjectAnimator 能够自动驱动,可以调用 setFrameDelay(longframeDelay) 设置动画帧之间的间隙时间,调整帧率,减少动画过程中频繁绘制界面,而在不影响动画效果的前提下减少 CPU 资源消耗。最重要的是,属性动画通过调用属性的 get、set 方法来真实地控制了一个 View 的属性值,因此强大的属性动画框架,基本可以实现所有的动画效果。(165页)
4、ObjectAnimator 是属性动画框架中最重要的实行类,创建一个 ObjectAnimator 只需通过他的静态工厂类直接返回一个 ObjectAnimator 对象。参数包括一个对象和对象的属性名字,但这个属性必须有 get 和 set 函数,内部会通过 Java 反射机制来调用 set 函数修改对象属性值。(166页)
5、在属性动画中,如果针对同一个对象的多个属性,要同时作用多种动画,可以使用 PropertyValuesHolder 来实现。(168页)
6、一个完整的动画具有 Start、Repeat、End、Cancel 四个过程。(168页)
7、在 Android 3.0 之后,Google 给 View 增加了 animate 方法来直接驱动属性动画。(170页)
8、布局动画是指作用在 ViewGroup 上,给 ViewGroup 增加 View 时添加一个动画过渡效果。(171页)
9、插值器是动画中一个非常重要的概念,通过插值器(Interpolators),可以定义动画变换速率,其作用主要是控制目标变量的变化值进行对应的变化。同样的一个动画变换起始值,在不同的插值器作用下,每个单位时间内所达到的变化值也是不一样的。(171页)
10、Google 在 Android 5.X 中增加了对 SVG 矢量图形的支持,这对于创建新的高效率动画具有非常重大的意义。(175页)
11、什么是 SVG:(175页)

  • 可伸缩矢量图形(Scalable Vector Graphics)
  • 定义用于网络的基于矢量的图形
  • 使用 XML 格式定义图形
  • 图像在放大或改变尺寸的情况下其图形质量不会有所损失
  • 万维网联盟的标准
  • 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体

12、Bitmap(位图)通过在每个像素点上存储色彩信息来表达图像,而 SVG 是一个绘图标准。与 Bitmap 对比,SVG 最大的优点就是放大不会失真。而且 Bitmap 需要为不同分辨率设计多套图标,而矢量图则不需要。(175页)
13、SVG 常用指令:(176页)

  • L:绘制直线的指令是 “L”,代表从当前点绘制直线到给定点。“L” 之后的参数是一个点坐标,如 “L 200 400” 绘制直线。同时,还可以使用 “H” 和 “V”指令来绘制水平、竖直线,后面的参数是 x 坐标(H 指令)或 y 坐标(V 指令)。
  • M:M 指令类似 Android 绘图中 path 类的 moveTo 方法,即代表将画笔移动到某一点,但并不发生绘制动作。
  • A:A 指令用来绘制一段弧线,且允许弧线不闭合。可以把 A 指令绘制的弧线想象成是椭圆的某一段。

14、path 是 SVG 树形结构中的最小单位,而通过 Group 可以将不同的 path 进行组合。(177页)

第8章 Activity 与 Activity 调用栈分析

1、Activity 是与用户交互的第一接口,它提供了一个用户完成指令的窗口。当开发者创建 Activity 之后,通过调用 setContentView(View) 方法来给该 Activity 指定一个显示的界面,并以此为基础提供给用户交互的接口。系统采用 Activity 栈的方式来管理 Activity。(196页)
2、Activity 一个最大的特点就是拥有多种形态,它可以在多种形态间进行切换,以此来控制自己的生命周期。(196页)

  • Active/Running:这时候,Activity 处于 Activity 栈的最顶层,可见,并与用户进行交互。
  • Paused:当 Activity 失去焦点,被一个新的非全屏的 Activity 或者一个透明的 Activity 放置在栈顶时,Activity 就转化为 Paused 形态。但它只是失去了与用户交互的能力,所有状态信息、成员变量都还保持着,只有在系统内存极地的情况下,才会被系统回收掉。
  • Stopped:如果一个 Activity 被另一个 Activity 完全覆盖,那么 Activity 就会进入 Stopped 形态。此时,它不再可见,但却依然保持了所有状态信息和成员变量。
  • Killed:当 Activity 被系统回收掉或者 Activity 从来没有创建过,Activity 就处于 Killed 状态。

3、Activity 的生命周期状态:(197页)

  • Resumed:这个状态,也就是 Active/Running 形态,此时,Activity 处于 Activity 栈顶,处理用户的交互。
  • Paused:当 Activity 的一部分被挡住的时候进入这个状态,这个状态下的 Activity 不会接收用户输入。
  • Stopped:当 Activity 完全被覆盖时进入这个状态,此时 Activity 不可见,仅在后台运行。

4、Activity 的启动与销毁过程:在系统调用 onCreate() 之后,就会马上调用 onStart(),然后继续调用 onResume() 以进入 Resumed 状态,最后就会停在 Resumed 状态,完成启动。系统会调用 onDestroy() 来结束一个 Activity 的声明周期让它回到 Killed 状态。(198页)

  • onCreate():创建基本的 UI 元素。
  • onPause() 与 onStop():清除 Activity 的资源,避免浪费。
  • onDestroy():因为引用会在 Activity 销毁的时候销毁,而线程不会,所以清除开启的线程。

5、Activity 的暂停与恢复过程:当栈顶的 Activity 部分不可见后,就会导致 Activity 进入 Paused 形态,此时就会调用 onPause() 方法,当结束阻塞后,就会调用 onResume() 方法来恢复到 Resumed 形态。(198页)

  • onPause():释放系统资源,如 Camera、sensor、receivers。
  • onResume():需要重新初始化在 onPause() 方法中释放的资源。

6、Activity 的停止过程:栈顶的 Activity 部分不可见时,实际上后续会有两种可能,从部分不可见到可见,也就是恢复过程;从部分不可见到完全不可见,也就是停止过程。系统在当前 Activity 不可见的时候,总会调用 onPause() 方法。每当 Activity 由不可见到可见时,都会调用 onStart() 方法。(198页)
7、Activity 的重新创建过程:如果你的系统长时间处于 Stopped 形态而且此时系统需要更多内存或者系统内存极为紧张时,系统就会回收你的 Activity,而此时系统为了补偿你,会将 Activity 状态通过 onSaveInstanceState() 方法保存到 Bundle 对象中,当然你也可以增加额外的键值对存入 Bundle 对象以保存这些状态。当你需要重新创建这些 Activity 的时候,保存的 Bundle 对象就会传递到 Activity 的 onRestoreInstanceState() 方法与 onCreate() 方法中,这也就是 onCreate() 方法中参数——Bundle savedInstanceState 的来源。不过需要注意的是,onSaveInstanceState() 方法并不是每次当 Activity 离开前台时都会调用的,如果用户使用 finish() 方法结束了 Activity,则不会调用。而且 Android 系统已经默认实现了控件的状态缓存,以此来减少开发者需要实现的缓存逻辑。(199页)
8、一个 Android 应用程序功能通常会被拆分为多个 Activity,而各个 Activity 之间通过 Intent 进行连接,而 Android 系统,通过栈结构来保存整个 App 的 Activity,栈底的元素是整个任务栈的发起者。(200页)
9、当一个 App 启动时,如果当前环境中不存在该 App 的任务栈,那么系统就会创建一个任务栈。此后,这个 App 所启动的 Activity 都将在这个任务栈中被管理,这个栈也被称为一个 Task,即表示若干个 Activity 的集合,它们组合在一起形成一个 Task。另外,需要特别注意的是,一个 Task 中的 Activity 可以来自不同的 App,同一个 App 的 Activity 也可能不在一个 Task 中。(200页)
10、栈结构是后进先出(Last In First Out)的线性表。根据 Activity 在当前栈结构中的位置,来决定该 Activity 的状态。当一个 Activity 启动了另一个 Activity 的时候,新启动的 Activity 就会置于任务栈的顶端,并处于活动状态,而启动它的 Activity 虽然功成身退,但依然保存在任务栈中,处于停止状态,当用户按下返回键或者调用 finish() 方法时,系统会移除顶部 Activity,让后面的 Activity 恢复活动状态。(200页)
11、在 AndroidManifest 文件中,Activity 一共有四种启动模式:standard、singleTop、singleTask、singleInstance。(201页)

  • standard:默认的启动模式,如果不指定 Activity 的启动模式,则使用这种方式启动 Activity。这种启动模式每次都会创建新的实例,每次点击 standard 模式创建 Activity 后,都会创建新的 MainActivity 覆盖在原 Activity 上。
  • singleTop:如果指定启动 Activity 为 singleTop 模式,那么在启动时,系统会判断当前栈顶 Activity 是不是要启动的 Activity,如果是则不创建新的 Activity 而直接引用这个 Activity;如果不是则创建新的 Activity。这种启动模式虽然不会创建新的实例,但是系统仍然会在 Activity 启动时调用 onNewIntent() 方法。
  • singleTask:singleTop 是检测栈顶元素是否是需要启动的 Activity,而 singleTask 是检测整个 Activity 栈中是否存在当前需要启动的 Activity。如果存在,则将该 Activity 置于栈顶,并将该 Activity 以上的 Activity 都销毁。不过这里是指在同一个 App 在启动这个 singleTask 的 Activity,如果是其他程序以 singleTask 模式来启动这个 Activity,那么它将创建一个新的任务栈。有一点需要注意的是,如果启动的模式为 singleTask 的 Activity 已经在后台一个任务栈中了,那么启动后,后台的这个任务栈将一起被切换到前台。
  • singleInstance:申明为 singleInstance 的 Activity 会出现在一个新的任务栈中,而且该任务栈中只存在这一个 Activity。

如果在一个 singleTop 或者 singleInstance 的 ActivityA 中通过 startActivityForResult() 方法来启动另一个 ActivityB,那么系统将直接返回 Activity.RESULT_CANCELED 而不会再去等待返回。这是由于系统在 Framework 层做了对这两种启动模式的限制,因为 Android 开发者认为,不同 Task 之间,默认是不能传递数据的,如果一定要传递,那就只能通过 Intent 来绑定数据。
12、通常情况下,可以在 AndroidManifest 文件中的<activity>标签中使用以下几种属性来清理任务栈。(203页)

  • clearTaskOnLaunch:在每次返回该 Activity 时,都将该 Activity 之上的所有 Activity 都清除。通过这个属性,可以让这个 Task 每次在初始化的时候,都只有这一个 Activity。
  • finishOnTaskLaunch:通过这个属性,当离开这个 Activity 所处的 Task,那么用户再返回时,该 Activity 就会被 finish 掉。
  • alwaysRetainTaskState:如果将 Activity 的这个属性设置为 True,那么该 Activity 所在的 Task 将不接受任何清理命令,一直保持当前 Task 状态。

第9章 Android 系统信息与安全机制

1、要获取系统的配置信息,通常可以从以下两个方面获取:android.os.Build 和 SystemProperty。(206页)
2、PackageManager 重点在于获得应用的包信息,而 ActivityManager 重点在于获得在运行的应用程序信息。(215页)
3、在系统初始化的时候,PackageManager 的底层实现类 PackageManagerService 会去扫描系统中的一些特定的目录,并解析其中的 Apk 文件。同时,Android 把它获得的应用信息,保存在 XML 文件中,做成一个应用的花名册,当系统中的 Apk 安装、删除、升级时,它也会被更新。这个小册子,就是位于 /data/system/ 目录下的——package.xml 文件。(218页)
4、permissions 标签定义了目前系统中的所有权限,并分为两类:系统定义的(package 属性为 Android)和 Apk 定义的(package 属性为 Apk 的包名)。(218页)
5、Android 开发者在 Android 系统中建立了五道防线来保护 Android 系统的安全。(220页)

  • 第一道防线:代码安全机制——代码混淆 proguard。由于 Java 语言的特殊性,即使是编译成 Apk 的应用程序也存在被反编译的风险。而 proguard 则是在代码层面上对 Android 应用程序 App 的第一重保护,它可以混淆关键代码、替换命名让破坏者阅读困难,同时也可以压缩代码、优化编译后的 Java 字节码。
  • 第二道防线:应用接入权限机制——AndroidManifest 文件权限声明、权限检查机制。任何应用程序 App 在使用 Android 受限资源的时候,都需要显示向系统声明所需要的权限,只有当一个应用 App 具有相应的权限,才能在申请受限资源的时候,通过权限机制的检查并使用系统的 Binder 对象完成对系统服务的调用。
  • 第三道防线:应用签名机制——数字证书。Android 中所有的 App 都会有一个数字证书,这就是 App 的签名,数字证书用于保护 App 的作者对其 App 的信任关系,只有拥有相同数字签名的 App,才会在升级时被认为是同一 App。
  • 第四道防线:Linux 内核层安全机制——Uid、访问权限控制。Android 本质是基于 Linux 内核开发的,所以 Android 同样继承了 Linux 的安全特性。通常情况下,只有 System、root 用户才有权限访问到系统文件,而一般用户无法访问。
  • 第五道防线:Android 虚拟机沙箱机制——沙箱隔离。Android 的 App 运行在虚拟机中,因此才有沙箱机制,可以让应用之间相互隔离。通常情况下,不同的应用之间不能互相访问,每个 App 都有与之对应的 Uid,每个 App 也运行在单独的虚拟机中,与其他应用完全隔离。在实现安全机制的基础上,也让应用之间能够互不影响,即使一个应用奔溃,也不会导致其他应用异常。

6、Android 系统安全隐患:代码漏洞、Root 风险、安全机制不健全、用户安全意识。Root 权限是指 Android 的系统管理员权限,具有 Root 权限的用户可以访问和修改手机中几乎所有的文件。(222页)
7、Android 与 iOS 系统一个非常显著的区别就是一个是开放系统一个是封闭系统,开放的好处是技术进步快、产品丰富,封闭的好处是安全性高、可控性高。(223页)
8、Android 的应用程序 Apk 文件,说到底也是一个压缩文件,那么可以通过解压缩,获得里面的文件内容。(223页)
9、为了能够对编译好的 Java Class 文件进行一些保护,通常会使用 ProGuard 来对 Apk 进行混淆处理,用无意义的字母来重命名类、字段、方法和属性。当然,ProGuard 不仅仅可以用来混淆代码,还可以删除无用的类、字段、方法和属性,以及删除没用的注释,最大限度地优化字节码文件。(226页)

第10章 Android 性能优化

1、对复杂的应用进行性能优化是创建高质量的应用程序的基础。(227页)
2、系统在渲染 UI 界面的时候将消耗大量的资源,一个好的 UI 不仅应该具有良好的视觉效果,更应该具有良好的使用体验。(228页)
3、人眼所感觉的流畅画面,需要画面的帧数达到 40 帧每秒到 60 帧每秒。在 Android 中,系统通过 VSYNC 信号触发对 UI 的渲染、重绘,其间隔时间是 16ms。这个 16ms 其实就是 1000ms 中显示 60 帧画面的单位时间,即 1000/60。如果系统每次渲染的时间都保持在 16ms 之内,那么我们看见的 UI 界面将是非常流畅的,但这也就需要将所有程序的逻辑都保证在 16ms 内。如果不能在 16ms 内完成绘制,那么就会造成丢帧现象,即当前该重绘的帧被未完成的逻辑阻塞,例如一次绘制任务耗时 20ms,那么在 16ms 系统发出 VSYNC 信号时就无法绘制,该帧就被丢弃,等待下次信号才开始绘制,导致 16*2ms 内都显示同一帧画面,这就是画面卡顿的原因。(228页)
4、在 Android 中,系统对 View 进行测量、布局和绘制时,都是通过对 View 树的遍历来进行操作。如果一个 View 树的高度太高,就会严重影响测量、布局和绘制的速度,因此优化布局的第一个办法就是降低 View 树的高度,Google 也在其 API 文档中建议 View 树的高度不宜超过 10 层。(229页)
5、在早期的 Android 版本中,Google 使用 LinearLayout 作为默认创建的 XML 文件的根布局,而现在版本的 Android 中,Google 已经使用 RelativeLayout 来替代 LinearLayout 作为默认的根布局,其原因就是通过扁平的 RelativeLayout 来降低通过 LinearLayout 嵌套所产生布局树的高度,从而提高 UI 渲染的效率。(229页)
6、在一个应用程序界面中,为了风格上的统一,很多界面都会存在一些共通的 UI。可以使用<include>标签来定义这样一个共通 UI。为了能够在不同的 Layout 组件中使用共通 UI,最好不要再共通 UI 中写太多只有某个特定 Layout 组件中才有的属性。(230页)
7、有一点需要注意,如果你需要在<include>标签中覆盖类似原布局中 android:layout_XXXXX 的属性,就必须在<include>标签中同时指定 android;layout_width 和 android:layout_height 属性。(231页)
8、可以使用<ViewStub>标签来实现对一个 View 的引用并实现延迟加载。<ViewStub>是一个非常轻量级的组件,它不仅不可视,而且大小为 0。(231页)
9、由于 Android 应用的沙箱机制,每个应用所分配的内存大小是有限度的,内存太低就会触发 LMK——Low Memory Killer 机制。通常情况下我们所说的内存是指手机的 RAM,它包括以下几个部分。(236页)

  • 寄存器(Registers):速度最快的存储场所,因为寄存器位于处理器内部,在程序中无法控制。
  • 栈(Stack):存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中。
  • 堆(Heap):堆内存用来存放由 new 创建的对象和数组。在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器(GC)来管理。
  • 静态存储区域(Static Field):静态存储区域就是指在固定的位置存放应用程序运行时一直存在的数据,Java 在内存中专门划分了一个静态存储区域来管理一些特殊的数据变量如静态的数据变量。
  • 常量池(Constant Pool):JVM 虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型、字段和方法的符号引用。

堆和栈的区分:当定义一个变量,Java 虚拟机就会在栈中为该变量分配内存空间,当该变量作用域结束后,这部分内存空间会马上被用作新的空间进行分配。如果使用 new 的方式创建一个变量,那么就会在堆中为这个对象分配内存空间,即使该对象的作用域结束,这部分内存也不会立即被回收,而是等待系统 GC 进行回收。堆的大小随着手机的不断发展而不断变大。
10、Java 对于 C、C++ 这类语言最大的优势就是不用手动管理系统资源,Java 创建了垃圾收集器线程(Garbage Collection Thread)来自动进行资源的管理。这样做的好处是大大降低了程序开发人员对内存管理的繁琐工作。但这也带来了很多问题,例如 Java 的 GC 是系统自动进行的,但何时进行却是开发者无法控制的,即使调用 System.gc() 方法,也只是建议系统进行 GC,但系统是否采纳你的建议,那就不一定了。JVM 虚拟机虽然能够自动控制 GC,但是再强大的算法,也难免会存在部分对象忘记回收的现象发生,这就是造成内存泄漏的原因。(238页)
11、Bitmap 是造成内存占用过高甚至是 OOM(Out Of Memory)的最大威胁。使用 Bitmap 的小技巧:(238页)

  • 使用适当分辨率和大小的图片:由于 Android 系统在做资源适配的时候会对不同分辨率文件夹下的图片进行缩放来适配相应的分辨率,如果图片分辨率与资源文件夹分辨率不匹配或者图片分辨率太高,就会导致系统消耗更多的内存资源。同时,在适当的时候,应该显示合适大小的图片。
  • 及时回收内存:一旦使用完 Bitmap 后,一定要及时使用 bitmap.recycle() 方法释放内存资源。自 Android 3.0 之后,由于 Bitmap 被放置到了堆中,其内存由 GC 管理,就不需要释放了。
  • 使用图片缓存:通过内存缓存(LruCache)和硬盘缓存(DiskLruCache)可以更好地使用 Bitmap。

12、任何 Java 类,都将占用大约 500 字节的内存空间。创建一个类的实例会消耗大约 15 字节的内存。(239页)
13、代码优化的技巧:(239页)

  • 对常量使用 static 修饰符。
  • 使用静态方法,静态方法会比普通方法提高 15% 左右的访问速度。
  • 减少不必要的成员变量,这点在 Android Lint 工具上已经集成检测了,如果一个变量可以定义为局部变量,则会建议你不要定义为成员变量。
  • 减少不必要的对象,使用基础类型会比使用对象更加节省资源,同时更应该避免频繁创建短作用域的变量。
  • 尽量不要使用枚举、少用迭代器。
  • 对 Cursor、Receiver、Sensor、File 等对象,要非常注意对它们的创建、回收与注册、解注册。
  • 避免使用 IOC 框架,IOC 通常使用注解。反射来进行实现,虽然现在 Java 对反射的效率已经进行了很好的优化,但大量使用反射依然会带来性能的下降。
  • 使用 RenderScript、OpenGL 来进行非常复杂的绘图操作。
  • 使用 SurfaceView 来替代 View 进行大量、频繁的绘图操作。
  • 尽量使用视图缓存,而不是每次都执行 inflate() 方法解析试图。

14、Android Lint 工具是 Android Studio 中集成的一个 Android 代码提示工具,它可以给你的布局、代码提供非常强大的帮助。应该养成在写完代码后检查 Lint 提示的习惯,这不仅可以让你及时发现代码中隐藏的一些问题,更能让你养成良好的代码风格。(240页)
15、Memory Monitor 工具是 Android Studio 自带的一个内存监视工具,它可以很好地帮助我们进行内存实时分析。(240页)
16、TraceView 是一个 Android 下的可视化性能调查工具,它用来分析 TraceView 日志。生成 TraceView 日志有两种方法,一个是利用 Debug 类帮助我们生成日志文件,另一个是利用 Android Device Monitor 工具辅助生成日志文件。(240页)
17、TraceView 提供了两种监听方式:(241页)

  • 整体监听:跟踪每个方法执行的全部过程,这种方式资源消耗较大。
  • 抽样监听:按照指定的频率来进行抽样调查,这种方式需要执行较长时间来获取较准确的样本数据。

18、TraceView 的分析界面分为两部分,上面是用于显示方法执行时间的时间轴区域,下面是显示详细信息的 profile 区域。时间轴区域显示了不同线程在不同的时间段内的执行情况,在时间轴中,每一行都代表了一个独立的线程。使用鼠标滚轮可以放大时间轴。Profile 区域内显示了你选择的色块所代表的方法在该色块所处的时间段内的性能分析。(242页)

第11章 搭建云端服务器

后端即服务——Backend as a Service,也叫 Baas。说白了,Baas 就是帮我们把服务器端的东西全部打包了,做移动端的人不用再考虑如何写服务器端、如何设计数据库、搭建服务器等,它把这一切都放在了云端,用户只需要调用 API 接口,就可以实现网络功能。(249页)

第12章 Android 5.X 新特性详解

1、材料的形态模拟是 Material Design 中最核心也是改变最大的一个设计,Google 通过模拟自然界纸墨的形态变化、光线与阴影、纸与纸之间的空间层级关系,带来一种真实的空间感。(258页)
2、Material Design 的一个很重要的特点就是拟物扁平化。通过展现生活中的材质效果、恰当地使用阴影和光线,配合完美的动画效果,模拟出一个动感十足又美丽大胆的视觉效果。(263页)
3、RecyclerView 是 support-v7 包中的新组件,是一个强大的滑动组件,与经典的 ListView 相比,它同样拥有 item 回收复用的功能,但是 RecyclerView 可以直接把 ViewHolder 的实现封装起来,用户只要实现自己的 ViewHolder 就可以了,该组件会自动帮你回收复用每一个 item。要使用 RecyclerView,首先需要在项目中引入 com.android.support:recyclerview-v7:21.0.2 的依赖。(269页)
4、CardView 是一个容器类布局,只是它提供了卡片这样一种形式。开发者可以定义卡片的大小与视图高度,并设置圆角的角度。(275页)
5、Android 5.X 为 Activity 的转场效果提供了三种 Transition 类型:(276页)

  • 进入:一个进入的过渡动画决定 Activity 中的所有视图怎么进入屏幕。
  • 退出:一个退出的过渡动画决定一个 Activity 中的所有视图怎么退出屏幕。
  • 共享元素:一个共享元素过渡动画决定两个 Activities 之间的过渡,怎么共享它们的视图。

6、Toolbar 与 Actionbar 最大的区别就是 Toolbar 更加自由、可控。这也是 Google 在逐渐使用 Toolbar 替换 Actionbar 的原因,要使用 Toolbar 必须引入 appcompat-v7 支持,并设置主题为 NoActionBar。(293页)
7、Notification 作为一个事件触发通知型的交互提示接口,让我们可以在获得消息的时候,在状态栏、锁屏界面得到相应的提示信息。当长按 Notification 的时候,会显示消息来源。Notification 会有一个从白色到灰色的动画切换效果,最终显示发出这个 Notification 的调用者。同时,在 Android 5.X 设备上,锁屏状态下我们也可以看见 Notification 通知。(296页)

持续更新中…