《第一行代码(第2版)》要点摘录

  1. 第1章 开始启程——你的第一行Android代码
  2. 第2章 先从看得到的入手——探究活动
  3. 第3章 软件也要拼脸蛋——UI开发的点点滴滴
  4. 第4章 手机平板要兼顾——探究碎片
  5. 第5章 全局大喇叭——详解广播机制
  6. 第6章 数据存储全方案——详解持久化技术
  7. 第7章 跨程序共享数据——探究内容提供器
  8. 第8章 丰富你的程序——运用手机多媒体
  9. 第9章 看看精彩的世界——使用网络技术
  10. 第10章 后台默默的劳动者——探究服务
  11. 第11章 Android特色开发——基于位置的服务
  12. 第12章 最佳的UI体验——Material Design实战
  13. 第13章 继续进阶——你还应该掌握的高级技巧
  14. 第14章 进入实战——开发酷欧天气
  15. 第15章 最后一步——将应用发布到360应用商店

第1章 开始启程——你的第一行Android代码

1、Android 系统四大组件:活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供器(Content Provider)。(4页)
2、项目中使用到的所有图片、布局、字符串等资源都存放在res目录下。其中图片放在drawable目录下,布局放在layout目录下,字符串放在values目录下。(19页)
3、AndroidMainfest.xml 是整个 Android 项目的配置文件,在程序中定义的所有四大组件都需要在这个文件里注册。(20页)
4、Activity 是 Android 系统提供的一个活动基类,项目中所有的活动都必须继承它或者它的子类才能拥有活动的特性。(21页)
5、Android 程序的设计讲究逻辑和视图分离,推荐在布局文件中编写界面,然后在活动中引入进来。(21页)
6、所有以drawable开头的文件夹都是用来放图片的,所有以mipmap开头的文件夹都是用来放应用图标的,所有以values开头的文件夹都是用来放字符串、样式、颜色等配置的,layout文件夹是用来放布局文件的。(22页)
7、如果美工只提供一份图片,就把所有图片都放在drawable-xxhdpi文件夹下就好了。(22页)
8、引用字符串app_name的方式:(22页)
(1)在代码中通过 R.string.app_name 可以获得该字符串的引用。
(2)在XML中通过 @string/app_name 可以获得该字符串的引用。
注:string 部分是可以替换的,如果是引用的图片资源就可以替换成 drawable,如果是引用的应用图标就可以替换成 mipmap,如果是引用的布局文件就可以替换成 layout。
9、通过 Android Studio 直接运行项目生成的都是测试版安装文件。(25页)
10、通常 Android Studio 项目一共有 3 种依赖方式:本地依赖、库依赖和远程依赖。(25页)

第2章 先从看得到的入手——探究活动

1、如果需要在XML中引用一个 id,使用 @id/id_name 这种语法;如果需要在 XML 中定义一个 id,则要使用 @+id/id_name 这种语法。(34页)
2、使用match_parent表示让当前元素和父元素一样宽,使用wrap_content表示当前元素的高度只要能刚好包含里面的内容就行。(34页)
3、AndroidMainfest.xml 中活动的注册声明要放在 <application> 标签内。(35页)
4、在启动器中点击应用的图标只会进入到该应用的主活动。(41页)
5、Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动活动、启动服务以及发送广播等场景。(43页)
6、Intent 大致可以分为两种:显式 Intent 和隐式 Intent。(43页)
7、每个 Intent 中只能指定一个 action,但却能指定多个 category。(45页)
8、Android 是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack)。(53页)
9、活动状态:运行状态、暂停状态、停止状态、销毁状态。(54页)
10、活动的生存期:(55页)

  • 完整生存期:onCreate() 方法和 onDestroy() 方法之间;
  • 可见生存期:onStart() 方法和 onStop() 方法之间;
  • 前台生存期:onResume() 方法和 onPause() 方法之间。

11、活动的启动模式:standard、singleTop、singleTask 和 singleInstance。(63页)

第3章 软件也要拼脸蛋——UI开发的点点滴滴

1、系统会对 Button 中的所有英文字母自动进行大写转换,如果想要保持小写,可以在 Button 的属性中加入代码:android:textAllCaps="false"。(81页)
2、Android 中 4 种基本布局:线性布局、相对布局、帧布局、百分比布局。(94页)
3、sp 是 Android 中字体大小的单位,dp 是 Android 中用于指定控件大小、间距等属性的单位。(98页)
4、当一个控件去引用另一个控件的 id 时,该控件一定要定义在引用控件的后面,不然会出现找不到 id 的情况。(103页)
5、ListView 的扩展性不够好,它只能实现数据纵向滚动的效果。(122页)
6、Nine-Patch 图片是一种被特殊处理过的 png 图片,能够指定哪些区域可以被拉伸,哪些区域不可以。(132页)
7、在 Android/sdk 目录下有一个 tools 文件夹,里面的 draw9patch.bat 文件就是用来制作 Nine-Patch 图片的。(133页)

第4章 手机平板要兼顾——探究碎片

1、碎片(Fragment)是一种可以嵌入在活动当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间。(142页)
2、碎片总是依附于活动而存在的。(152页)
3、Android 中一些常见的限定符:(158页)

屏幕特征 限定符 描述
大小 small 提供给小屏幕设备的资源
normal 提供给中等屏幕设备的资源
large 提供给大屏幕设备的资源
xlarge 提供给超大屏幕设备的资源
分辨率 ldpi 提供给低分辨率设备的资源(120dpi以下)
mdpi 提供给中等分辨率设备的资源(120dpi到160dpi)
hdpi 提供给高分辨率设备的资源(160dpi到240dpi)
xhdpi 提供给超高分辨率设备的资源(240dpi到320dpi)
xxhdpi 提供给超超高分辨率设备的资源(320dpi到480dpi)
方向 land 提供给横屏设备的资源
port 提供给竖屏设备的资源

第5章 全局大喇叭——详解广播机制

1、Android 中的广播主要可以分为两种类型:标准广播(Normal broadcasts)和有序广播(Orderd broadcasts)。(170页)
2、注册广播的方式一般有两种,在代码中注册和在 AndroidMainfest.xml 中注册,其中前者也被称为动态注册,后者也被称为静态注册。(171页)
3、当网络状态发生变化时,系统发出一条值为android.net.conn.CONNECTIVITY_CHANGE的广播。(172页)
4、动态注册的广播接收器一定都要取消注册才行。(173页)
5、Android 系统为了保护用户设备的安全和隐私,做了严格的规定:如果程序需要进行一些对用户来说比较敏感的操作,就必须在配置文件中声明权限才可以,否则程序将会直接崩溃。(173页)
6、广播接收器的Exported属性表示是否允许这个广播接收器接收本程序以外的广播,Enabled属性表示是否启用这个广播接收器。(175页)
7、静态的广播接收器一定要在 AndroidMainfest.xml 文件中注册才可以使用。(175页)
8、Android 系统启动完成后会发出一条值为android.intent.action.BOOT_COMPLETED的广播。(176页)
9、不要在 onReceive() 方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的,当 onReceive() 方法进行了较长时间而没有结束时,程序就会报错。(177页)
10、在 onReceive() 方法中调用 abortBroadcast() 方法,就表示将这条广播截断,后面的广播接收器将无法再接收到这条广播。(182页)
11、本地广播是无法通过静态注册的方式来接收的。(185页)

第6章 数据存储全方案——详解持久化技术

1、瞬时数据是指那些存储在内存当中,有可能会因为程序关闭或其他原因导致内存被回收而丢失的数据。(196页)
2、数据持久化就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失。(196页)
3、Android 系统主要提供了 3 种方式用于简单地实现数据持久化技术功能,即文件存储、SharedPreference 存储以及数据库存储。(196页)
4、文件存储不对存储的内容进行任何的格式化处理,所有数据都是原封不动地保存到文件当中,因而比较适合用于存储一些简单地文本数据或二进制数据。(197页)
5、Context 类中提供了一个openFileOutput()方法用于将数据存储到指定的文件中,提供了一个openFileInput()方法用于从文件中读取数据。(197页)
6、在对字符串进行非空判断时,使用TextUtils.isEmpty()方法可以一次性进行两种空值的判断。当传入的字符串等于 null 或者等于空字符串的时候,这个方法都会返回 true。(202页)
7、SharedPreferences 文件通过XML格式来对数据进行管理。(206页)
8、SQLiteOpenHelper 是一个抽象类,如果要使用它,需要创建一个自己的帮助类去继承它。(211页)
9、adb 是 Android SDK 中自带的一个调试工具,使用这个工具可以直接对连接在电脑上的手机或模拟器进行调试操作。(214页)
10、可以对数据进行的操作有 4 种,即 CRUD。其中 C 代表添加(Create),R 代表查询(Retrieve),U 代表更新(Update),D 代表删除(Delete)。添加数据时使用insert,查询数据时使用select,更新数据时使用update,删除数据时使用delete。(219页)
11、SQL 的全称是 Structured Query Language,翻译成中文是结构化查询语言。(225页)
12、LitePal 是一款开源的 Android 数据库框架,它采用了对象关系映射(ORM)的模式,将平时开发最常用到的一些数据库功能进行了封装,使得不用编写一行 SQL 语句就可以完成各种建表和增删改查的操作。(230页)
13、生成 getter 和 setter 方法的快捷方式是,先将类中的字段定义好,然后按下Alt+Insert键(Mac 系统是 command+N),在弹出菜单中选择 Getter and Setter,接着使用 Shift 键将所有字段都选中,最后点击 OK。(232页)
14、LitePal 进行表管理操作时不需要模型类有任何的继承结构,进行 CRUD 操作时必须要继承自 DataSupport 类才行。(236页)

第7章 跨程序共享数据——探究内容提供器

1、内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。(244页)
2、Android 将所有的权限归成了两类,一类是普通权限,一类是危险权限。普通权限指的是那些不会直接威胁到用户的安全和隐私的权限,对于这部分权限的申请,系统会自动帮我们授权,而不需要用户再去手动操作。危险权限则表示那些可能会触及用户隐私,或者对设备安全性造成影响的权限,对于这部分权限的申请,必须要由用户手动点击授权才可以,否则程序就无法使用相应的功能。(247页)
3、Android 中所有的危险权限一共是 9 组 24 个:(248页)

权限组名 权限名
CALENDAR READ_CALENDAR
WRITE_CALENDAR
CAMERA CAMERA
CONTACTS READ_CONTACTS
WRITE_CONTACTS
GET_CONTACTS
LOCATION ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE RECORD_AUDIO
PHONE READ_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORS BODY_SENSORS
SMS SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

4、表格中每个危险权限都属于一个权限组,在进行运行时权限处理时使用的是权限名,但是用户一旦同意授权,那么该权限所对应的权限组中所有的其他权限也会同时被授权。(248页)
5、内容提供器的用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序中的数据,另一种是创建自己的内容提供器给我们程序的数据提供外部访问接口。(254页)
6、如果一个应用程序通过内容提供器对其数据提供了外部访问接口,那么任何其他的应用程序就都可以对这部分数据进行访问。(254页)
7、不同于 SQLiteDatabase,ContentResolver 中的增删改查方法都是不接收表名参数的,而是使用一个 Uri 参数代替,这个参数被称为内容 URI。内容 URI 给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:authoritypath。authority 是用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式来进行命名。path 则是用于对同一应用程序中不同的表做区分的,通常都会添加到 authority 后面。(254页)
8、调用 Uri.parse() 方法,就可以将内容 URI 字符串解析成 Uri 对象。(255页)
9、标准的内容 URI 的写法:content://com.example.app.provider/table1,表示调用方期望访问的是 com.example.app 这个应用的 table1 表中的数据。在后面加上 id:content://com.example.app.provider/table1/1,表示调用方期望访问的是 com.example.app 这个应用的 table1 表中 id 为 1 的数据。(262页)
10、可以使用通配符的方式来分别匹配两种格式的内容 URI:(263页)

  • *:表示匹配任意长度的任意字符;
  • #:表示匹配任意长度的数字。

一个能够匹配任意表的内容 URI 格式可以写成:content://com.example.app.provider/*
一个能够匹配 table1 表中任意一行数据的内容 URI 格式可以写成:content://com.example.app.provider/table1/#
11、getType() 方法是所有的内容提供器都必须提供的一个方法,用于获取 Uri 对象所对应的 MIME 类型。(264页)
12、一个内容 URI 所对应的 MIME 字符串主要由 3 部分组成:(264页)

  • 必须以 vnd 开头。
  • 如果内容 URI 以路径结尾,则后接 android.cursor.dir/,如果内容 URI 以 id 结尾,则后接 android.cursor.item/。
  • 最后接上 vnd.<authority>.<path>。

13、内容提供器一定要在 AndroidManifest.xml 文件中注册才可以使用,注册所用标签是 <provider>。(270页)
14、Git 提供了一种可配性很强的机制来允许用户将指定的文件或目录排除在版本控制之外,它会检查代码仓库的目录下是否存在一个名为 .gitignore 的文件,如果存在的话,就去一行行读取这个文件中的内容,并把每一行指定的文件或目录排除在版本控制之外。(275页)
注意:.gitignore 中指定的文件或目录是可以使用 “*” 通配符的。

第8章 丰富你的程序——运用手机多媒体

1、当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,可以借助通知(Notification)来实现。(283页)
2、通知可以在活动里创建,也可以在广播接收器里创建,还可以在服务里创建。(283页)
3、PendingIntent 和 Intent 有些类似,可以用于启动活动、启动服务以及发送广播。不同的是,Intent 倾向于立即执行这个动作,而 PendingIntent 更加倾向于在某个合适的时机去执行某个动作。(286页)
4、在代码中没有对通知进行取消,它就会一直显示在系统的状态栏上。(288页)
5、在通知到来的时候让手机进行震动使用的是vibrate属性。它是一个长整型的数组,用于设置手机静止和震动的时长,以毫秒为单位。下标为 0 的值表示手机静止的时长,下标为 1 的值表示手机震动的时长,下标为 2 的值又表示手机静止的时长,以此类推。(290页)
6、setLight() 方法可以实现 LED 灯不停闪烁的效果。接收 3 个参数,第一个参数用于指定 LED 灯的颜色,第二个参数用于指定 LED 灯亮起的时长,以毫秒为单位,第三个参数用于指定 LED 灯暗去的时长,以毫秒为单位。(290页)
7、通过 BitmapFactory 的 decodeResource() 方法可以将图片解析成 Bitmap 对象。(292页)
8、应用关联缓存目录指专门用于存放当前应用缓存数据的位置。(296页)
9、在 Android 中播放音频文件一般都是使用 MediaPlayer 类来实现的。(303页)
10、MediaPlayer 的工作流程:
    首先需要创建一个 MediaPlayer 对象,然后调用 setDataSource() 方法来设置音频文件的路径,再调用 prepare() 方法使 MediaPlayer 进入到准备状态,接下来调用 start() 方法就可以开始播放音频,调用 pause() 方法就会暂停播放,调用 reset() 方法就会停止播放。(303页)
11、播放视频文件是使用 VideoView 类来实现的,这个类将视频的显示和控制集于一身。(307页)

第9章 看看精彩的世界——使用网络技术

1、HTTP 协议的工作原理:客户端向服务器发出一条 HTTP 请求,服务器收到请求之后会返回一些数据给客户端,然后客户端再对这些数据进行解析和处理就可以了。(314页)
2、当过多的内容在手机屏幕上无法完整显示时,借助 ScrollView 控件就可以以滚动的形式查看屏幕外的那部分内容。(316页)
3、Android 不允许在子线程中进行 UI 操作。(317页)
4、一般我们会在网络上传输一些格式化后的数据,这种数据会有一定的结构规格和语义,当另一方收到数据消息之后就可以按照相同的结构规格进行解析,从而取出他想要的那部分内容。(321页)
5、在网络上传输数据时最常用的格式有两种:XMLJSON。(321页)
6、解析XML格式的数据时常用的三种方式是Pull解析SAX解析DOM解析。(324页)
7、SAX 解析方式:
startDocument() 方法会在开始 XML 解析的时候调用,startElement() 方法会在开始解析某个节点的时候调用,characters() 方法会在获取节点中内容的时候调用,endElement() 方法会在完成解析某个节点的时候调用,endDocument() 方法会在完成整个 XML 解析的时候调用。(328页)
8、与 XML 相比,JSON 的主要优势在于它的体积更小,在网络上传输的时候可以更省流量。但缺点在于,它的语义性较差,看起来不如 XML 直观。(329页)
9、解析 JSON 数据可以使用官方提供的 JSONObject,也可以使用 Google 的开源库 GSON,第三方的开源库 Jackson、FastJSON 等也不错。(330页)

第10章 后台默默的劳动者——探究服务

1、服务(Service)是 Android 中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。(339页)
2、服务并不是运行在一个独立的进程当中,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。(339页)
3、服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞住的情况。(339页)
4、定义一个线程只需要新建一个类(MyThread)继承自 Thread,然后重写父类的 run() 方法,并在里面编写具体逻辑即可。启动这个线程只需要 new 出 MyThread 的实例,然后调用它的 start() 方法,这样 run() 方法中的代码就会在子线程当中运行了。(340页)
5、使用继承的方式耦合性有点高,更多的时候都会选择使用实现 Runnable 接口的方式来定义一个线程。(340页)
6、Android 提供了一套异步消息处理机制,完美地解决了在子线程中进行 UI 操作的问题。(343页)
7、Android 中的异步消息处理主要由 4 个部分组成:Message、Handler、MessageQueue 和 Looper。Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。Handler 是处理者的意思,主要用于发送和处理消息。发送消息一般是使用 Handler 的 sendMessage() 方法,而发出的消息经过一系列地辗转处理后,最终会传递到 Handler 的 handleMessage() 方法中。MessageQueue 是消息队列的意思,它主要用于存放所有通过 Handler 发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个 MessageQueue 对象。Looper 是每个线程中的 MessageQueue 的管家,调用 Looper 的 loop() 方法后,就会进入到一个无限循环当中,然后每当发现 MessageQueue 中存在一条消息,就会将它取出,并传递到 Handler 的 handleMessage() 方法中。每个线程中也只会有一个 Looper 对象。(345页)
8、异步消息处理的整个流程:首先需要在主线程当中创建一个 Handler 对象,并重写 handleMessage() 方法。然后当子线程中需要进行 UI 操作时,就创建一个 Message 对象,并通过 Handler 将这条消息发送出去。之后这条消息会被添加到 MessageQueue 的队列中等待被处理,而 Looper 则会一直尝试从 MessageQueue 中取出待处理消息,最后分发回 Handler 的 handlerMessage() 方法中。由于 Handler 是在主线程中创建的,所以此时 handleMessage() 方法中的代码也会在主线程中进行。(346页)
9、借助工具 AsyncTask 可以十分简单地从子线程切换到主线程。AsyncTask 是一个抽象类,如果想使用它,就必须创建一个子类去继承它。使用 AsyncTask 的诀窍是,在 doInBackground() 方法中执行具体的耗时任务,在 onProgressUpdate() 方法中进行 UI 操作,在 onPostExecute() 方法中执行一些任务的收尾工作。(349页)
10、onBind() 方法是 Service 中唯一的一个抽象方法,必须要在子类里实现。(350页)
11、onCreate()、onStartCommand() 和 onDestroy() 这 3 个方法是每个服务中最常用到的3个方法。onCreate() 方法会在服务创建的时候调用,onStartCommand() 方法会在每次服务启动的时候调用,onDestroy() 方法会在服务销毁的时候调用。(351页)
12、如果希望服务一旦启动就立刻去执行某个动作,就可以将逻辑写在 onStartCommand() 方法里。(351页)
13、每一个服务都需要在 AndroidManifest.xml 文件中进行注册才能生效。(351页)
14、虽然每调用一次 startService() 方法,onStartCommand() 就会执行一次,但实际上每个服务都只会存在一个实例。所以不管调用了多少次 startService() 方法,只需调用一次 stopService() 或 stopSelf() 方法,服务就会停止下来了。(359页)
15、对一个服务既调用了 startService() 方法,又调用了 bindService() 方法,要销毁服务时,要同时调用 stopService() 和 unbindService() 方法,onDestroy() 方法才会执行。(359页)
16、前台服务和普通服务最大的区别在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后就可以看到更加详细的信息,非常类似于通知的效果。(360页)
17、调用 startForeground() 方法后就会让 MyService 变成一个前台服务,并在系统状态栏显示出来。(361页)
18、为了可以简单地创建一个异步的、会自动停止的服务,Android 专门提供了一个 IntentService 类。(362页)

第11章 Android特色开发——基于位置的服务

1、基于位置的服务简称 LBS,主要的工作原理是利用无线电通讯网或 GPS 等定位方式来确定出移动设备所在的位置。(379页)
2、确定用户所在的位置通常有两种技术方式可以实现:一种是通过 GPS 定位,一种是通过网络定位。GPS 定位的工作原理是基于手机内置的 GPS 硬件直接和卫星交互来获取当前的经纬度信息,这种定位方式精确度非常高,但缺点是只能在室外使用,室内基本无法接收到卫星的信号。网络定位的工作原理是根据手机当前网络附近的三个基站进行测速,以此计算出手机和每个基站之间的距离,再通过三角定位确定出一个大概的位置,这种定位方式精确度一般,但优点是在室内室外都可以使用。(380页)
3、项目的 app 模块下面的 libs 目录是用来存放所有的 Jar 包的。(385页)
4、直接将 Jar 包复制到 libs 目录下,没有修改 gradle 文件,项目将无法引用到 Jar 包中提供的任何接口。需要手动点击一下 Android Studio 顶部工具栏的 Sync 按钮。(386页)
5、百度地图将缩放级别的取值范围限定在 3 到 19 之间,其中小数点位的值也是可以取的,值越大,地图显示的信息就越精细。(398页)
6、版本控制工具中分支的主要作用是在现有代码的基础上开辟一个分叉口,使得代码可以在主干线和分支线上同时进行开发,且相互之间不会影响。(403页)
7、查看当前的版本库当中有哪些分支,可以使用 git branch 这个命令。(403页)

第12章 最佳的UI体验——Material Design实战

1、Toolbar 的强大之处在于,它不仅继承了 ActionBar 的所有功能,而且灵活性很高,可以配合其他控件来完成一些 Material Design 的效果。(409页)
2、Toolbar 控件是由 appcompat-v7 库提供的。(411页)
3、给 activity 增加一个 android:label 属性,用于指定在 Toolbar 中显示的文字内容,如果没有指定的话,会默认使用 application 中指定的 label 内容,也就是应用名称。(413页)
4、标签 <item> 中的 android:showAsAction 属性用来指定按钮的显示位置。showAsAction 主要有以下几种值可选:always表示永远显示在 Toolbar 中,如果屏幕空间不够则不显示;ifRoom表示屏幕空间足够的情况下显示在 Toolbar 中,不够的话就显示在菜单当中;never则表示永远显示在菜单当中。Toolbar 中的 antion 按钮只会显示图标,菜单中的 antion 按钮只会显示文字。(413页)
5、滑动菜单是将一些菜单选项隐藏起来,而不是放置在主屏幕上,然后可以通过滑动的方式将菜单显示出来。这种方式既节省了屏幕空间,又实现了非常好的动画效果,是 Material Design 中推荐的做法。(415页)
6、Toolbar 最左侧的导航按钮叫作 HomeAsUp 按钮,id 永远都是 android.R.id.home。(418页)
7、开源项目 CircleImageView 可以用来轻松实现图片圆形化的功能,项目主页地址:https://github.com/hdodenhof/CircleImageView 。(419页)
8、CardView 是用于实现卡片式布局效果的重要控件,由 appcompat-v7 库提供。(431页)
9、Glide 是一个超级强大的图片加载库,它不仅可以用于加载本地图片,还可以加载网络图片、GIF 图片、甚至是本地视频。Glide 的项目主页地址:https://github.com/bumptech/glide 。(432页)
10、ImageView 中的 scaleType 属性可以指定图片的缩放模式。(434页)
11、SwipeRefreshLayout 是用于实现下拉刷新功能的核心类,它是由 support-v4 库提供的。(440页)
12、想要让背景图能够和系统状态栏融合,需要借助 android:fitsSystemWindows 这个属性来实现。(453页)

第13章 继续进阶——你还应该掌握的高级技巧

1、Android 提供了一个 Application 类,每当应用程序启动的时候,系统就会自动将这个类进行初始化。(459页)
2、任何一个项目都只能配置一个 Application,否则会冲突。(460页)
3、使用 Intent 来传递对象通常有两种方式:SerializableParcelable。(461页)
4、Serializable 是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。(462页)
5、Parcelable 方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是 Intent 所支持的数据类型,这样就实现了传递对象的功能。(463页)
6、当开发过程中遇到一些奇怪的 bug,但又迟迟定位不出来原因的时候,最好的解决办法就是调试。调试允许逐行地执行代码,并可以实时观察内存中的数据,从而能够比较轻易地查出问题的原因。(466页)
7、调试工作的第一步是添加断点。添加断点的方法是在相应代码行的左边点击一下就可以了。如果想要取消这个断点,对着它再次点击就可以了。(466页)
8、Android 中的定时任务一般有两种实现方式,一种是使用 Java API 里提供的 Timer 类,一种是使用 Android 的 Alarm 机制。Timer 有一个明显的短板,它并不太适用于那些需要长期在后台运行的定时任务。(469页)
9、为了能让电池更加耐用,每种手机都会有自己的休眠策略,Android 手机就会在长时间不操作的情况下自动让 CPU 进入到睡眠状态,这就有可能导致 Timer 中的定时任务无法正常运行。而 Alarm 则具有唤醒 CPU 的功能,它可以保证在大多数情况下需要执行定时任务的时候 CPU 都能正常工作。(469页)
10、使用 SystemClock.elapsedRealtime() 方法可以获取到系统开机至今所经历时间的毫秒数,使用 System.currentTimeMillis() 方法可以获取到 1970 年 1 月 1 日 0 点至今所经历时间的毫秒数。(469页)
11、从 Android4.4 系统开始,Alarm 任务的触发时间将会变得不准确,有可能会延迟一段时间后任务才能得到执行。这并不是个 bug,而是系统在耗电性方面进行的优化。系统会自动检测目前有多少 Alarm 任务存在,然后将触发时间相近的几个任务放在一起执行,这就可以大幅度地减少 CPU 被唤醒的次数,从而有效延长电池的使用时间。(471页)
12、当用户的设备是 Android6.0 或以上系统时,如果该设备未插接电源,处于静止状态(Android7.0 中删除了这一条件),且屏幕关闭了一段时间之后,就会进入到 Doze 模式。在 Doze 模式下,系统会对 CPU、网络、Alarm 等活动进行限制,从而延长了电池的使用寿命。当然,系统并不会一直处于 Doze 模式,而是会间歇性地退出 Doze 模式一小段时间,在这段时间中,应用就可以去完成它们的同步操作、Alarm 任务等。(471页)
13、在 Doze 模式下下列功能会受到限制:(472页)

  • 网络访问被禁止
  • 系统忽略唤醒 CPU 或者屏幕操作
  • 系统不再执行 WIFI 扫描
  • 系统不再执行同步服务
  • Alarm 任务将会在下次退出 Doze 模式的时候执行

14、手机导航栏右边的 Overview 按钮的作用是打开一个最近访问过的活动或任务的列表界面,从而能够方便地在多个应用程序之间进行切换。(473页)
15、通过以下两种方式可以进入多窗口模式:(473页)

  • 在 Overview 列表界面长按任意一个活动的标题,将该活动拖动到屏幕突出显示的区域,则可以进入多窗口模式。
  • 打开任意一个程序,长按 Overview 按钮,也可以进入多窗口模式。

16、多窗口模式并不会改变活动原有的生命周期,只是会将用户最近交互过的那个活动设置为运行状态,而将多窗口模式下另外一个可见的活动设置暂停状态。如果这时用户又去和暂停的活动进行交互,那么该活动就变成运行状态,之前处于运行状态的活动变成暂停状态。(475页)
17、禁用多窗口模式的方法是在 AndroidManifest.xml 的 <appaication> 或 <activity> 标签中加入如下属性:android:resizeableActivity=["true"|"false"]。其中,true 表示应用支持多窗口模式,false 表示应用不支持多窗口模式,如果不配置这个属性,那么默认值为 true。(479页)
18、默认情况下,应用都是可以随着手机的旋转自由地横竖屏切换的,如果想要让应用不允许横竖屏切换,那么需要在 AndroidManifest.xml 的 activity 标签中加入如下配置:android:screenOrientation=["portrait"|"landscape"]。其中,portrait 表示活动只允许竖屏,landscape 表示活动只支持横屏。(481页)
19、Lambda 表达式本质上是一种匿名方法,它既没有方法名,也没有访问修饰符和返回值类型,使用它来编写代码会更加简洁,也更加易读。(481页)
20、凡是只有一个待实现方法的接口,都可以使用 Lambda 表达式的写法。(482页)

第14章 进入实战——开发酷欧天气

1、LitePal 中的每一个实体类都是必须要继承自 DataSupport 类的。(496页)
2、碎片中最好不要直接使用 ActionBar 或 ToolBar,不然在复用的时候可能会有一些意料之外的效果。(502页)
3、JSON 中的一些字段不太适合直接作为 Java 字段来命名,使用 @SerializedName 注解的方式可以让 JSON 字段和 Java 字段之间建立映射关系。(510页)
4、ScrollView 的内部只允许存在一个直接子布局。(520页)
5、instanceof 关键字可以用来判断一个对象是否属于某个类的实例。(538页)

第15章 最后一步——将应用发布到360应用商店

1、通过 Android Studio 将程序安装到手机上背后实际的工作流程是,Android Studio 会将程序代码打包成一个 APK 文件,然后将这个文件传输到手机上,最后再执行安装操作。Android 系统会将所有的 APK 的文件识别为应用程序的安装包。(545页)
2、并不是所有的 APK 文件都能成功安装到手机上,Android 系统要求只有签名后的 APK 文件才可以安装。(545页)
3、Gradle 是一个非常先进的项目构建工具,在 Android Studio 中开发的所有项目都是使用它来构建的。(548页)
4、Gradle 中的配置规定不能以数字开头。(552页)